Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# See GitHub's docs for more details:
# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners

# TypeScript Team
* @blutui/typescript
10 changes: 9 additions & 1 deletion src/agency.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { Brand, Domains, Members, Projects, Roles } from './resources/agency'
import {
Brand,
Domains,
Invites,
Members,
Projects,
Roles,
} from './resources/agency'

import type { Blutui } from './blutui'
import type { GetOptions, PostOptions } from './types'

export class Agency {
readonly brand = new Brand(this)
readonly domains = new Domains(this)
readonly invites = new Invites(this)
readonly members = new Members(this)
readonly projects = new Projects(this)
readonly roles = new Roles(this)
Expand Down
1 change: 1 addition & 0 deletions src/resources/agency/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { Brand } from './brand/brand'
export { Domains } from './domains/domains'
export { Invites } from './invites/invites'
export { Members } from './members/members'
export { Projects } from './projects/projects'
export { Roles } from './roles/roles'
30 changes: 30 additions & 0 deletions src/resources/agency/invites/fixtures/invite-list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"object": "list",
"data": [
{
"id": "9cf6c82a-a457-4787-8aad-81ce8ddf3235",
"object": "invite",
"email": "mara@blutui.dev",
"role": {
"id": 3,
"object": "role",
"name": "Developer",
"description": "The frontend developer role",
"is_super": false,
"created_at": 1690330767,
"updated_at": 1721869652
},
"created_at": 1725837341,
"updated_at": 1725917399
}
],
"meta": {
"hasMore": false,
"currentPage": 1,
"from": 1,
"to": 1,
"perPage": 10,
"total": 1,
"lastPage": 1
}
}
16 changes: 16 additions & 0 deletions src/resources/agency/invites/fixtures/invite.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"id": "9cf6c82a-a457-4787-8aad-81ce8ddf3235",
"object": "invite",
"email": "mara@blutui.dev",
"role": {
"id": 3,
"object": "role",
"name": "Developer",
"description": "The frontend developer role",
"is_super": false,
"created_at": 1690330767,
"updated_at": 1721869652
},
"created_at": 1725837341,
"updated_at": 1725917399
}
2 changes: 2 additions & 0 deletions src/resources/agency/invites/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './invite.interface'
export * from './update-invite-options.interface'
19 changes: 19 additions & 0 deletions src/resources/agency/invites/interfaces/invite.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Role, RoleResponse } from '../../roles/interfaces'

export interface Invite {
id: string
object: 'invite'
email: string
role: number | Role
createdAt: number
updatedAt: number
}

export interface InviteResponse {
id: string
object: 'invite'
email: string
role: number | RoleResponse
created_at: number
updated_at: number
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface UpdateInviteOptions {
role: number
}

export interface SerializedUpdateInviteOptions {
role: number
}
71 changes: 71 additions & 0 deletions src/resources/agency/invites/invites.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import fetch from 'jest-fetch-mock'
import { Blutui } from '@/blutui'
import { fetchOnce, fetchURL } from '@/utils/testing'

import inviteFixture from './fixtures/invite.json'
import inviteListFixture from './fixtures/invite-list.json'

const accessToken =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
const blutui = new Blutui(accessToken)

describe('Invite', () => {
beforeEach(() => fetch.resetMocks())

describe('list', () => {
it('can retrieve a list of invites', async () => {
fetchOnce(inviteListFixture)
const invites = await blutui.agency('foo').invites.list()

expect(fetchURL()).toBe(`${blutui.baseURL}/v1/agencies/foo/invites`)
expect(invites).toMatchObject({
object: 'list',
})
})

it('can retrieve a list of invites with an expanded role', async () => {
fetchOnce(inviteListFixture)
const invites = await blutui
.agency('foo')
.invites.list({ expand: ['role'] })

expect(fetchURL()).toBe(
encodeURI(`${blutui.baseURL}/v1/agencies/foo/invites?expand[]=role`)
)

expect(invites).toMatchObject({
object: 'list',
})
expect(invites.data[0].role).toMatchObject({
object: 'role',
})
})
})

describe('update', () => {
it('can update an agency invite', async () => {
fetchOnce(inviteFixture)
const invite = await blutui
.agency('foo')
.invites.update(inviteFixture.id, { role: 3 })

expect(fetchURL()).toBe(
`${blutui.baseURL}/v1/agencies/foo/invites/${inviteFixture.id}`
)
expect(invite).toMatchObject({
object: 'invite',
})
})
})

describe('remove', () => {
it('can remove an invite', async () => {
fetchOnce(inviteFixture)
await blutui.agency('foo').invites.remove(inviteFixture.id)

expect(fetchURL()).toBe(
`${blutui.baseURL}/v1/agencies/foo/invites/${inviteFixture.id}`
)
})
})
})
61 changes: 61 additions & 0 deletions src/resources/agency/invites/invites.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {
deserializeInvite,
deserializeInviteList,
serializeUpdateInviteOptions,
} from './serializers'

import type { Agency } from '@/agency'
import type {
Invite,
InviteResponse,
SerializedUpdateInviteOptions,
UpdateInviteOptions,
} from './interfaces'
import type {
DeletedResponse,
Expandable,
List,
ListResponse,
PaginationOptions,
} from '@/types'

export class Invites {
constructor(private readonly agency: Agency) {}

/**
* Get a list of invites for the current agency.
*/
async list(
options?: PaginationOptions & Expandable<'role'>
): Promise<List<Invite>> {
const { data } = await this.agency.get<ListResponse<InviteResponse>>(
'invites',
{
query: options,
}
)

return deserializeInviteList(data)
}

/**
* Update a invite in the current agency.
*/
async update(id: string, payload: UpdateInviteOptions): Promise<Invite> {
const { data } = await this.agency.patch<
InviteResponse,
SerializedUpdateInviteOptions
>(`invites/${id}`, serializeUpdateInviteOptions(payload))

return deserializeInvite(data)
}

/**
* Remove a invite from the current agency.
*/
async remove(id: string): Promise<DeletedResponse> {
const { data } = await this.agency.delete<DeletedResponse>(`invites/${id}`)

return data
}
}
2 changes: 2 additions & 0 deletions src/resources/agency/invites/serializers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './invite.serializer'
export * from './update-invite-options.serializer'
23 changes: 23 additions & 0 deletions src/resources/agency/invites/serializers/invite.serializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { deserializePaginationMeta } from '@/utils/serializers'
import { deserializeRole } from '../../roles/serializers'

import type { List, ListResponse } from '@/types'
import type { Invite, InviteResponse } from '../interfaces'

export const deserializeInvite = (invite: InviteResponse): Invite => ({
id: invite.id,
object: invite.object,
email: invite.email,
role:
invite.role instanceof Object ? deserializeRole(invite.role) : invite.role,
createdAt: invite.created_at,
updatedAt: invite.updated_at,
})

export const deserializeInviteList = (
invites: ListResponse<InviteResponse>
): List<Invite> => ({
object: 'list',
data: invites.data.map(deserializeInvite),
meta: deserializePaginationMeta(invites.meta),
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type {
SerializedUpdateInviteOptions,
UpdateInviteOptions,
} from '../interfaces'

export const serializeUpdateInviteOptions = (
options: UpdateInviteOptions
): SerializedUpdateInviteOptions => ({
role: options.role,
})
2 changes: 1 addition & 1 deletion src/resources/agency/roles/roles.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ describe('Role', () => {
})

describe('remove', () => {
it('can remove an role', async () => {
it('can remove a role', async () => {
fetchOnce(roleFixture)
await blutui.agency('foo').roles.remove(roleFixture.id)

Expand Down