-
Notifications
You must be signed in to change notification settings - Fork 11
feat: adding more v1 apis #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,148 @@ | ||
| /** | ||
| * Copyright 2025 GoodRx, Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| import { NextApiRequest, NextApiResponse } from 'next/types'; | ||
| import rootLogger from 'server/lib/logger'; | ||
| import BuildService from 'server/services/build'; | ||
|
|
||
| const logger = rootLogger.child({ | ||
| filename: 'builds/[uuid]/index.ts', | ||
| }); | ||
|
|
||
| /** | ||
| * @openapi | ||
| * /api/v1/builds/{uuid}: | ||
| * get: | ||
| * summary: Get build by UUID | ||
| * description: | | ||
| * Retrieves detailed information about a specific build by its UUID. | ||
| * tags: | ||
| * - Builds | ||
| * parameters: | ||
| * - in: path | ||
| * name: uuid | ||
| * required: true | ||
| * schema: | ||
| * type: string | ||
| * description: The UUID of the build | ||
| * responses: | ||
| * 200: | ||
| * description: Successfully retrieved build details | ||
| * content: | ||
| * application/json: | ||
| * schema: | ||
| * type: object | ||
| * properties: | ||
| * id: | ||
| * type: integer | ||
| * uuid: | ||
| * type: string | ||
| * status: | ||
| * type: string | ||
| * statusMessage: | ||
| * type: string | ||
| * enableFullYaml: | ||
| * type: boolean | ||
| * sha: | ||
| * type: string | ||
| * createdAt: | ||
| * type: string | ||
| * format: date-time | ||
| * updatedAt: | ||
| * type: string | ||
| * format: date-time | ||
| * deletedAt: | ||
| * type: string | ||
| * format: date-time | ||
| * nullable: true | ||
| * pullRequestId: | ||
| * type: integer | ||
| * manifest: | ||
| * type: object | ||
| * webhooksYaml: | ||
| * type: object | ||
| * dashboardLinks: | ||
| * type: object | ||
| * isStatic: | ||
| * type: boolean | ||
| * namespace: | ||
| * type: string | ||
| * 404: | ||
| * description: Build not found | ||
| * content: | ||
| * application/json: | ||
| * schema: | ||
| * type: object | ||
| * properties: | ||
| * error: | ||
| * type: string | ||
| * example: Build not found | ||
| * 405: | ||
| * description: Method not allowed | ||
| * content: | ||
| * application/json: | ||
| * schema: | ||
| * type: object | ||
| * properties: | ||
| * error: | ||
| * type: string | ||
| */ | ||
| // eslint-disable-next-line import/no-anonymous-default-export | ||
| export default async (req: NextApiRequest, res: NextApiResponse) => { | ||
| if (req.method !== 'GET') { | ||
| return res.status(405).json({ error: `${req.method} is not allowed` }); | ||
| } | ||
|
|
||
| const { uuid } = req.query; | ||
|
|
||
| if (!uuid || typeof uuid !== 'string') { | ||
| return res.status(400).json({ error: 'Invalid UUID' }); | ||
| } | ||
|
|
||
| try { | ||
| const buildService = new BuildService(); | ||
|
|
||
| const build = await buildService.db.models.Build.query() | ||
| .findOne({ uuid }) | ||
| .select( | ||
| 'id', | ||
| 'uuid', | ||
| 'status', | ||
| 'statusMessage', | ||
| 'enableFullYaml', | ||
| 'sha', | ||
| 'createdAt', | ||
| 'updatedAt', | ||
| 'deletedAt', | ||
| 'pullRequestId', | ||
| 'manifest', | ||
| 'webhooksYaml', | ||
| 'dashboardLinks', | ||
| 'isStatic', | ||
| 'namespace' | ||
| ); | ||
|
|
||
| if (!build) { | ||
| logger.info(`Build with UUID ${uuid} not found`); | ||
| return res.status(404).json({ error: 'Build not found' }); | ||
| } | ||
|
|
||
| return res.status(200).json(build); | ||
| } catch (error) { | ||
| logger.error(`Error fetching build ${uuid}:`, error); | ||
| return res.status(500).json({ error: 'An unexpected error occurred' }); | ||
| } | ||
| }; |
This file contains hidden or 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,214 @@ | ||
| /** | ||
| * Copyright 2025 GoodRx, Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| import { NextApiRequest, NextApiResponse } from 'next/types'; | ||
| import rootLogger from 'server/lib/logger'; | ||
| import BuildService from 'server/services/build'; | ||
|
|
||
| const logger = rootLogger.child({ | ||
| filename: 'api/v1/builds/index.ts', | ||
| }); | ||
|
|
||
| /** | ||
| * @openapi | ||
| * /api/v1/builds: | ||
| * get: | ||
| * summary: Get all builds with optional status filtering | ||
| * description: | | ||
| * Retrieves a list of builds with optional status exclusion filtering and pagination support. | ||
| * By default, excludes builds with status 'torn_down' and 'pending'. | ||
| * tags: | ||
| * - Builds | ||
| * parameters: | ||
| * - in: query | ||
| * name: exclude | ||
| * required: false | ||
| * schema: | ||
| * oneOf: | ||
| * - type: array | ||
| * items: | ||
| * type: string | ||
| * - type: string | ||
| * description: | | ||
| * Status values to exclude from results. Can be passed as: | ||
| * - JSON array string: exclude=["torn_down","pending"] | ||
| * - Multiple query params: exclude=torn_down&exclude=pending | ||
| * - Single value: exclude=torn_down | ||
| * Default: ["torn_down", "pending"] | ||
| * - in: query | ||
| * name: page | ||
| * required: false | ||
| * schema: | ||
| * type: integer | ||
| * minimum: 1 | ||
| * description: Page number for pagination (if not provided with limit, all results are returned) | ||
| * - in: query | ||
| * name: limit | ||
| * required: false | ||
| * schema: | ||
| * type: integer | ||
| * minimum: 1 | ||
| * description: Number of items per page (if not provided with page, all results are returned) | ||
| * responses: | ||
| * 200: | ||
| * description: Successfully retrieved builds list | ||
| * content: | ||
| * application/json: | ||
| * schema: | ||
| * type: object | ||
| * required: | ||
| * - builds | ||
| * - metadata | ||
| * properties: | ||
| * builds: | ||
| * type: array | ||
| * items: | ||
| * type: object | ||
| * required: | ||
| * - uuid | ||
| * - status | ||
| * properties: | ||
| * uuid: | ||
| * type: string | ||
| * description: Unique identifier for the build | ||
| * example: "550e8400-e29b-41d4-a716-446655440000" | ||
| * status: | ||
| * type: string | ||
| * description: Current status of the build | ||
| * example: "success" | ||
| * metadata: | ||
| * type: object | ||
| * required: | ||
| * - currentPage | ||
| * - totalPages | ||
| * - total | ||
| * - limit | ||
| * properties: | ||
| * currentPage: | ||
| * type: integer | ||
| * description: Current page number | ||
| * example: 1 | ||
| * totalPages: | ||
| * type: integer | ||
| * description: Total number of pages | ||
| * example: 5 | ||
| * total: | ||
| * type: integer | ||
| * description: Total number of builds after filtering | ||
| * example: 100 | ||
| * limit: | ||
| * type: integer | ||
| * description: Number of items per page | ||
| * example: 20 | ||
| * 405: | ||
| * description: Method not allowed | ||
| * content: | ||
| * application/json: | ||
| * schema: | ||
| * type: object | ||
| * properties: | ||
| * error: | ||
| * type: string | ||
| * example: "POST is not allowed" | ||
| * 500: | ||
| * description: Internal server error | ||
| * content: | ||
| * application/json: | ||
| * schema: | ||
| * type: object | ||
| * properties: | ||
| * error: | ||
| * type: string | ||
| * example: "An unexpected error occurred" | ||
| */ | ||
| // eslint-disable-next-line import/no-anonymous-default-export | ||
| export default async (req: NextApiRequest, res: NextApiResponse) => { | ||
| if (req.method !== 'GET') { | ||
| return res.status(405).json({ error: `${req.method} is not allowed` }); | ||
| } | ||
|
|
||
| try { | ||
| const buildService = new BuildService(); | ||
|
|
||
| // Extract query parameters | ||
| const { exclude, page, limit } = req.query; | ||
|
|
||
| // Parse exclude parameter - default to ['torn_down', 'pending'] | ||
| let excludeStatuses: string[] = ['torn_down', 'pending']; | ||
| if (exclude) { | ||
| if (Array.isArray(exclude)) { | ||
| excludeStatuses = exclude.filter((status) => typeof status === 'string'); | ||
| } else if (typeof exclude === 'string') { | ||
| try { | ||
| const parsed = JSON.parse(exclude); | ||
| if (Array.isArray(parsed)) { | ||
| excludeStatuses = parsed.filter((status) => typeof status === 'string'); | ||
| } | ||
| } catch { | ||
| // If not valid JSON, treat as single value | ||
| excludeStatuses = [exclude]; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Build base query | ||
| let query = buildService.db.models.Build.query().select('uuid', 'status').whereNotIn('status', excludeStatuses); | ||
|
|
||
| // Handle pagination | ||
| let response: any = {}; | ||
|
|
||
| if (page || limit) { | ||
| // If pagination params provided, apply pagination | ||
| const pageNumber = Math.max(1, parseInt(page as string, 10) || 1); | ||
| const limitNumber = Math.max(1, parseInt(limit as string, 10) || 20); | ||
| const offset = (pageNumber - 1) * limitNumber; | ||
|
|
||
| // Get total count | ||
| const totalCount = await query.resultSize(); | ||
|
|
||
| // Apply pagination | ||
| const builds = await query.offset(offset).limit(limitNumber); | ||
|
|
||
| response = { | ||
| builds, | ||
| metadata: { | ||
| currentPage: pageNumber, | ||
| totalPages: Math.ceil(totalCount / limitNumber), | ||
| total: totalCount, | ||
| limit: limitNumber, | ||
| }, | ||
| }; | ||
| } else { | ||
| // No pagination - return all results | ||
| const builds = await query; | ||
|
|
||
| response = { | ||
| builds, | ||
| metadata: { | ||
| currentPage: 1, | ||
| totalPages: 1, | ||
| total: builds.length, | ||
| limit: builds.length, | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| return res.status(200).json(response); | ||
| } catch (error) { | ||
| logger.error('Error fetching builds:', error); | ||
| return res.status(500).json({ error: 'An unexpected error occurred' }); | ||
| } | ||
| }; | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.