-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #431 from VK-RED/feat/openapi-for-shares
feat: openapi for shares endpoint
- Loading branch information
Showing
23 changed files
with
987 additions
and
31 deletions.
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
prisma/migrations/20240721090639_default_share_legends/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
-- AlterTable | ||
ALTER TABLE "Share" ALTER COLUMN "companyLegends" SET DEFAULT ARRAY[]::"ShareLegendsEnum"[]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,16 @@ | ||
import { PublicAPI } from "./hono"; | ||
import { initMiddleware } from "./middlewares/init"; | ||
import { registerCompanyRoutes } from "./routes/company"; | ||
import registerStakeholderRoutes from "./routes/company/stakeholder"; | ||
import { registerShareRoutes } from "./routes/company/share"; | ||
import { registerStakeholderRoutes } from "./routes/company/stakeholder"; | ||
|
||
const api = PublicAPI(); | ||
|
||
api.use("*", initMiddleware()); | ||
|
||
// RESTful routes for company | ||
// Register RESTful routes | ||
registerCompanyRoutes(api); | ||
|
||
// RESTful routes for a stakeholder in a company | ||
registerShareRoutes(api); | ||
registerStakeholderRoutes(api); | ||
|
||
export default api; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import { withCompanyAuth } from "@/server/api/auth"; | ||
import { ApiError, ErrorResponses } from "@/server/api/error"; | ||
import type { PublicAPI } from "@/server/api/hono"; | ||
import { CreateShareSchema } from "@/server/api/schema/shares"; | ||
import { getHonoUserAgent, getIp } from "@/server/api/utils"; | ||
import { addShare } from "@/server/services/shares/add-share"; | ||
import { createRoute, z } from "@hono/zod-openapi"; | ||
import type { Context } from "hono"; | ||
|
||
const ParamsSchema = z.object({ | ||
id: z | ||
.string() | ||
.cuid() | ||
.openapi({ | ||
description: "Company ID", | ||
param: { | ||
name: "id", | ||
in: "path", | ||
}, | ||
|
||
example: "clycjihpy0002c5fzcyf4gjjc", | ||
}), | ||
}); | ||
|
||
const ResponseSchema = z.object({ | ||
message: z.string(), | ||
data: CreateShareSchema, | ||
}); | ||
|
||
const route = createRoute({ | ||
method: "post", | ||
path: "/v1/companies/{id}/shares", | ||
summary: "Issue shares", | ||
description: "Issue shares to a stakeholder in a company.", | ||
tags: ["Shares"], | ||
request: { | ||
params: ParamsSchema, | ||
body: { | ||
content: { | ||
"application/json": { | ||
schema: CreateShareSchema, | ||
}, | ||
}, | ||
}, | ||
}, | ||
responses: { | ||
200: { | ||
content: { | ||
"application/json": { | ||
schema: ResponseSchema, | ||
}, | ||
}, | ||
description: "Issue shares", | ||
}, | ||
...ErrorResponses, | ||
}, | ||
}); | ||
|
||
const create = (app: PublicAPI) => { | ||
app.openapi(route, async (c: Context) => { | ||
const { company, member, user } = await withCompanyAuth(c); | ||
const body = await c.req.json(); | ||
|
||
const { success, message, data } = await addShare({ | ||
...body, | ||
companyId: company.id, | ||
memberId: member.id, | ||
requestIP: getIp(c.req), | ||
userAgent: getHonoUserAgent(c.req), | ||
user: { | ||
id: user.id, | ||
name: user.name, | ||
}, | ||
}); | ||
|
||
if (!success || !data) { | ||
throw new ApiError({ | ||
code: "INTERNAL_SERVER_ERROR", | ||
message: "Something went wrong, please try again or contact support.", | ||
}); | ||
} | ||
|
||
// Ensure data matches ResponseSchema | ||
const responseData = { | ||
status: data.status as string, // Cast to string if necessary | ||
certificateId: data.certificateId, | ||
quantity: data.quantity, | ||
pricePerShare: data.pricePerShare ?? 0, | ||
capitalContribution: data.capitalContribution ?? 0, | ||
ipContribution: data.ipContribution ?? 0, | ||
debtCancelled: data.debtCancelled ?? 0, | ||
otherContributions: data.otherContributions ?? 0, | ||
vestingSchedule: data.vestingSchedule ?? "", | ||
companyLegends: data.companyLegends ?? "", // Add missing fields | ||
issueDate: data.issueDate ?? new Date().toISOString(), // Add missing fields | ||
rule144Date: data.rule144Date ?? new Date().toISOString(), // Add missing fields | ||
vestingStartDate: data.vestingStartDate ?? new Date().toISOString(), // Add missing fields | ||
boardApprovalDate: data.boardApprovalDate ?? new Date().toISOString(), // Add boardApprovalDate | ||
stakeholderId: data.stakeholderId ?? "", // Add stakeholderId | ||
shareClassId: data.shareClassId, | ||
}; | ||
|
||
return c.json({ message, data: responseData }, 200); | ||
}); | ||
}; | ||
|
||
export default create; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { withCompanyAuth } from "@/server/api/auth"; | ||
import { | ||
ApiError, | ||
type ErrorCodeType, | ||
ErrorResponses, | ||
} from "@/server/api/error"; | ||
import type { PublicAPI } from "@/server/api/hono"; | ||
import { getHonoUserAgent, getIp } from "@/server/api/utils"; | ||
import { deleteShare } from "@/server/services/shares/delete-share"; | ||
import { createRoute, z } from "@hono/zod-openapi"; | ||
import type { Context } from "hono"; | ||
import { RequestParamsSchema } from "./update"; | ||
|
||
const ResponseSchema = z | ||
.object({ | ||
message: z.string(), | ||
}) | ||
.openapi({ | ||
description: "Delete a Share by ID", | ||
}); | ||
|
||
const route = createRoute({ | ||
method: "delete", | ||
path: "/v1/companies/{id}/shares/{shareId}", | ||
summary: "Delete issued shares", | ||
description: "Delete a Share by ID", | ||
tags: ["Shares"], | ||
request: { | ||
params: RequestParamsSchema, | ||
}, | ||
responses: { | ||
200: { | ||
content: { | ||
"application/json": { | ||
schema: ResponseSchema, | ||
}, | ||
}, | ||
description: "Delete a Share by ID", | ||
}, | ||
...ErrorResponses, | ||
}, | ||
}); | ||
|
||
const deleteOne = (app: PublicAPI) => { | ||
app.openapi(route, async (c: Context) => { | ||
const { company, user } = await withCompanyAuth(c); | ||
const { shareId: id } = c.req.param(); | ||
|
||
const { success, code, message } = await deleteShare({ | ||
companyId: company.id, | ||
requestIp: getIp(c.req), | ||
userAgent: getHonoUserAgent(c.req), | ||
shareId: id as string, | ||
user: { id: user.id, name: user.name || "" }, | ||
}); | ||
|
||
if (!success) { | ||
throw new ApiError({ | ||
code: code as ErrorCodeType, | ||
message, | ||
}); | ||
} | ||
|
||
return c.json( | ||
{ | ||
message: message, | ||
}, | ||
200, | ||
); | ||
}); | ||
}; | ||
|
||
export default deleteOne; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { withCompanyAuth } from "@/server/api/auth"; | ||
import { ErrorResponses } from "@/server/api/error"; | ||
import type { PublicAPI } from "@/server/api/hono"; | ||
import { | ||
DEFAULT_PAGINATION_LIMIT, | ||
PaginationQuerySchema, | ||
PaginationResponseSchema, | ||
} from "@/server/api/schema/pagination"; | ||
import { ShareSchema } from "@/server/api/schema/shares"; | ||
import { getPaginatedShares } from "@/server/services/shares/get-shares"; | ||
import { createRoute, z } from "@hono/zod-openapi"; | ||
import type { Context } from "hono"; | ||
|
||
const ParamsSchema = z.object({ | ||
id: z | ||
.string() | ||
.cuid() | ||
.openapi({ | ||
description: "Company ID", | ||
param: { | ||
name: "id", | ||
in: "path", | ||
}, | ||
|
||
example: "clxwbok580000i7nge8nm1ry0", | ||
}), | ||
}); | ||
|
||
const ResponseSchema = z | ||
.object({ | ||
data: z.array(ShareSchema), | ||
meta: PaginationResponseSchema, | ||
}) | ||
.openapi({ | ||
description: "Get Shares by Company ID", | ||
}); | ||
|
||
const route = createRoute({ | ||
method: "get", | ||
path: "/v1/companies/{id}/shares", | ||
summary: "Get list of issued shares", | ||
description: "Get list of issued shares for a company", | ||
tags: ["Shares"], | ||
request: { | ||
params: ParamsSchema, | ||
query: PaginationQuerySchema, | ||
}, | ||
responses: { | ||
200: { | ||
content: { | ||
"application/json": { | ||
schema: ResponseSchema, | ||
}, | ||
}, | ||
description: "Retrieve the shares for the company", | ||
}, | ||
...ErrorResponses, | ||
}, | ||
}); | ||
|
||
const getMany = (app: PublicAPI) => { | ||
app.openapi(route, async (c: Context) => { | ||
const { company } = await withCompanyAuth(c); | ||
|
||
const { take, cursor, total } = c.req.query(); | ||
|
||
const { data, meta } = await getPaginatedShares({ | ||
companyId: company.id, | ||
take: Number(take || DEFAULT_PAGINATION_LIMIT), | ||
cursor, | ||
total: Number(total), | ||
}); | ||
|
||
return c.json( | ||
{ | ||
data, | ||
meta, | ||
}, | ||
200, | ||
); | ||
}); | ||
}; | ||
|
||
export default getMany; |
Oops, something went wrong.