Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
21 changes: 21 additions & 0 deletions src/admin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Menus } from './resources/project/admin'

import type { Blutui } from './blutui'
import type { Project } from './project'
import { Request } from './utils/request'

export class Admin extends Request {
readonly menus = new Menus(this)

constructor(
private readonly project: Project,
blutui: Blutui
) {
super(blutui)
}

protected getRequestPath(path: string): string {
const newPath = path.startsWith('/') ? path.replace('/', '') : path
return `https://${this.project.handle}.blutui.com/admin/api/${newPath}`
}
}
44 changes: 6 additions & 38 deletions src/agency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import {
} from './resources/agency'

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

export class Agency {
import { Request } from './utils/request'

export class Agency extends Request {
readonly brand = new Brand(this)
readonly cassettes = new Cassettes(this)
readonly domains = new Domains(this)
Expand All @@ -22,45 +23,12 @@ export class Agency {

constructor(
public username: string,
private readonly blutui: Blutui
) {}

async get<Result>(path: string, options: GetOptions = {}) {
return await this.blutui.get<Result>(this.getAgencyPath(path), options)
}

async post<Result, Entity>(
path: string,
entity: Entity,
options: PostOptions = {}
blutui: Blutui
) {
return await this.blutui.post<Result, Entity>(
this.getAgencyPath(path),
entity,
options
)
}

async patch<Result, Entity>(
path: string,
entity: Entity,
options: PostOptions = {}
) {
return await this.blutui.patch<Result, Entity>(
this.getAgencyPath(path),
entity,
options
)
}

async delete<Result>(path: string, options: PostOptions = {}) {
return await this.blutui.delete<Result>(this.getAgencyPath(path), options)
super(blutui)
}

/**
* Get the path for the current agency.
*/
private getAgencyPath(path: string): string {
protected getRequestPath(path: string): string {
const newPath = path.startsWith('/') ? path.replace('/', '') : path

return `/agencies/${this.username}/${newPath}`
Expand Down
15 changes: 15 additions & 0 deletions src/blutui.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Agency } from './agency'
import { Project } from './project'
import {
FetchException,
GenericServerException,
Expand Down Expand Up @@ -29,6 +30,7 @@ export class Blutui {
readonly baseURL: string
private readonly client: Client
private readonly _agencies: Record<string, Agency> = {}
private readonly _projects: Record<string, Project> = {}

readonly agencies = new Agencies(this)
readonly user = new User(this)
Expand Down Expand Up @@ -85,6 +87,19 @@ export class Blutui {
return this._agencies[username]
}

/**
* Get a Blutui Project instance for the given handle.
*
* @param handle - The project's handle. If the project's handle is different from its subdomain, the subdomain should be used instead.
*/
project(handle: string): Project {
if (!this._projects[handle]) {
this._projects[handle] = new Project(handle, this)
}

return this._projects[handle]
}

async get<Result>(
path: string,
options: GetOptions = {}
Expand Down
24 changes: 24 additions & 0 deletions src/project.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Menus } from './resources/project'

import type { Blutui } from './blutui'
import { Admin } from './admin'
import { Request } from './utils/request'

export class Project extends Request {
readonly admin: Admin
readonly menus = new Menus(this)

constructor(
public handle: string,
blutui: Blutui
) {
super(blutui)
this.admin = new Admin(this, blutui)
}

protected getRequestPath(path: string): string {
const newPath = path.startsWith('/') ? path.replace('/', '') : path

return `https://${this.handle}.blutui.com/api/${newPath}`
}
}
1 change: 1 addition & 0 deletions src/resources/project/admin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Menus } from './menus/menus.admin'
1 change: 1 addition & 0 deletions src/resources/project/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Menus } from './menus/menus'
21 changes: 21 additions & 0 deletions src/resources/project/menus/fixtures/menu-list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"object": "list",
"data": [
{
"id": "9bfdb42b-1bf0-4510-978e-46aa329f8efa",
"object": "menu",
"name": "Primary Menu",
"created_at": 1716170007,
"updated_at": 1716170007
}
],
"meta": {
"hasMore": false,
"currentPage": 1,
"from": 1,
"to": 1,
"perPage": 10,
"total": 1,
"lastPage": 1
}
}
18 changes: 18 additions & 0 deletions src/resources/project/menus/fixtures/menu-with-items.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"id": "9bfdb42b-1bf0-4510-978e-46aa329f8efa",
"object": "menu",
"name": "Primary Menu",
"items": [{
"id": "99bc147e-966c-4dd0-8def-de817c63cf41",
"object": "menu_item",
"label": "Contact",
"url": "/contact",
"active": true,
"is_new_tab": false,
"order": 1,
"created_at": 1720758022,
"updated_at": 1720758046
}],
"created_at": 1716170007,
"updated_at": 1716170007
}
7 changes: 7 additions & 0 deletions src/resources/project/menus/fixtures/menu.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"id": "9bfdb42b-1bf0-4510-978e-46aa329f8efa",
"object": "menu",
"name": "Primary Menu",
"created_at": 1716170007,
"updated_at": 1716170007
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export interface CreateMenuOptions {
handle: string
name: string
items?: CreateMenuItemOptions[]
}

export interface CreateMenuItemOptions {
label: string
url: string
isNewTab: boolean
active: boolean
items?: CreateMenuItemOptions[]
}

export interface SerializedCreateMenuOptions {
handle: string
name: string
items?: SerializedCreateMenuItemOptions[]
}

export interface SerializedCreateMenuItemOptions {
label: string
url: string
is_new_tab: boolean
active: boolean
items?: SerializedCreateMenuItemOptions[]
}
3 changes: 3 additions & 0 deletions src/resources/project/menus/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './menu.interface'
export * from './create-menu-options.interface'
export * from './update-menu-options.interface'
43 changes: 43 additions & 0 deletions src/resources/project/menus/interfaces/menu.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export interface Menu {
id: string
object: 'menu'
name: string
items?: MenuItem[]
createdAt: number
updatedAt: number
}

export interface MenuResponse {
id: string
object: 'menu'
name: string
items?: MenuItemResponse[]
created_at: number
updated_at: number
}

export interface MenuItem {
id: string
object: 'menu_item'
label: string
url: string
active: boolean
isNewTab: boolean
order: number
items?: MenuItem[]
createdAt: number
updatedAt: number
}

export interface MenuItemResponse {
id: string
object: 'menu_item'
label: string
url: string
active: boolean
is_new_tab: boolean
order: number
items?: MenuItemResponse[]
created_at: number
updated_at: number
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export interface UpdateMenuOptions {
handle?: string
name?: string
items?: UpdateMenuItemOptions[]
}

export interface UpdateMenuItemOptions {
label: string
url: string
isNewTab: boolean
active: boolean
items?: UpdateMenuItemOptions[]
}

export interface SerializedUpdateMenuOptions {
handle?: string
name?: string
items?: SerializedUpdateMenuItemOptions[]
}

export interface SerializedUpdateMenuItemOptions {
label: string
url: string
is_new_tab: boolean
active: boolean
items?: SerializedUpdateMenuItemOptions[]
}
Loading