Skip to content

Commit 24fe9a5

Browse files
authored
feat(api): add endpoint to srearch libraries
1 parent 544a7ad commit 24fe9a5

File tree

7 files changed

+627
-5
lines changed

7 files changed

+627
-5
lines changed

cmd/gendoc/docs.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ const (
3030
AIModelsTag Tag = "AIModels"
3131
SystemTag Tag = "System"
3232
Property Tag = "Property"
33+
LibrariesTag Tag = "Libraries"
3334
)
3435

35-
var validTags = []Tag{ApplicationTag, BrickTag, AIModelsTag, SystemTag}
36+
var validTags = []Tag{ApplicationTag, BrickTag, AIModelsTag, SystemTag, LibrariesTag}
3637

3738
type Generator struct {
3839
reflector *openapi3.Reflector
@@ -41,9 +42,8 @@ type Generator struct {
4142
func NewOpenApiGenerator(version string) *Generator {
4243
reflector := openapi3.NewReflector()
4344
reflector.Spec.Info.WithTitle("Arduino-App-Cli").WithVersion(version)
44-
reflector.Spec.Info.WithDescription("API specification for the MonzaImola Orchestrator")
4545
reflector.Spec.Servers = append(reflector.Spec.Servers, openapi3.Server{
46-
URL: "http://localhost:8080",
46+
URL: "http://localhost:6060",
4747
Description: f.Ptr("local server"),
4848
})
4949

@@ -945,6 +945,32 @@ Contains a JSON object with the details of an error.
945945
{StatusCode: http.StatusInternalServerError, Reference: "#/components/responses/InternalServerError"},
946946
},
947947
},
948+
{
949+
OperationId: "listLibraries",
950+
Method: http.MethodGet,
951+
Path: "/v1/libraries",
952+
Parameters: (*struct {
953+
Search string `query:"search" description:"Search term to filter libraries by name, sentence, paragraph."`
954+
Architecture string `query:"architecture" description:"Filter libraries by target architecture"`
955+
Platform string `query:"platform" description:"Filter libraries by platform"`
956+
Sort string `query:"sort" description:"Sort order for the results" enum:"stars_asc,stars_desc,forks_asc,forks_desc,recent_asc,recent_desc" default:"stars_desc"`
957+
Page int `query:"page" description:"Page number for pagination" minimum:"1" default:"1"`
958+
Limit int `query:"limit" description:"Number of results per page" minimum:"1" maximum:"1000" default:"20"`
959+
})(nil),
960+
CustomSuccessResponse: &CustomResponseDef{
961+
ContentType: "application/json",
962+
DataStructure: handlers.LibraryListResponse{},
963+
Description: "Successful response with library search results",
964+
StatusCode: http.StatusOK,
965+
},
966+
Description: "Search for Arduino libraries in the registry with various filters.",
967+
Summary: "Search Arduino libraries",
968+
Tags: []Tag{LibrariesTag},
969+
PossibleErrors: []ErrorResponse{
970+
{StatusCode: http.StatusBadRequest, Reference: "#/components/responses/BadRequest"},
971+
{StatusCode: http.StatusInternalServerError, Reference: "#/components/responses/InternalServerError"},
972+
},
973+
},
948974
}
949975

950976
for _, op := range operations {

internal/api/api.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,7 @@ func NewHTTPRouter(
7878

7979
mux.Handle("GET /v1/monitor/ws", handlers.HandleMonitorWS(allowedOrigins))
8080

81+
mux.Handle("GET /v1/libraries", handlers.HandleLibraryList(cfg.LibrariesAPIURL, version))
82+
8183
return mux
8284
}

internal/api/docs/openapi.yaml

Lines changed: 166 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
openapi: 3.0.3
22
info:
3-
description: API specification for the MonzaImola Orchestrator
43
title: Arduino-App-Cli
54
version: 0.1.0
65
servers:
76
- description: local server
8-
url: http://localhost:8080
7+
url: http://localhost:6060
98
tags:
109
- name: Application
1110
- name: Brick
1211
- name: AIModels
1312
- name: System
13+
- name: Libraries
1414
paths:
1515
/v1/apps:
1616
get:
@@ -603,6 +603,74 @@ paths:
603603
summary: returns application configuration
604604
tags:
605605
- Application
606+
/v1/libraries:
607+
get:
608+
description: Search for Arduino libraries in the registry with various filters.
609+
operationId: listLibraries
610+
parameters:
611+
- description: Search term to filter libraries by name, sentence, paragraph.
612+
in: query
613+
name: search
614+
schema:
615+
description: Search term to filter libraries by name, sentence, paragraph.
616+
type: string
617+
- description: Filter libraries by target architecture
618+
in: query
619+
name: architecture
620+
schema:
621+
description: Filter libraries by target architecture
622+
type: string
623+
- description: Filter libraries by platform
624+
in: query
625+
name: platform
626+
schema:
627+
description: Filter libraries by platform
628+
type: string
629+
- description: Sort order for the results
630+
in: query
631+
name: sort
632+
schema:
633+
default: stars_desc
634+
description: Sort order for the results
635+
enum:
636+
- stars_asc
637+
- stars_desc
638+
- forks_asc
639+
- forks_desc
640+
- recent_asc
641+
- recent_desc
642+
type: string
643+
- description: Page number for pagination
644+
in: query
645+
name: page
646+
schema:
647+
default: 1
648+
description: Page number for pagination
649+
minimum: 1
650+
type: integer
651+
- description: Number of results per page
652+
in: query
653+
name: limit
654+
schema:
655+
default: 20
656+
description: Number of results per page
657+
maximum: 1000
658+
minimum: 1
659+
type: integer
660+
responses:
661+
"200":
662+
content:
663+
application/json:
664+
schema:
665+
$ref: '#/components/schemas/LibraryListResponse'
666+
description: Successful response with library search results
667+
"400":
668+
$ref: '#/components/responses/BadRequest'
669+
"500":
670+
$ref: '#/components/responses/InternalServerError'
671+
summary: Search Arduino libraries
672+
tags:
673+
- Libraries
606674
/v1/models:
607675
get:
608676
description: Returns the list of AI models available in the system. It is possible
@@ -1256,13 +1324,109 @@ components:
12561324
message:
12571325
type: string
12581326
type: object
1327+
Library:
1328+
properties:
1329+
architectures:
1330+
items:
1331+
type: string
1332+
nullable: true
1333+
type: array
1334+
author:
1335+
type: string
1336+
category:
1337+
type: string
1338+
dependencies:
1339+
items:
1340+
properties:
1341+
name:
1342+
type: string
1343+
type: object
1344+
nullable: true
1345+
type: array
1346+
example_count:
1347+
type: integer
1348+
id:
1349+
type: string
1350+
includes:
1351+
items:
1352+
type: string
1353+
nullable: true
1354+
type: array
1355+
license:
1356+
type: string
1357+
maintainer:
1358+
type: string
1359+
name:
1360+
type: string
1361+
paragraph:
1362+
type: string
1363+
platform:
1364+
nullable: true
1365+
type: string
1366+
releases:
1367+
items:
1368+
properties:
1369+
id:
1370+
type: string
1371+
version:
1372+
type: string
1373+
type: object
1374+
nullable: true
1375+
type: array
1376+
repository:
1377+
nullable: true
1378+
properties:
1379+
forks:
1380+
type: integer
1381+
stars:
1382+
type: integer
1383+
updated_at:
1384+
type: string
1385+
url:
1386+
type: string
1387+
type: object
1388+
sentence:
1389+
type: string
1390+
types:
1391+
items:
1392+
type: string
1393+
nullable: true
1394+
type: array
1395+
website:
1396+
type: string
1397+
type: object
1398+
LibraryListResponse:
1399+
properties:
1400+
libraries:
1401+
items:
1402+
$ref: '#/components/schemas/Library'
1403+
nullable: true
1404+
type: array
1405+
pagination:
1406+
$ref: '#/components/schemas/Pagination'
1407+
type: object
12591408
PackageType:
12601409
description: Package type
12611410
enum:
12621411
- arduino-platform
12631412
- debian-package
12641413
type: string
12651414
uniqueItems: true
1415+
Pagination:
1416+
properties:
1417+
next_page:
1418+
type: integer
1419+
page:
1420+
type: integer
1421+
per_page:
1422+
type: integer
1423+
prev_page:
1424+
type: integer
1425+
total_items:
1426+
type: integer
1427+
total_pages:
1428+
type: integer
1429+
type: object
12661430
Port:
12671431
properties:
12681432
port:

internal/api/handlers/libraries.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package handlers
2+
3+
import (
4+
"log/slog"
5+
"net/http"
6+
"net/http/httputil"
7+
"net/url"
8+
)
9+
10+
// HandleLibraryList is a proxy to the List libraries API
11+
func HandleLibraryList(target *url.URL, version string) http.Handler {
12+
return &httputil.ReverseProxy{
13+
Rewrite: func(r *httputil.ProxyRequest) {
14+
r.Out.URL = target
15+
r.Out.URL.RawQuery = r.In.URL.RawQuery
16+
r.Out.Host = target.Host // Cloudfront needs the Host header to match the URL host otherwise it returns 403
17+
r.Out.Header.Set("User-Agent", "arduino-app-cli/"+version)
18+
19+
r.SetXForwarded()
20+
slog.Debug("Proxying library request", slog.Any("in", r.In.URL), slog.Any("out", r.Out.URL), slog.String("target", target.String()))
21+
},
22+
}
23+
}
24+
25+
// NOTE: this is only to generate the openapi docs.
26+
type LibraryListResponse struct {
27+
Libraries []Library `json:"libraries"`
28+
Pagination Pagination `json:"pagination"`
29+
}
30+
31+
type Library struct {
32+
Name string `json:"name"`
33+
ID string `json:"id"`
34+
35+
Repository *struct {
36+
URL string `json:"url"`
37+
Stars int `json:"stars"`
38+
Forks int `json:"forks"`
39+
UpdatedAt string `json:"updated_at"`
40+
} `json:"repository"`
41+
Website string `json:"website"`
42+
License string `json:"license"`
43+
44+
Platform *string `json:"platform"`
45+
Architectures []string `json:"architectures"`
46+
Types []string `json:"types"`
47+
Category string `json:"category"`
48+
49+
Maintainer string `json:"maintainer"`
50+
Author string `json:"author"`
51+
Sentence string `json:"sentence"`
52+
Paragraph string `json:"paragraph"`
53+
54+
Includes []string `json:"includes"`
55+
Dependencies []struct {
56+
Name string `json:"name"`
57+
} `json:"dependencies"`
58+
59+
ExampleCount int `json:"example_count"`
60+
61+
Releases []struct {
62+
ID string `json:"id"`
63+
Version string `json:"version"`
64+
} `json:"releases"`
65+
}
66+
67+
type Pagination struct {
68+
TotalPages int `json:"total_pages"`
69+
TotalItems int `json:"total_items"`
70+
Page int `json:"page"`
71+
PerPage int `json:"per_page"`
72+
NextPage int `json:"next_page"`
73+
PrevPage int `json:"prev_page"`
74+
}

0 commit comments

Comments
 (0)