initial commit
@@ -8,6 +8,8 @@
|
|||||||
*.dll
|
*.dll
|
||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
|
bin/*
|
||||||
|
!bin/.gitkeep
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Ignored default folder with query files
|
||||||
|
/queries/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module version="4">
|
||||||
|
<component name="Go" enabled="true" />
|
||||||
|
</module>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="GoImports">
|
||||||
|
<option name="excludedPackages">
|
||||||
|
<array>
|
||||||
|
<option value="golang.org/x/net/context" />
|
||||||
|
</array>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/backbone.iml" filepath="$PROJECT_DIR$/.idea/backbone.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProtobufLanguageSettings">
|
||||||
|
<option name="importPathEntries">
|
||||||
|
<list>
|
||||||
|
<ImportPathEntry>
|
||||||
|
<option name="location" value="file://$PROJECT_DIR$/pkg/3rdparty" />
|
||||||
|
</ImportPathEntry>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
FROM node:24-alpine AS frontend_dependencies
|
||||||
|
RUN mkdir -p /app
|
||||||
|
WORKDIR /app
|
||||||
|
ADD static/app/package.json .
|
||||||
|
ADD static/app/yarn.lock .
|
||||||
|
RUN yarn install --frozen-lockfile
|
||||||
|
|
||||||
|
FROM frontend_dependencies AS frontend_build
|
||||||
|
ADD static/app .
|
||||||
|
RUN yarn build
|
||||||
|
|
||||||
|
FROM golang:1.26-alpine AS backend_dependencies
|
||||||
|
RUN apk add git make
|
||||||
|
RUN mkdir -p /app
|
||||||
|
WORKDIR /app
|
||||||
|
ADD go.mod .
|
||||||
|
ADD go.sum .
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
FROM backend_dependencies AS backend_build
|
||||||
|
ADD . .
|
||||||
|
RUN rm -rf static/app/dist
|
||||||
|
COPY --from=frontend_build /app/dist /app/static/app/dist
|
||||||
|
RUN make build
|
||||||
|
|
||||||
|
FROM alpine:latest AS final
|
||||||
|
|
||||||
|
FROM final
|
||||||
|
EXPOSE 8000
|
||||||
|
EXPOSE 9000
|
||||||
|
COPY --from=backend_build /app/bin/app /app
|
||||||
|
CMD ["/app"]
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
ROOT := $(shell pwd)
|
||||||
|
LOCAL_BIN := $(ROOT)/bin
|
||||||
|
VERSION := $(shell git show-ref --tags -d || git rev-parse --short HEAD)
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build:
|
||||||
|
echo "$(VERSION)" > static/app/dist/version.txt
|
||||||
|
go build \
|
||||||
|
-ldflags "-X backbone/internal/pkg/version.Version=$(VERSION)" \
|
||||||
|
-o $(LOCAL_BIN)/app \
|
||||||
|
internal/app/cmd/main.go
|
||||||
|
|
||||||
|
.PHONY: deps
|
||||||
|
proto-deps:
|
||||||
|
GOBIN=$(LOCAL_BIN) go install google.golang.org/protobuf/cmd/protoc-gen-go
|
||||||
|
GOBIN=$(LOCAL_BIN) go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
|
||||||
|
GOBIN=$(LOCAL_BIN) go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
|
||||||
|
GOBIN=$(LOCAL_BIN) go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
|
||||||
|
|
||||||
|
.PHONY: proto
|
||||||
|
proto:
|
||||||
|
@PATH=$(PATH):$(LOCAL_BIN) protoc \
|
||||||
|
-I . \
|
||||||
|
-I pkg/3rdparty \
|
||||||
|
--go_out=pkg/pb \
|
||||||
|
--go_opt=Mgoogle/api/http.proto=google.golang.org/genproto/googleapis/api/annotations \
|
||||||
|
--go-grpc_opt=Mgoogle/api/http.proto=google.golang.org/genproto/googleapis/api/annotations \
|
||||||
|
--go_opt=Mgoogle/api/annotations.proto=google.golang.org/genproto/googleapis/api/annotations \
|
||||||
|
--go-grpc_opt=Mgoogle/api/annotations.proto=google.golang.org/genproto/googleapis/api/annotations \
|
||||||
|
--go_opt=paths=source_relative \
|
||||||
|
--go-grpc_out=pkg/pb \
|
||||||
|
--go-grpc_opt=paths=source_relative \
|
||||||
|
--grpc-gateway_out=pkg/pb \
|
||||||
|
--grpc-gateway_opt=Mgoogle/api/http.proto=google.golang.org/genproto/googleapis/api/annotations \
|
||||||
|
--grpc-gateway_opt=Mgoogle/api/annotations.proto=google.golang.org/genproto/googleapis/api/annotations \
|
||||||
|
--grpc-gateway_opt=paths=source_relative \
|
||||||
|
--openapiv2_opt=Mgoogle/api/http.proto=google.golang.org/genproto/googleapis/api/annotations \
|
||||||
|
--openapiv2_opt=Mgoogle/api/annotations.proto=google.golang.org/genproto/googleapis/api/annotations \
|
||||||
|
--openapiv2_out=logtostderr=true,allow_merge=true,merge_file_name=api:./api \
|
||||||
|
api/messages/*.proto \
|
||||||
|
api/services/*.proto
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Application",
|
||||||
|
"version": "%version%"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"name": "DebugAPI"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/api/v1/version": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "DebugAPI_GetVersion",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A successful response.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/servicesGetVersionResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"description": "An unexpected error response.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/rpcStatus"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"DebugAPI"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"definitions": {
|
||||||
|
"protobufAny": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"@type": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": {}
|
||||||
|
},
|
||||||
|
"rpcStatus": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"details": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"$ref": "#/definitions/protobufAny"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"servicesGetVersionResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"version": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package api.messages;
|
||||||
|
|
||||||
|
option go_package = "pkg/pb/api/messages";
|
||||||
|
|
||||||
|
message Message{}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed api.swagger.json
|
||||||
|
var OpenAPI []byte
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package api.services;
|
||||||
|
|
||||||
|
option go_package = "pkg/pb/api/services";
|
||||||
|
|
||||||
|
import "protoc-gen-openapiv2/options/annotations.proto";
|
||||||
|
|
||||||
|
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||||
|
info: {
|
||||||
|
title: "Application"
|
||||||
|
version: "%version%"
|
||||||
|
}
|
||||||
|
security_definitions: {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package api.services;
|
||||||
|
|
||||||
|
option go_package = "pkg/pb/api/services";
|
||||||
|
|
||||||
|
import "google/api/annotations.proto";
|
||||||
|
|
||||||
|
service DebugAPI {
|
||||||
|
rpc GetVersion (GetVersion.Request) returns (GetVersion.Response) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/api/v1/version"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetVersion {
|
||||||
|
message Request {}
|
||||||
|
message Response {
|
||||||
|
string version = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
module backbone
|
||||||
|
|
||||||
|
go 1.26.5
|
||||||
|
|
||||||
|
tool (
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
|
||||||
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc
|
||||||
|
google.golang.org/protobuf/cmd/protoc-gen-go
|
||||||
|
)
|
||||||
|
|
||||||
|
//replace git.kamenetskii.ru/core/backbone/pkg/pb => ./pkg/pb
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/go-chi/chi/v5 v5.3.2
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0
|
||||||
|
github.com/jackc/pgx/v5 v5.11.0
|
||||||
|
github.com/jmoiron/sqlx v1.4.0
|
||||||
|
go.mongodb.org/mongo-driver/v2 v2.9.1
|
||||||
|
google.golang.org/grpc v1.83.0
|
||||||
|
google.golang.org/protobuf v1.36.12
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||||
|
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||||
|
github.com/klauspost/compress v1.19.2 // indirect
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
|
github.com/xdg-go/scram v1.2.0 // indirect
|
||||||
|
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
|
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
||||||
|
golang.org/x/crypto v0.54.0 // indirect
|
||||||
|
golang.org/x/net v0.57.0 // indirect
|
||||||
|
golang.org/x/sync v0.23.0 // indirect
|
||||||
|
golang.org/x/sys v0.47.0 // indirect
|
||||||
|
golang.org/x/text v0.42.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d // indirect
|
||||||
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.2 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/go-chi/chi/v5 v5.3.2 h1:5YQkICvTCSZ25hoRsyJazN0scjzKGiu4VAUc7H1o1nY=
|
||||||
|
github.com/go-chi/chi/v5 v5.3.2/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
|
||||||
|
github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8=
|
||||||
|
github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0 h1:/Tnpcb2E0Pz/tN9s3bfEY2Q8ePCEX9iuS+cneUwncnw=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0/go.mod h1:zOBXOsUaBSjKgmH4OGzV1esUpR3oUSCPYVd2cUBjKYY=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
|
github.com/jackc/pgx/v5 v5.11.0 h1:IzBBtyK9AHqf98cctWFifYSci2hgQR/cd56wB4p+ogg=
|
||||||
|
github.com/jackc/pgx/v5 v5.11.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
|
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
||||||
|
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
|
||||||
|
github.com/klauspost/compress v1.19.2 h1:hMRETovs/pu/dVWN7zIT1PGG8t509MwT6bO7XSi26R8=
|
||||||
|
github.com/klauspost/compress v1.19.2/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||||
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
|
github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs=
|
||||||
|
github.com/xdg-go/scram v1.2.0/go.mod h1:3dlrS0iBaWKYVt2ZfA4cj48umJZ+cAEbR6/SjLA88I8=
|
||||||
|
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||||
|
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
go.mongodb.org/mongo-driver/v2 v2.9.1 h1:jewiFs2m1/VOQp8qhFshX6hWZ+EAXDhZHXExAUMcOgQ=
|
||||||
|
go.mongodb.org/mongo-driver/v2 v2.9.1/go.mod h1:SHKN0IWkKmEVGHLjXnni6s4wPKX4v86FTgOeJJFuXcA=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||||
|
go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU=
|
||||||
|
go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ=
|
||||||
|
go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M=
|
||||||
|
go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=
|
||||||
|
go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag=
|
||||||
|
go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||||
|
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
|
||||||
|
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk=
|
||||||
|
golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||||
|
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
|
golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI=
|
||||||
|
golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||||
|
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||||
|
google.golang.org/grpc v1.83.0 h1:JeNZEKJFbQxArAMl+hiytHauacDNqJUllNfmIMmpqnQ=
|
||||||
|
google.golang.org/grpc v1.83.0/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ=
|
||||||
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.2 h1:rgSNvqscFZ1JgV/4wH5GOsZFSFkR2Eua9As3KIr2LlM=
|
||||||
|
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.2/go.mod h1:iMEtFwDlAhjDU9L5mY6U1XLwlIId/G3h+QcBHDIvrJ8=
|
||||||
|
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||||
|
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"backbone/internal/app/handler/debugh"
|
||||||
|
"backbone/internal/pkg/app"
|
||||||
|
svc "backbone/pkg/pb/api/services"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := app.New(
|
||||||
|
app.WithSwaggerUI(),
|
||||||
|
app.WithStatic(),
|
||||||
|
)
|
||||||
|
|
||||||
|
debugH := debugh.New()
|
||||||
|
|
||||||
|
a.RegisterServices(func(gs *grpc.Server) {
|
||||||
|
svc.RegisterDebugAPIServer(gs, debugH)
|
||||||
|
})
|
||||||
|
|
||||||
|
a.RegisterGateways(
|
||||||
|
svc.RegisterDebugAPIHandler,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := a.ListenAndServe(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package debugh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"backbone/internal/pkg/version"
|
||||||
|
svc "backbone/pkg/pb/api/services"
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *Handler) GetVersion(_ context.Context, _ *svc.GetVersion_Request) (*svc.GetVersion_Response, error) {
|
||||||
|
return &svc.GetVersion_Response{
|
||||||
|
Version: version.Version,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package debugh
|
||||||
|
|
||||||
|
import svc "backbone/pkg/pb/api/services"
|
||||||
|
|
||||||
|
func New() *Handler {
|
||||||
|
return new(Handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Handler struct {
|
||||||
|
svc.UnimplementedDebugAPIServer
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/mongo"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(options ...Option) *App {
|
||||||
|
a := &App{
|
||||||
|
ctx: context.Background(),
|
||||||
|
router: chi.NewRouter(),
|
||||||
|
grpcServer: grpc.NewServer(),
|
||||||
|
httpServer: new(http.Server),
|
||||||
|
}
|
||||||
|
for _, option := range options {
|
||||||
|
option(a)
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
type App struct {
|
||||||
|
ctx context.Context
|
||||||
|
router *chi.Mux
|
||||||
|
grpcServer *grpc.Server
|
||||||
|
httpServer *http.Server
|
||||||
|
mux *runtime.ServeMux
|
||||||
|
postgres *sqlx.DB
|
||||||
|
mongo *mongo.Client
|
||||||
|
closers []closeFunc
|
||||||
|
serviceRegistry []registerServiceFunc
|
||||||
|
gatewayRegistry []registerGatewayFunc
|
||||||
|
config struct {
|
||||||
|
grpcAddr string
|
||||||
|
httpAddr string
|
||||||
|
postgresURI string
|
||||||
|
mongoURI string
|
||||||
|
withGrpc bool
|
||||||
|
withSwagger bool
|
||||||
|
withStatic bool
|
||||||
|
forwardResponse forwardResponseFunc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultHttpAddr = ":8000"
|
||||||
|
defaultGrpcAddr = ":9000"
|
||||||
|
)
|
||||||
|
|
||||||
|
type forwardResponseFunc func(context.Context, http.ResponseWriter, proto.Message) error
|
||||||
|
type closeFunc func() error
|
||||||
|
type registerServiceFunc func(gs *grpc.Server)
|
||||||
|
type registerGatewayFunc func(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error
|
||||||
|
|
||||||
|
func (a *App) RegisterServices(fn registerServiceFunc) {
|
||||||
|
a.serviceRegistry = append(a.serviceRegistry, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) RegisterGateways(fns ...registerGatewayFunc) {
|
||||||
|
a.gatewayRegistry = append(a.gatewayRegistry, fns...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) GRPC() *grpc.Server {
|
||||||
|
return a.grpcServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) HTTP() *http.Server {
|
||||||
|
return a.httpServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) Router() *chi.Mux {
|
||||||
|
return a.router
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"backbone/static"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *App) ListenAndServe() error {
|
||||||
|
a.httpServer.Handler = a.router
|
||||||
|
a.httpServer.Addr = a.getHTTPAddr()
|
||||||
|
|
||||||
|
muxOptions := []runtime.ServeMuxOption{
|
||||||
|
runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{
|
||||||
|
MarshalOptions: protojson.MarshalOptions{
|
||||||
|
EmitUnpopulated: true,
|
||||||
|
EmitDefaultValues: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
if a.config.forwardResponse != nil {
|
||||||
|
muxOptions = append(muxOptions,
|
||||||
|
runtime.WithForwardResponseOption(a.config.forwardResponse))
|
||||||
|
}
|
||||||
|
a.mux = runtime.NewServeMux(muxOptions...)
|
||||||
|
|
||||||
|
a.router.Handle("/api/*", a.mux)
|
||||||
|
if a.config.withSwagger {
|
||||||
|
a.router.Handle("/api/openapi.json", openApiServer)
|
||||||
|
a.router.Handle("/swagger*", swaggerUIHandler)
|
||||||
|
}
|
||||||
|
if a.config.withStatic {
|
||||||
|
a.router.NotFound(static.Handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// register services
|
||||||
|
for _, s := range a.serviceRegistry {
|
||||||
|
s(a.grpcServer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// register gateways
|
||||||
|
conn, err := grpc.NewClient(a.getGRPCAddr(),
|
||||||
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to init local grpc client: %w", err)
|
||||||
|
}
|
||||||
|
for _, g := range a.gatewayRegistry {
|
||||||
|
if err = g(a.ctx, a.mux, conn); err != nil {
|
||||||
|
return fmt.Errorf("failed to init gateway: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errChan := make(chan error)
|
||||||
|
go a.startGRPC(errChan)
|
||||||
|
go a.startHTTP(errChan)
|
||||||
|
go a.wait(errChan)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case err := <-errChan:
|
||||||
|
return err
|
||||||
|
case <-a.ctx.Done():
|
||||||
|
return a.ctx.Err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) startHTTP(errChan chan error) {
|
||||||
|
if err := a.httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
|
errChan <- fmt.Errorf("failed to start http server: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) startGRPC(errChan chan error) {
|
||||||
|
listener, err := net.Listen("tcp", a.getGRPCAddr())
|
||||||
|
if err != nil {
|
||||||
|
errChan <- fmt.Errorf("failed to start grpc server: %w", err)
|
||||||
|
}
|
||||||
|
if err = a.grpcServer.Serve(listener); err != nil {
|
||||||
|
errChan <- fmt.Errorf("failed to serve grpc: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) getHTTPAddr() string {
|
||||||
|
if a.config.httpAddr != "" {
|
||||||
|
return a.config.httpAddr
|
||||||
|
}
|
||||||
|
if v := os.Getenv("HTTP_ADDR"); v != "" {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return defaultHttpAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) getGRPCAddr() string {
|
||||||
|
if a.config.grpcAddr != "" {
|
||||||
|
return a.config.grpcAddr
|
||||||
|
}
|
||||||
|
if v := os.Getenv("GRPC_ADDR"); v != "" {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return defaultGrpcAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) wait(errChan chan error) {
|
||||||
|
sigs := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-sigs
|
||||||
|
|
||||||
|
shutdownCtx, cancel := context.WithTimeout(a.ctx, 30*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if err := a.httpServer.Shutdown(shutdownCtx); err != nil {
|
||||||
|
errChan <- err
|
||||||
|
}
|
||||||
|
a.grpcServer.GracefulStop()
|
||||||
|
|
||||||
|
for _, closer := range a.closers {
|
||||||
|
if err := closer(); err != nil {
|
||||||
|
errChan <- err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errChan <- nil
|
||||||
|
}()
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/v2/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *App) initMongo() {
|
||||||
|
if a.config.mongoURI == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
client, err := mongo.Connect(options.Client().ApplyURI(a.config.mongoURI))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("failed to connect mongo:", err)
|
||||||
|
}
|
||||||
|
a.mongo = client
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"backbone/api"
|
||||||
|
"backbone/internal/pkg/version"
|
||||||
|
"bytes"
|
||||||
|
"embed"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed swagger
|
||||||
|
var swaggerFS embed.FS
|
||||||
|
|
||||||
|
var swaggerUIHandler = func() http.Handler {
|
||||||
|
//sub,err := fs.Sub(swaggerFS, "swagger")
|
||||||
|
return http.FileServerFS(swaggerFS)
|
||||||
|
}()
|
||||||
|
|
||||||
|
var openApiServer = func() http.Handler {
|
||||||
|
content := bytes.ReplaceAll(api.OpenAPI, []byte("%version%"), []byte(version.Version))
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.ServeContent(w, r, "openapi.json", time.Now(), bytes.NewReader(content))
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
|
||||||
|
//
|
||||||
|
//func (a *App) serveOpenAPIFile(w http.ResponseWriter, r *http.Request) {
|
||||||
|
//
|
||||||
|
// //w.Header().Set("Content-Type", "application/json")
|
||||||
|
// //w.WriteHeader(http.StatusOK)
|
||||||
|
// //_, _ = w.Write(api.OpenAPI)
|
||||||
|
//}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
type Option func(*App)
|
||||||
|
|
||||||
|
func WithHTTPAddr(addr string) Option {
|
||||||
|
return func(a *App) {
|
||||||
|
a.config.httpAddr = addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithGRPCAddr(addr string) Option {
|
||||||
|
return func(a *App) {
|
||||||
|
a.config.grpcAddr = addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithPostgresDatabase(uri string) Option {
|
||||||
|
return func(a *App) {
|
||||||
|
a.config.postgresURI = uri
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithMongoDatabase(uri string) Option {
|
||||||
|
return func(a *App) {
|
||||||
|
a.config.mongoURI = uri
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithSwaggerUI() Option {
|
||||||
|
return func(a *App) {
|
||||||
|
a.config.withSwagger = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithStatic() Option {
|
||||||
|
return func(a *App) {
|
||||||
|
a.config.withStatic = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithForwardResponse(fn forwardResponseFunc) Option {
|
||||||
|
return func(a *App) {
|
||||||
|
a.config.forwardResponse = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
|
"github.com/jackc/pgx/v5/stdlib"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *App) initPostgres() {
|
||||||
|
if a.config.postgresURI == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pool, err := pgxpool.New(a.ctx, a.config.postgresURI)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("failed to connect to postgres:", err)
|
||||||
|
}
|
||||||
|
a.postgres = sqlx.NewDb(stdlib.OpenDBFromPool(pool), "postgres")
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 665 B |
|
After Width: | Height: | Size: 628 B |
@@ -0,0 +1,16 @@
|
|||||||
|
html {
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: -moz-scrollbars-vertical;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after {
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<!-- HTML for static distribution bundle build -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Swagger UI</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="swagger-ui.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="index.css" />
|
||||||
|
<link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />
|
||||||
|
<link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="swagger-ui"></div>
|
||||||
|
<script src="swagger-ui-bundle.js" charset="UTF-8"> </script>
|
||||||
|
<script src="swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
|
||||||
|
<script src="swagger-initializer.js" charset="UTF-8"> </script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
window.onload = function () {
|
||||||
|
//<editor-fold desc="Changeable Configuration Block">
|
||||||
|
|
||||||
|
const HideInfoUrlPartsPlugin = () => {
|
||||||
|
return {
|
||||||
|
wrapComponents: {
|
||||||
|
InfoUrl: () => () => null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
|
||||||
|
window.ui = SwaggerUIBundle({
|
||||||
|
url: "/api/openapi.json",
|
||||||
|
dom_id: '#swagger-ui',
|
||||||
|
deepLinking: true,
|
||||||
|
presets: [
|
||||||
|
SwaggerUIBundle.presets.apis,
|
||||||
|
SwaggerUIStandalonePreset
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
SwaggerUIBundle.plugins.DownloadUrl,
|
||||||
|
HideInfoUrlPartsPlugin,
|
||||||
|
],
|
||||||
|
layout: "StandaloneLayout"
|
||||||
|
});
|
||||||
|
|
||||||
|
//</editor-fold>
|
||||||
|
};
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package version
|
||||||
|
|
||||||
|
var Version string = "dev"
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (c) 2015, Google 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.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package google.api;
|
||||||
|
|
||||||
|
import "google/api/http.proto";
|
||||||
|
import "google/protobuf/descriptor.proto";
|
||||||
|
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option java_outer_classname = "AnnotationsProto";
|
||||||
|
option java_package = "com.google.api";
|
||||||
|
option objc_class_prefix = "GAPI";
|
||||||
|
|
||||||
|
extend google.protobuf.MethodOptions {
|
||||||
|
// See `HttpRule`.
|
||||||
|
HttpRule http = 72295728;
|
||||||
|
}
|
||||||
@@ -0,0 +1,285 @@
|
|||||||
|
// Copyright 2016 Google 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.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package google.api;
|
||||||
|
|
||||||
|
option cc_enable_arenas = true;
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option java_outer_classname = "HttpProto";
|
||||||
|
option java_package = "com.google.api";
|
||||||
|
option objc_class_prefix = "GAPI";
|
||||||
|
|
||||||
|
|
||||||
|
// Defines the HTTP configuration for a service. It contains a list of
|
||||||
|
// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
|
||||||
|
// to one or more HTTP REST API methods.
|
||||||
|
message Http {
|
||||||
|
// A list of HTTP configuration rules that apply to individual API methods.
|
||||||
|
//
|
||||||
|
// **NOTE:** All service configuration rules follow "last one wins" order.
|
||||||
|
repeated HttpRule rules = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `HttpRule` defines the mapping of an RPC method to one or more HTTP
|
||||||
|
// REST APIs. The mapping determines what portions of the request
|
||||||
|
// message are populated from the path, query parameters, or body of
|
||||||
|
// the HTTP request. The mapping is typically specified as an
|
||||||
|
// `google.api.http` annotation, see "google/api/annotations.proto"
|
||||||
|
// for details.
|
||||||
|
//
|
||||||
|
// The mapping consists of a field specifying the path template and
|
||||||
|
// method kind. The path template can refer to fields in the request
|
||||||
|
// message, as in the example below which describes a REST GET
|
||||||
|
// operation on a resource collection of messages:
|
||||||
|
//
|
||||||
|
// ```proto
|
||||||
|
// service Messaging {
|
||||||
|
// rpc GetMessage(GetMessageRequest) returns (Message) {
|
||||||
|
// option (google.api.http).get = "/v1/messages/{message_id}/{sub.subfield}";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// message GetMessageRequest {
|
||||||
|
// message SubMessage {
|
||||||
|
// string subfield = 1;
|
||||||
|
// }
|
||||||
|
// string message_id = 1; // mapped to the URL
|
||||||
|
// SubMessage sub = 2; // `sub.subfield` is url-mapped
|
||||||
|
// }
|
||||||
|
// message Message {
|
||||||
|
// string text = 1; // content of the resource
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// This definition enables an automatic, bidrectional mapping of HTTP
|
||||||
|
// JSON to RPC. Example:
|
||||||
|
//
|
||||||
|
// HTTP | RPC
|
||||||
|
// -----|-----
|
||||||
|
// `GET /v1/messages/123456/foo` | `GetMessage(message_id: "123456" sub: SubMessage(subfield: "foo"))`
|
||||||
|
//
|
||||||
|
// In general, not only fields but also field paths can be referenced
|
||||||
|
// from a path pattern. Fields mapped to the path pattern cannot be
|
||||||
|
// repeated and must have a primitive (non-message) type.
|
||||||
|
//
|
||||||
|
// Any fields in the request message which are not bound by the path
|
||||||
|
// pattern automatically become (optional) HTTP query
|
||||||
|
// parameters. Assume the following definition of the request message:
|
||||||
|
//
|
||||||
|
// ```proto
|
||||||
|
// message GetMessageRequest {
|
||||||
|
// message SubMessage {
|
||||||
|
// string subfield = 1;
|
||||||
|
// }
|
||||||
|
// string message_id = 1; // mapped to the URL
|
||||||
|
// int64 revision = 2; // becomes a parameter
|
||||||
|
// SubMessage sub = 3; // `sub.subfield` becomes a parameter
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// This enables a HTTP JSON to RPC mapping as below:
|
||||||
|
//
|
||||||
|
// HTTP | RPC
|
||||||
|
// -----|-----
|
||||||
|
// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: "foo"))`
|
||||||
|
//
|
||||||
|
// Note that fields which are mapped to HTTP parameters must have a
|
||||||
|
// primitive type or a repeated primitive type. Message types are not
|
||||||
|
// allowed. In the case of a repeated type, the parameter can be
|
||||||
|
// repeated in the URL, as in `...?param=A¶m=B`.
|
||||||
|
//
|
||||||
|
// For HTTP method kinds which allow a request body, the `body` field
|
||||||
|
// specifies the mapping. Consider a REST update method on the
|
||||||
|
// message resource collection:
|
||||||
|
//
|
||||||
|
// ```proto
|
||||||
|
// service Messaging {
|
||||||
|
// rpc UpdateMessage(UpdateMessageRequest) returns (Message) {
|
||||||
|
// option (google.api.http) = {
|
||||||
|
// put: "/v1/messages/{message_id}"
|
||||||
|
// body: "message"
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// message UpdateMessageRequest {
|
||||||
|
// string message_id = 1; // mapped to the URL
|
||||||
|
// Message message = 2; // mapped to the body
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// The following HTTP JSON to RPC mapping is enabled, where the
|
||||||
|
// representation of the JSON in the request body is determined by
|
||||||
|
// protos JSON encoding:
|
||||||
|
//
|
||||||
|
// HTTP | RPC
|
||||||
|
// -----|-----
|
||||||
|
// `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" message { text: "Hi!" })`
|
||||||
|
//
|
||||||
|
// The special name `*` can be used in the body mapping to define that
|
||||||
|
// every field not bound by the path template should be mapped to the
|
||||||
|
// request body. This enables the following alternative definition of
|
||||||
|
// the update method:
|
||||||
|
//
|
||||||
|
// ```proto
|
||||||
|
// service Messaging {
|
||||||
|
// rpc UpdateMessage(Message) returns (Message) {
|
||||||
|
// option (google.api.http) = {
|
||||||
|
// put: "/v1/messages/{message_id}"
|
||||||
|
// body: "*"
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// message Message {
|
||||||
|
// string message_id = 1;
|
||||||
|
// string text = 2;
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// The following HTTP JSON to RPC mapping is enabled:
|
||||||
|
//
|
||||||
|
// HTTP | RPC
|
||||||
|
// -----|-----
|
||||||
|
// `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" text: "Hi!")`
|
||||||
|
//
|
||||||
|
// Note that when using `*` in the body mapping, it is not possible to
|
||||||
|
// have HTTP parameters, as all fields not bound by the path end in
|
||||||
|
// the body. This makes this option more rarely used in practice of
|
||||||
|
// defining REST APIs. The common usage of `*` is in custom methods
|
||||||
|
// which don't use the URL at all for transferring data.
|
||||||
|
//
|
||||||
|
// It is possible to define multiple HTTP methods for one RPC by using
|
||||||
|
// the `additional_bindings` option. Example:
|
||||||
|
//
|
||||||
|
// ```proto
|
||||||
|
// service Messaging {
|
||||||
|
// rpc GetMessage(GetMessageRequest) returns (Message) {
|
||||||
|
// option (google.api.http) = {
|
||||||
|
// get: "/v1/messages/{message_id}"
|
||||||
|
// additional_bindings {
|
||||||
|
// get: "/v1/users/{user_id}/messages/{message_id}"
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// message GetMessageRequest {
|
||||||
|
// string message_id = 1;
|
||||||
|
// string user_id = 2;
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// This enables the following two alternative HTTP JSON to RPC
|
||||||
|
// mappings:
|
||||||
|
//
|
||||||
|
// HTTP | RPC
|
||||||
|
// -----|-----
|
||||||
|
// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")`
|
||||||
|
// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: "123456")`
|
||||||
|
//
|
||||||
|
// # Rules for HTTP mapping
|
||||||
|
//
|
||||||
|
// The rules for mapping HTTP path, query parameters, and body fields
|
||||||
|
// to the request message are as follows:
|
||||||
|
//
|
||||||
|
// 1. The `body` field specifies either `*` or a field path, or is
|
||||||
|
// omitted. If omitted, it assumes there is no HTTP body.
|
||||||
|
// 2. Leaf fields (recursive expansion of nested messages in the
|
||||||
|
// request) can be classified into three types:
|
||||||
|
// (a) Matched in the URL template.
|
||||||
|
// (b) Covered by body (if body is `*`, everything except (a) fields;
|
||||||
|
// else everything under the body field)
|
||||||
|
// (c) All other fields.
|
||||||
|
// 3. URL query parameters found in the HTTP request are mapped to (c) fields.
|
||||||
|
// 4. Any body sent with an HTTP request can contain only (b) fields.
|
||||||
|
//
|
||||||
|
// The syntax of the path template is as follows:
|
||||||
|
//
|
||||||
|
// Template = "/" Segments [ Verb ] ;
|
||||||
|
// Segments = Segment { "/" Segment } ;
|
||||||
|
// Segment = "*" | "**" | LITERAL | Variable ;
|
||||||
|
// Variable = "{" FieldPath [ "=" Segments ] "}" ;
|
||||||
|
// FieldPath = IDENT { "." IDENT } ;
|
||||||
|
// Verb = ":" LITERAL ;
|
||||||
|
//
|
||||||
|
// The syntax `*` matches a single path segment. It follows the semantics of
|
||||||
|
// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String
|
||||||
|
// Expansion.
|
||||||
|
//
|
||||||
|
// The syntax `**` matches zero or more path segments. It follows the semantics
|
||||||
|
// of [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.3 Reserved
|
||||||
|
// Expansion.
|
||||||
|
//
|
||||||
|
// The syntax `LITERAL` matches literal text in the URL path.
|
||||||
|
//
|
||||||
|
// The syntax `Variable` matches the entire path as specified by its template;
|
||||||
|
// this nested template must not contain further variables. If a variable
|
||||||
|
// matches a single path segment, its template may be omitted, e.g. `{var}`
|
||||||
|
// is equivalent to `{var=*}`.
|
||||||
|
//
|
||||||
|
// NOTE: the field paths in variables and in the `body` must not refer to
|
||||||
|
// repeated fields or map fields.
|
||||||
|
//
|
||||||
|
// Use CustomHttpPattern to specify any HTTP method that is not included in the
|
||||||
|
// `pattern` field, such as HEAD, or "*" to leave the HTTP method unspecified for
|
||||||
|
// a given URL path rule. The wild-card rule is useful for services that provide
|
||||||
|
// content to Web (HTML) clients.
|
||||||
|
message HttpRule {
|
||||||
|
// Selects methods to which this rule applies.
|
||||||
|
//
|
||||||
|
// Refer to [selector][google.api.DocumentationRule.selector] for syntax details.
|
||||||
|
string selector = 1;
|
||||||
|
|
||||||
|
// Determines the URL pattern is matched by this rules. This pattern can be
|
||||||
|
// used with any of the {get|put|post|delete|patch} methods. A custom method
|
||||||
|
// can be defined using the 'custom' field.
|
||||||
|
oneof pattern {
|
||||||
|
// Used for listing and getting information about resources.
|
||||||
|
string get = 2;
|
||||||
|
|
||||||
|
// Used for updating a resource.
|
||||||
|
string put = 3;
|
||||||
|
|
||||||
|
// Used for creating a resource.
|
||||||
|
string post = 4;
|
||||||
|
|
||||||
|
// Used for deleting a resource.
|
||||||
|
string delete = 5;
|
||||||
|
|
||||||
|
// Used for updating a resource.
|
||||||
|
string patch = 6;
|
||||||
|
|
||||||
|
// Custom pattern is used for defining custom verbs.
|
||||||
|
CustomHttpPattern custom = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The name of the request field whose value is mapped to the HTTP body, or
|
||||||
|
// `*` for mapping all fields not captured by the path pattern to the HTTP
|
||||||
|
// body. NOTE: the referred field must not be a repeated field and must be
|
||||||
|
// present at the top-level of response message type.
|
||||||
|
string body = 7;
|
||||||
|
|
||||||
|
// Additional HTTP bindings for the selector. Nested bindings must
|
||||||
|
// not contain an `additional_bindings` field themselves (that is,
|
||||||
|
// the nesting may only be one level deep).
|
||||||
|
repeated HttpRule additional_bindings = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A custom pattern is used for defining custom HTTP verb.
|
||||||
|
message CustomHttpPattern {
|
||||||
|
// The name of this custom HTTP verb.
|
||||||
|
string kind = 1;
|
||||||
|
|
||||||
|
// The path matched by this custom verb.
|
||||||
|
string path = 2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package grpc.gateway.protoc_gen_openapiv2.options;
|
||||||
|
|
||||||
|
import "google/protobuf/descriptor.proto";
|
||||||
|
import "protoc-gen-openapiv2/options/openapiv2.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options";
|
||||||
|
|
||||||
|
extend google.protobuf.FileOptions {
|
||||||
|
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||||
|
//
|
||||||
|
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||||
|
// different descriptor messages.
|
||||||
|
Swagger openapiv2_swagger = 1042;
|
||||||
|
}
|
||||||
|
extend google.protobuf.MethodOptions {
|
||||||
|
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||||
|
//
|
||||||
|
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||||
|
// different descriptor messages.
|
||||||
|
Operation openapiv2_operation = 1042;
|
||||||
|
}
|
||||||
|
extend google.protobuf.MessageOptions {
|
||||||
|
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||||
|
//
|
||||||
|
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||||
|
// different descriptor messages.
|
||||||
|
Schema openapiv2_schema = 1042;
|
||||||
|
}
|
||||||
|
extend google.protobuf.EnumOptions {
|
||||||
|
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||||
|
//
|
||||||
|
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||||
|
// different descriptor messages.
|
||||||
|
EnumSchema openapiv2_enum = 1042;
|
||||||
|
}
|
||||||
|
extend google.protobuf.ServiceOptions {
|
||||||
|
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||||
|
//
|
||||||
|
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||||
|
// different descriptor messages.
|
||||||
|
Tag openapiv2_tag = 1042;
|
||||||
|
}
|
||||||
|
extend google.protobuf.FieldOptions {
|
||||||
|
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||||
|
//
|
||||||
|
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||||
|
// different descriptor messages.
|
||||||
|
JSONSchema openapiv2_field = 1042;
|
||||||
|
}
|
||||||
@@ -0,0 +1,762 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package grpc.gateway.protoc_gen_openapiv2.options;
|
||||||
|
|
||||||
|
import "google/protobuf/struct.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options";
|
||||||
|
|
||||||
|
// Scheme describes the schemes supported by the OpenAPI Swagger
|
||||||
|
// and Operation objects.
|
||||||
|
enum Scheme {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
HTTP = 1;
|
||||||
|
HTTPS = 2;
|
||||||
|
WS = 3;
|
||||||
|
WSS = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Swagger` is a representation of OpenAPI v2 specification's Swagger object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#swaggerObject
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||||
|
// info: {
|
||||||
|
// title: "Echo API";
|
||||||
|
// version: "1.0";
|
||||||
|
// description: "";
|
||||||
|
// contact: {
|
||||||
|
// name: "gRPC-Gateway project";
|
||||||
|
// url: "https://github.com/grpc-ecosystem/grpc-gateway";
|
||||||
|
// email: "none@example.com";
|
||||||
|
// };
|
||||||
|
// license: {
|
||||||
|
// name: "BSD 3-Clause License";
|
||||||
|
// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE";
|
||||||
|
// };
|
||||||
|
// };
|
||||||
|
// schemes: HTTPS;
|
||||||
|
// consumes: "application/json";
|
||||||
|
// produces: "application/json";
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
message Swagger {
|
||||||
|
// Specifies the OpenAPI Specification version being used. It can be
|
||||||
|
// used by the OpenAPI UI and other clients to interpret the API listing. The
|
||||||
|
// value MUST be "2.0".
|
||||||
|
string swagger = 1;
|
||||||
|
// Provides metadata about the API. The metadata can be used by the
|
||||||
|
// clients if needed.
|
||||||
|
Info info = 2;
|
||||||
|
// The host (name or ip) serving the API. This MUST be the host only and does
|
||||||
|
// not include the scheme nor sub-paths. It MAY include a port. If the host is
|
||||||
|
// not included, the host serving the documentation is to be used (including
|
||||||
|
// the port). The host does not support path templating.
|
||||||
|
string host = 3;
|
||||||
|
// The base path on which the API is served, which is relative to the host. If
|
||||||
|
// it is not included, the API is served directly under the host. The value
|
||||||
|
// MUST start with a leading slash (/). The basePath does not support path
|
||||||
|
// templating.
|
||||||
|
// Note that using `base_path` does not change the endpoint paths that are
|
||||||
|
// generated in the resulting OpenAPI file. If you wish to use `base_path`
|
||||||
|
// with relatively generated OpenAPI paths, the `base_path` prefix must be
|
||||||
|
// manually removed from your `google.api.http` paths and your code changed to
|
||||||
|
// serve the API from the `base_path`.
|
||||||
|
string base_path = 4;
|
||||||
|
// The transfer protocol of the API. Values MUST be from the list: "http",
|
||||||
|
// "https", "ws", "wss". If the schemes is not included, the default scheme to
|
||||||
|
// be used is the one used to access the OpenAPI definition itself.
|
||||||
|
repeated Scheme schemes = 5;
|
||||||
|
// A list of MIME types the APIs can consume. This is global to all APIs but
|
||||||
|
// can be overridden on specific API calls. Value MUST be as described under
|
||||||
|
// Mime Types.
|
||||||
|
repeated string consumes = 6;
|
||||||
|
// A list of MIME types the APIs can produce. This is global to all APIs but
|
||||||
|
// can be overridden on specific API calls. Value MUST be as described under
|
||||||
|
// Mime Types.
|
||||||
|
repeated string produces = 7;
|
||||||
|
// field 8 is reserved for 'paths'.
|
||||||
|
reserved 8;
|
||||||
|
// field 9 is reserved for 'definitions', which at this time are already
|
||||||
|
// exposed as and customizable as proto messages.
|
||||||
|
reserved 9;
|
||||||
|
// An object to hold responses that can be used across operations. This
|
||||||
|
// property does not define global responses for all operations.
|
||||||
|
map<string, Response> responses = 10;
|
||||||
|
// Security scheme definitions that can be used across the specification.
|
||||||
|
SecurityDefinitions security_definitions = 11;
|
||||||
|
// A declaration of which security schemes are applied for the API as a whole.
|
||||||
|
// The list of values describes alternative security schemes that can be used
|
||||||
|
// (that is, there is a logical OR between the security requirements).
|
||||||
|
// Individual operations can override this definition.
|
||||||
|
repeated SecurityRequirement security = 12;
|
||||||
|
// A list of tags for API documentation control. Tags can be used for logical
|
||||||
|
// grouping of operations by resources or any other qualifier.
|
||||||
|
repeated Tag tags = 13;
|
||||||
|
// Additional external documentation.
|
||||||
|
ExternalDocumentation external_docs = 14;
|
||||||
|
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||||
|
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||||
|
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||||
|
map<string, google.protobuf.Value> extensions = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Operation` is a representation of OpenAPI v2 specification's Operation object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#operationObject
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// service EchoService {
|
||||||
|
// rpc Echo(SimpleMessage) returns (SimpleMessage) {
|
||||||
|
// option (google.api.http) = {
|
||||||
|
// get: "/v1/example/echo/{id}"
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||||
|
// summary: "Get a message.";
|
||||||
|
// operation_id: "getMessage";
|
||||||
|
// tags: "echo";
|
||||||
|
// responses: {
|
||||||
|
// key: "200"
|
||||||
|
// value: {
|
||||||
|
// description: "OK";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
message Operation {
|
||||||
|
// A list of tags for API documentation control. Tags can be used for logical
|
||||||
|
// grouping of operations by resources or any other qualifier.
|
||||||
|
repeated string tags = 1;
|
||||||
|
// A short summary of what the operation does. For maximum readability in the
|
||||||
|
// swagger-ui, this field SHOULD be less than 120 characters.
|
||||||
|
string summary = 2;
|
||||||
|
// A verbose explanation of the operation behavior. GFM syntax can be used for
|
||||||
|
// rich text representation.
|
||||||
|
string description = 3;
|
||||||
|
// Additional external documentation for this operation.
|
||||||
|
ExternalDocumentation external_docs = 4;
|
||||||
|
// Unique string used to identify the operation. The id MUST be unique among
|
||||||
|
// all operations described in the API. Tools and libraries MAY use the
|
||||||
|
// operationId to uniquely identify an operation, therefore, it is recommended
|
||||||
|
// to follow common programming naming conventions.
|
||||||
|
string operation_id = 5;
|
||||||
|
// A list of MIME types the operation can consume. This overrides the consumes
|
||||||
|
// definition at the OpenAPI Object. An empty value MAY be used to clear the
|
||||||
|
// global definition. Value MUST be as described under Mime Types.
|
||||||
|
repeated string consumes = 6;
|
||||||
|
// A list of MIME types the operation can produce. This overrides the produces
|
||||||
|
// definition at the OpenAPI Object. An empty value MAY be used to clear the
|
||||||
|
// global definition. Value MUST be as described under Mime Types.
|
||||||
|
repeated string produces = 7;
|
||||||
|
// field 8 is reserved for 'parameters'.
|
||||||
|
reserved 8;
|
||||||
|
// The list of possible responses as they are returned from executing this
|
||||||
|
// operation.
|
||||||
|
map<string, Response> responses = 9;
|
||||||
|
// The transfer protocol for the operation. Values MUST be from the list:
|
||||||
|
// "http", "https", "ws", "wss". The value overrides the OpenAPI Object
|
||||||
|
// schemes definition.
|
||||||
|
repeated Scheme schemes = 10;
|
||||||
|
// Declares this operation to be deprecated. Usage of the declared operation
|
||||||
|
// should be refrained. Default value is false.
|
||||||
|
bool deprecated = 11;
|
||||||
|
// A declaration of which security schemes are applied for this operation. The
|
||||||
|
// list of values describes alternative security schemes that can be used
|
||||||
|
// (that is, there is a logical OR between the security requirements). This
|
||||||
|
// definition overrides any declared top-level security. To remove a top-level
|
||||||
|
// security declaration, an empty array can be used.
|
||||||
|
repeated SecurityRequirement security = 12;
|
||||||
|
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||||
|
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||||
|
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||||
|
map<string, google.protobuf.Value> extensions = 13;
|
||||||
|
// Custom parameters such as HTTP request headers.
|
||||||
|
// See: https://swagger.io/docs/specification/2-0/describing-parameters/
|
||||||
|
// and https://swagger.io/specification/v2/#parameter-object.
|
||||||
|
Parameters parameters = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Parameters` is a representation of OpenAPI v2 specification's parameters object.
|
||||||
|
// Note: This technically breaks compatibility with the OpenAPI 2 definition structure as we only
|
||||||
|
// allow header parameters to be set here since we do not want users specifying custom non-header
|
||||||
|
// parameters beyond those inferred from the Protobuf schema.
|
||||||
|
// See: https://swagger.io/specification/v2/#parameter-object
|
||||||
|
message Parameters {
|
||||||
|
// `Headers` is one or more HTTP header parameter.
|
||||||
|
// See: https://swagger.io/docs/specification/2-0/describing-parameters/#header-parameters
|
||||||
|
repeated HeaderParameter headers = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `HeaderParameter` a HTTP header parameter.
|
||||||
|
// See: https://swagger.io/specification/v2/#parameter-object
|
||||||
|
message HeaderParameter {
|
||||||
|
// `Type` is a supported HTTP header type.
|
||||||
|
// See https://swagger.io/specification/v2/#parameterType.
|
||||||
|
enum Type {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
STRING = 1;
|
||||||
|
NUMBER = 2;
|
||||||
|
INTEGER = 3;
|
||||||
|
BOOLEAN = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Name` is the header name.
|
||||||
|
string name = 1;
|
||||||
|
// `Description` is a short description of the header.
|
||||||
|
string description = 2;
|
||||||
|
// `Type` is the type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported.
|
||||||
|
// See: https://swagger.io/specification/v2/#parameterType.
|
||||||
|
Type type = 3;
|
||||||
|
// `Format` The extending format for the previously mentioned type.
|
||||||
|
string format = 4;
|
||||||
|
// `Required` indicates if the header is optional
|
||||||
|
bool required = 5;
|
||||||
|
// field 6 is reserved for 'items', but in OpenAPI-specific way.
|
||||||
|
reserved 6;
|
||||||
|
// field 7 is reserved `Collection Format`. Determines the format of the array if type array is used.
|
||||||
|
reserved 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Header` is a representation of OpenAPI v2 specification's Header object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#headerObject
|
||||||
|
//
|
||||||
|
message Header {
|
||||||
|
// `Description` is a short description of the header.
|
||||||
|
string description = 1;
|
||||||
|
// The type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported.
|
||||||
|
string type = 2;
|
||||||
|
// `Format` The extending format for the previously mentioned type.
|
||||||
|
string format = 3;
|
||||||
|
// field 4 is reserved for 'items', but in OpenAPI-specific way.
|
||||||
|
reserved 4;
|
||||||
|
// field 5 is reserved `Collection Format` Determines the format of the array if type array is used.
|
||||||
|
reserved 5;
|
||||||
|
// `Default` Declares the value of the header that the server will use if none is provided.
|
||||||
|
// See: https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2.
|
||||||
|
// Unlike JSON Schema this value MUST conform to the defined type for the header.
|
||||||
|
string default = 6;
|
||||||
|
// field 7 is reserved for 'maximum'.
|
||||||
|
reserved 7;
|
||||||
|
// field 8 is reserved for 'exclusiveMaximum'.
|
||||||
|
reserved 8;
|
||||||
|
// field 9 is reserved for 'minimum'.
|
||||||
|
reserved 9;
|
||||||
|
// field 10 is reserved for 'exclusiveMinimum'.
|
||||||
|
reserved 10;
|
||||||
|
// field 11 is reserved for 'maxLength'.
|
||||||
|
reserved 11;
|
||||||
|
// field 12 is reserved for 'minLength'.
|
||||||
|
reserved 12;
|
||||||
|
// 'Pattern' See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.3.
|
||||||
|
string pattern = 13;
|
||||||
|
// field 14 is reserved for 'maxItems'.
|
||||||
|
reserved 14;
|
||||||
|
// field 15 is reserved for 'minItems'.
|
||||||
|
reserved 15;
|
||||||
|
// field 16 is reserved for 'uniqueItems'.
|
||||||
|
reserved 16;
|
||||||
|
// field 17 is reserved for 'enum'.
|
||||||
|
reserved 17;
|
||||||
|
// field 18 is reserved for 'multipleOf'.
|
||||||
|
reserved 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Response` is a representation of OpenAPI v2 specification's Response object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#responseObject
|
||||||
|
//
|
||||||
|
message Response {
|
||||||
|
// `Description` is a short description of the response.
|
||||||
|
// GFM syntax can be used for rich text representation.
|
||||||
|
string description = 1;
|
||||||
|
// `Schema` optionally defines the structure of the response.
|
||||||
|
// If `Schema` is not provided, it means there is no content to the response.
|
||||||
|
Schema schema = 2;
|
||||||
|
// `Headers` A list of headers that are sent with the response.
|
||||||
|
// `Header` name is expected to be a string in the canonical format of the MIME header key
|
||||||
|
// See: https://golang.org/pkg/net/textproto/#CanonicalMIMEHeaderKey
|
||||||
|
map<string, Header> headers = 3;
|
||||||
|
// `Examples` gives per-mimetype response examples.
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#example-object
|
||||||
|
map<string, string> examples = 4;
|
||||||
|
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||||
|
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||||
|
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||||
|
map<string, google.protobuf.Value> extensions = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Info` is a representation of OpenAPI v2 specification's Info object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#infoObject
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||||
|
// info: {
|
||||||
|
// title: "Echo API";
|
||||||
|
// version: "1.0";
|
||||||
|
// description: "";
|
||||||
|
// contact: {
|
||||||
|
// name: "gRPC-Gateway project";
|
||||||
|
// url: "https://github.com/grpc-ecosystem/grpc-gateway";
|
||||||
|
// email: "none@example.com";
|
||||||
|
// };
|
||||||
|
// license: {
|
||||||
|
// name: "BSD 3-Clause License";
|
||||||
|
// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE";
|
||||||
|
// };
|
||||||
|
// };
|
||||||
|
// ...
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
message Info {
|
||||||
|
// The title of the application.
|
||||||
|
string title = 1;
|
||||||
|
// A short description of the application. GFM syntax can be used for rich
|
||||||
|
// text representation.
|
||||||
|
string description = 2;
|
||||||
|
// The Terms of Service for the API.
|
||||||
|
string terms_of_service = 3;
|
||||||
|
// The contact information for the exposed API.
|
||||||
|
Contact contact = 4;
|
||||||
|
// The license information for the exposed API.
|
||||||
|
License license = 5;
|
||||||
|
// Provides the version of the application API (not to be confused
|
||||||
|
// with the specification version).
|
||||||
|
string version = 6;
|
||||||
|
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||||
|
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||||
|
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||||
|
map<string, google.protobuf.Value> extensions = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Contact` is a representation of OpenAPI v2 specification's Contact object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#contactObject
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||||
|
// info: {
|
||||||
|
// ...
|
||||||
|
// contact: {
|
||||||
|
// name: "gRPC-Gateway project";
|
||||||
|
// url: "https://github.com/grpc-ecosystem/grpc-gateway";
|
||||||
|
// email: "none@example.com";
|
||||||
|
// };
|
||||||
|
// ...
|
||||||
|
// };
|
||||||
|
// ...
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
message Contact {
|
||||||
|
// The identifying name of the contact person/organization.
|
||||||
|
string name = 1;
|
||||||
|
// The URL pointing to the contact information. MUST be in the format of a
|
||||||
|
// URL.
|
||||||
|
string url = 2;
|
||||||
|
// The email address of the contact person/organization. MUST be in the format
|
||||||
|
// of an email address.
|
||||||
|
string email = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `License` is a representation of OpenAPI v2 specification's License object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#licenseObject
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||||
|
// info: {
|
||||||
|
// ...
|
||||||
|
// license: {
|
||||||
|
// name: "BSD 3-Clause License";
|
||||||
|
// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE";
|
||||||
|
// };
|
||||||
|
// ...
|
||||||
|
// };
|
||||||
|
// ...
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
message License {
|
||||||
|
// The license name used for the API.
|
||||||
|
string name = 1;
|
||||||
|
// A URL to the license used for the API. MUST be in the format of a URL.
|
||||||
|
string url = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `ExternalDocumentation` is a representation of OpenAPI v2 specification's
|
||||||
|
// ExternalDocumentation object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#externalDocumentationObject
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||||
|
// ...
|
||||||
|
// external_docs: {
|
||||||
|
// description: "More about gRPC-Gateway";
|
||||||
|
// url: "https://github.com/grpc-ecosystem/grpc-gateway";
|
||||||
|
// }
|
||||||
|
// ...
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
message ExternalDocumentation {
|
||||||
|
// A short description of the target documentation. GFM syntax can be used for
|
||||||
|
// rich text representation.
|
||||||
|
string description = 1;
|
||||||
|
// The URL for the target documentation. Value MUST be in the format
|
||||||
|
// of a URL.
|
||||||
|
string url = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Schema` is a representation of OpenAPI v2 specification's Schema object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject
|
||||||
|
//
|
||||||
|
message Schema {
|
||||||
|
JSONSchema json_schema = 1;
|
||||||
|
// Adds support for polymorphism. The discriminator is the schema property
|
||||||
|
// name that is used to differentiate between other schema that inherit this
|
||||||
|
// schema. The property name used MUST be defined at this schema and it MUST
|
||||||
|
// be in the required property list. When used, the value MUST be the name of
|
||||||
|
// this schema or any schema that inherits it.
|
||||||
|
string discriminator = 2;
|
||||||
|
// Relevant only for Schema "properties" definitions. Declares the property as
|
||||||
|
// "read only". This means that it MAY be sent as part of a response but MUST
|
||||||
|
// NOT be sent as part of the request. Properties marked as readOnly being
|
||||||
|
// true SHOULD NOT be in the required list of the defined schema. Default
|
||||||
|
// value is false.
|
||||||
|
bool read_only = 3;
|
||||||
|
// field 4 is reserved for 'xml'.
|
||||||
|
reserved 4;
|
||||||
|
// Additional external documentation for this schema.
|
||||||
|
ExternalDocumentation external_docs = 5;
|
||||||
|
// A free-form property to include an example of an instance for this schema in JSON.
|
||||||
|
// This is copied verbatim to the output.
|
||||||
|
string example = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `EnumSchema` is subset of fields from the OpenAPI v2 specification's Schema object.
|
||||||
|
// Only fields that are applicable to Enums are included
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum) = {
|
||||||
|
// ...
|
||||||
|
// title: "MyEnum";
|
||||||
|
// description:"This is my nice enum";
|
||||||
|
// example: "ZERO";
|
||||||
|
// required: true;
|
||||||
|
// ...
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
message EnumSchema {
|
||||||
|
// A short description of the schema.
|
||||||
|
string description = 1;
|
||||||
|
string default = 2;
|
||||||
|
// The title of the schema.
|
||||||
|
string title = 3;
|
||||||
|
bool required = 4;
|
||||||
|
bool read_only = 5;
|
||||||
|
// Additional external documentation for this schema.
|
||||||
|
ExternalDocumentation external_docs = 6;
|
||||||
|
string example = 7;
|
||||||
|
// Ref is used to define an external reference to include in the message.
|
||||||
|
// This could be a fully qualified proto message reference, and that type must
|
||||||
|
// be imported into the protofile. If no message is identified, the Ref will
|
||||||
|
// be used verbatim in the output.
|
||||||
|
// For example:
|
||||||
|
// `ref: ".google.protobuf.Timestamp"`.
|
||||||
|
string ref = 8;
|
||||||
|
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||||
|
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||||
|
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||||
|
map<string, google.protobuf.Value> extensions = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `JSONSchema` represents properties from JSON Schema taken, and as used, in
|
||||||
|
// the OpenAPI v2 spec.
|
||||||
|
//
|
||||||
|
// This includes changes made by OpenAPI v2.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject
|
||||||
|
//
|
||||||
|
// See also: https://cswr.github.io/JsonSchema/spec/basic_types/,
|
||||||
|
// https://github.com/json-schema-org/json-schema-spec/blob/master/schema.json
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// message SimpleMessage {
|
||||||
|
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
|
||||||
|
// json_schema: {
|
||||||
|
// title: "SimpleMessage"
|
||||||
|
// description: "A simple message."
|
||||||
|
// required: ["id"]
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// // Id represents the message identifier.
|
||||||
|
// string id = 1; [
|
||||||
|
// (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
|
// description: "The unique identifier of the simple message."
|
||||||
|
// }];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
message JSONSchema {
|
||||||
|
// field 1 is reserved for '$id', omitted from OpenAPI v2.
|
||||||
|
reserved 1;
|
||||||
|
// field 2 is reserved for '$schema', omitted from OpenAPI v2.
|
||||||
|
reserved 2;
|
||||||
|
// Ref is used to define an external reference to include in the message.
|
||||||
|
// This could be a fully qualified proto message reference, and that type must
|
||||||
|
// be imported into the protofile. If no message is identified, the Ref will
|
||||||
|
// be used verbatim in the output.
|
||||||
|
// For example:
|
||||||
|
// `ref: ".google.protobuf.Timestamp"`.
|
||||||
|
string ref = 3;
|
||||||
|
// field 4 is reserved for '$comment', omitted from OpenAPI v2.
|
||||||
|
reserved 4;
|
||||||
|
// The title of the schema.
|
||||||
|
string title = 5;
|
||||||
|
// A short description of the schema.
|
||||||
|
string description = 6;
|
||||||
|
string default = 7;
|
||||||
|
bool read_only = 8;
|
||||||
|
// A free-form property to include a JSON example of this field. This is copied
|
||||||
|
// verbatim to the output swagger.json. Quotes must be escaped.
|
||||||
|
// This property is the same for 2.0 and 3.0.0 https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md#schemaObject https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject
|
||||||
|
string example = 9;
|
||||||
|
double multiple_of = 10;
|
||||||
|
// Maximum represents an inclusive upper limit for a numeric instance. The
|
||||||
|
// value of MUST be a number,
|
||||||
|
double maximum = 11;
|
||||||
|
bool exclusive_maximum = 12;
|
||||||
|
// minimum represents an inclusive lower limit for a numeric instance. The
|
||||||
|
// value of MUST be a number,
|
||||||
|
double minimum = 13;
|
||||||
|
bool exclusive_minimum = 14;
|
||||||
|
uint64 max_length = 15;
|
||||||
|
uint64 min_length = 16;
|
||||||
|
string pattern = 17;
|
||||||
|
// field 18 is reserved for 'additionalItems', omitted from OpenAPI v2.
|
||||||
|
reserved 18;
|
||||||
|
// field 19 is reserved for 'items', but in OpenAPI-specific way.
|
||||||
|
// TODO(ivucica): add 'items'?
|
||||||
|
reserved 19;
|
||||||
|
uint64 max_items = 20;
|
||||||
|
uint64 min_items = 21;
|
||||||
|
bool unique_items = 22;
|
||||||
|
// field 23 is reserved for 'contains', omitted from OpenAPI v2.
|
||||||
|
reserved 23;
|
||||||
|
uint64 max_properties = 24;
|
||||||
|
uint64 min_properties = 25;
|
||||||
|
repeated string required = 26;
|
||||||
|
// field 27 is reserved for 'additionalProperties', but in OpenAPI-specific
|
||||||
|
// way. TODO(ivucica): add 'additionalProperties'?
|
||||||
|
reserved 27;
|
||||||
|
// field 28 is reserved for 'definitions', omitted from OpenAPI v2.
|
||||||
|
reserved 28;
|
||||||
|
// field 29 is reserved for 'properties', but in OpenAPI-specific way.
|
||||||
|
// TODO(ivucica): add 'additionalProperties'?
|
||||||
|
reserved 29;
|
||||||
|
// following fields are reserved, as the properties have been omitted from
|
||||||
|
// OpenAPI v2:
|
||||||
|
// patternProperties, dependencies, propertyNames, const
|
||||||
|
reserved 30 to 33;
|
||||||
|
// Items in 'array' must be unique.
|
||||||
|
repeated string array = 34;
|
||||||
|
|
||||||
|
enum JSONSchemaSimpleTypes {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
ARRAY = 1;
|
||||||
|
BOOLEAN = 2;
|
||||||
|
INTEGER = 3;
|
||||||
|
NULL = 4;
|
||||||
|
NUMBER = 5;
|
||||||
|
OBJECT = 6;
|
||||||
|
STRING = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
repeated JSONSchemaSimpleTypes type = 35;
|
||||||
|
// `Format`
|
||||||
|
string format = 36;
|
||||||
|
// following fields are reserved, as the properties have been omitted from
|
||||||
|
// OpenAPI v2: contentMediaType, contentEncoding, if, then, else
|
||||||
|
reserved 37 to 41;
|
||||||
|
// field 42 is reserved for 'allOf', but in OpenAPI-specific way.
|
||||||
|
// TODO(ivucica): add 'allOf'?
|
||||||
|
reserved 42;
|
||||||
|
// following fields are reserved, as the properties have been omitted from
|
||||||
|
// OpenAPI v2:
|
||||||
|
// anyOf, oneOf, not
|
||||||
|
reserved 43 to 45;
|
||||||
|
// Items in `enum` must be unique https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1
|
||||||
|
repeated string enum = 46;
|
||||||
|
|
||||||
|
// Additional field level properties used when generating the OpenAPI v2 file.
|
||||||
|
FieldConfiguration field_configuration = 1001;
|
||||||
|
|
||||||
|
// 'FieldConfiguration' provides additional field level properties used when generating the OpenAPI v2 file.
|
||||||
|
// These properties are not defined by OpenAPIv2, but they are used to control the generation.
|
||||||
|
message FieldConfiguration {
|
||||||
|
// Alternative parameter name when used as path parameter. If set, this will
|
||||||
|
// be used as the complete parameter name when this field is used as a path
|
||||||
|
// parameter. Use this to avoid having auto generated path parameter names
|
||||||
|
// for overlapping paths.
|
||||||
|
string path_param_name = 47;
|
||||||
|
// Declares this field to be deprecated. Allows for the generated OpenAPI
|
||||||
|
// parameter to be marked as deprecated without affecting the proto field.
|
||||||
|
bool deprecated = 49;
|
||||||
|
}
|
||||||
|
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||||
|
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||||
|
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||||
|
map<string, google.protobuf.Value> extensions = 48;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Tag` is a representation of OpenAPI v2 specification's Tag object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#tagObject
|
||||||
|
//
|
||||||
|
message Tag {
|
||||||
|
// The name of the tag. Use it to allow override of the name of a
|
||||||
|
// global Tag object, then use that name to reference the tag throughout the
|
||||||
|
// OpenAPI file.
|
||||||
|
string name = 1;
|
||||||
|
// A short description for the tag. GFM syntax can be used for rich text
|
||||||
|
// representation.
|
||||||
|
string description = 2;
|
||||||
|
// Additional external documentation for this tag.
|
||||||
|
ExternalDocumentation external_docs = 3;
|
||||||
|
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||||
|
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||||
|
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||||
|
map<string, google.protobuf.Value> extensions = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `SecurityDefinitions` is a representation of OpenAPI v2 specification's
|
||||||
|
// Security Definitions object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityDefinitionsObject
|
||||||
|
//
|
||||||
|
// A declaration of the security schemes available to be used in the
|
||||||
|
// specification. This does not enforce the security schemes on the operations
|
||||||
|
// and only serves to provide the relevant details for each scheme.
|
||||||
|
message SecurityDefinitions {
|
||||||
|
// A single security scheme definition, mapping a "name" to the scheme it
|
||||||
|
// defines.
|
||||||
|
map<string, SecurityScheme> security = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `SecurityScheme` is a representation of OpenAPI v2 specification's
|
||||||
|
// Security Scheme object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securitySchemeObject
|
||||||
|
//
|
||||||
|
// Allows the definition of a security scheme that can be used by the
|
||||||
|
// operations. Supported schemes are basic authentication, an API key (either as
|
||||||
|
// a header or as a query parameter) and OAuth2's common flows (implicit,
|
||||||
|
// password, application and access code).
|
||||||
|
message SecurityScheme {
|
||||||
|
// The type of the security scheme. Valid values are "basic",
|
||||||
|
// "apiKey" or "oauth2".
|
||||||
|
enum Type {
|
||||||
|
TYPE_INVALID = 0;
|
||||||
|
TYPE_BASIC = 1;
|
||||||
|
TYPE_API_KEY = 2;
|
||||||
|
TYPE_OAUTH2 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The location of the API key. Valid values are "query" or "header".
|
||||||
|
enum In {
|
||||||
|
IN_INVALID = 0;
|
||||||
|
IN_QUERY = 1;
|
||||||
|
IN_HEADER = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The flow used by the OAuth2 security scheme. Valid values are
|
||||||
|
// "implicit", "password", "application" or "accessCode".
|
||||||
|
enum Flow {
|
||||||
|
FLOW_INVALID = 0;
|
||||||
|
FLOW_IMPLICIT = 1;
|
||||||
|
FLOW_PASSWORD = 2;
|
||||||
|
FLOW_APPLICATION = 3;
|
||||||
|
FLOW_ACCESS_CODE = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The type of the security scheme. Valid values are "basic",
|
||||||
|
// "apiKey" or "oauth2".
|
||||||
|
Type type = 1;
|
||||||
|
// A short description for security scheme.
|
||||||
|
string description = 2;
|
||||||
|
// The name of the header or query parameter to be used.
|
||||||
|
// Valid for apiKey.
|
||||||
|
string name = 3;
|
||||||
|
// The location of the API key. Valid values are "query" or
|
||||||
|
// "header".
|
||||||
|
// Valid for apiKey.
|
||||||
|
In in = 4;
|
||||||
|
// The flow used by the OAuth2 security scheme. Valid values are
|
||||||
|
// "implicit", "password", "application" or "accessCode".
|
||||||
|
// Valid for oauth2.
|
||||||
|
Flow flow = 5;
|
||||||
|
// The authorization URL to be used for this flow. This SHOULD be in
|
||||||
|
// the form of a URL.
|
||||||
|
// Valid for oauth2/implicit and oauth2/accessCode.
|
||||||
|
string authorization_url = 6;
|
||||||
|
// The token URL to be used for this flow. This SHOULD be in the
|
||||||
|
// form of a URL.
|
||||||
|
// Valid for oauth2/password, oauth2/application and oauth2/accessCode.
|
||||||
|
string token_url = 7;
|
||||||
|
// The available scopes for the OAuth2 security scheme.
|
||||||
|
// Valid for oauth2.
|
||||||
|
Scopes scopes = 8;
|
||||||
|
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||||
|
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||||
|
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||||
|
map<string, google.protobuf.Value> extensions = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `SecurityRequirement` is a representation of OpenAPI v2 specification's
|
||||||
|
// Security Requirement object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityRequirementObject
|
||||||
|
//
|
||||||
|
// Lists the required security schemes to execute this operation. The object can
|
||||||
|
// have multiple security schemes declared in it which are all required (that
|
||||||
|
// is, there is a logical AND between the schemes).
|
||||||
|
//
|
||||||
|
// The name used for each property MUST correspond to a security scheme
|
||||||
|
// declared in the Security Definitions.
|
||||||
|
message SecurityRequirement {
|
||||||
|
// If the security scheme is of type "oauth2", then the value is a list of
|
||||||
|
// scope names required for the execution. For other security scheme types,
|
||||||
|
// the array MUST be empty.
|
||||||
|
message SecurityRequirementValue {
|
||||||
|
repeated string scope = 1;
|
||||||
|
}
|
||||||
|
// Each name must correspond to a security scheme which is declared in
|
||||||
|
// the Security Definitions. If the security scheme is of type "oauth2",
|
||||||
|
// then the value is a list of scope names required for the execution.
|
||||||
|
// For other security scheme types, the array MUST be empty.
|
||||||
|
map<string, SecurityRequirementValue> security_requirement = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Scopes` is a representation of OpenAPI v2 specification's Scopes object.
|
||||||
|
//
|
||||||
|
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#scopesObject
|
||||||
|
//
|
||||||
|
// Lists the available scopes for an OAuth2 security scheme.
|
||||||
|
message Scopes {
|
||||||
|
// Maps between a name of a scope to a short description of it (as the value
|
||||||
|
// of the property).
|
||||||
|
map<string, string> scope = 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.36.12
|
||||||
|
// protoc v7.36.0
|
||||||
|
// source: api/messages/message.proto
|
||||||
|
|
||||||
|
package messages
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Message) Reset() {
|
||||||
|
*x = Message{}
|
||||||
|
mi := &file_api_messages_message_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Message) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Message) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Message) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_api_messages_message_proto_msgTypes[0]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Message.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Message) Descriptor() ([]byte, []int) {
|
||||||
|
return file_api_messages_message_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_api_messages_message_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
const file_api_messages_message_proto_rawDesc = "" +
|
||||||
|
"\n" +
|
||||||
|
"\x1aapi/messages/message.proto\x12\fapi.messages\"\t\n" +
|
||||||
|
"\aMessageB\x15Z\x13pkg/pb/api/messagesb\x06proto3"
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_api_messages_message_proto_rawDescOnce sync.Once
|
||||||
|
file_api_messages_message_proto_rawDescData []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_api_messages_message_proto_rawDescGZIP() []byte {
|
||||||
|
file_api_messages_message_proto_rawDescOnce.Do(func() {
|
||||||
|
file_api_messages_message_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_messages_message_proto_rawDesc), len(file_api_messages_message_proto_rawDesc)))
|
||||||
|
})
|
||||||
|
return file_api_messages_message_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_api_messages_message_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||||
|
var file_api_messages_message_proto_goTypes = []any{
|
||||||
|
(*Message)(nil), // 0: api.messages.Message
|
||||||
|
}
|
||||||
|
var file_api_messages_message_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_api_messages_message_proto_init() }
|
||||||
|
func file_api_messages_message_proto_init() {
|
||||||
|
if File_api_messages_message_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_messages_message_proto_rawDesc), len(file_api_messages_message_proto_rawDesc)),
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 1,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_api_messages_message_proto_goTypes,
|
||||||
|
DependencyIndexes: file_api_messages_message_proto_depIdxs,
|
||||||
|
MessageInfos: file_api_messages_message_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_api_messages_message_proto = out.File
|
||||||
|
file_api_messages_message_proto_goTypes = nil
|
||||||
|
file_api_messages_message_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.36.12
|
||||||
|
// protoc v7.36.0
|
||||||
|
// source: api/services/core.proto
|
||||||
|
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options"
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
unsafe "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
var File_api_services_core_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
const file_api_services_core_proto_rawDesc = "" +
|
||||||
|
"\n" +
|
||||||
|
"\x17api/services/core.proto\x12\fapi.services\x1a.protoc-gen-openapiv2/options/annotations.protoB4\x92A\x1c\x12\x18\n" +
|
||||||
|
"\vApplication2\t%version%Z\x00Z\x13pkg/pb/api/servicesb\x06proto3"
|
||||||
|
|
||||||
|
var file_api_services_core_proto_goTypes = []any{}
|
||||||
|
var file_api_services_core_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_api_services_core_proto_init() }
|
||||||
|
func file_api_services_core_proto_init() {
|
||||||
|
if File_api_services_core_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_services_core_proto_rawDesc), len(file_api_services_core_proto_rawDesc)),
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 0,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_api_services_core_proto_goTypes,
|
||||||
|
DependencyIndexes: file_api_services_core_proto_depIdxs,
|
||||||
|
}.Build()
|
||||||
|
File_api_services_core_proto = out.File
|
||||||
|
file_api_services_core_proto_goTypes = nil
|
||||||
|
file_api_services_core_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,205 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.36.12
|
||||||
|
// protoc v7.36.0
|
||||||
|
// source: api/services/debug_service.proto
|
||||||
|
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetVersion struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetVersion) Reset() {
|
||||||
|
*x = GetVersion{}
|
||||||
|
mi := &file_api_services_debug_service_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetVersion) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetVersion) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetVersion) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_api_services_debug_service_proto_msgTypes[0]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GetVersion.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetVersion) Descriptor() ([]byte, []int) {
|
||||||
|
return file_api_services_debug_service_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetVersion_Request struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetVersion_Request) Reset() {
|
||||||
|
*x = GetVersion_Request{}
|
||||||
|
mi := &file_api_services_debug_service_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetVersion_Request) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetVersion_Request) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetVersion_Request) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_api_services_debug_service_proto_msgTypes[1]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GetVersion_Request.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetVersion_Request) Descriptor() ([]byte, []int) {
|
||||||
|
return file_api_services_debug_service_proto_rawDescGZIP(), []int{0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetVersion_Response struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetVersion_Response) Reset() {
|
||||||
|
*x = GetVersion_Response{}
|
||||||
|
mi := &file_api_services_debug_service_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetVersion_Response) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetVersion_Response) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetVersion_Response) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_api_services_debug_service_proto_msgTypes[2]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GetVersion_Response.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetVersion_Response) Descriptor() ([]byte, []int) {
|
||||||
|
return file_api_services_debug_service_proto_rawDescGZIP(), []int{0, 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetVersion_Response) GetVersion() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Version
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_api_services_debug_service_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
const file_api_services_debug_service_proto_rawDesc = "" +
|
||||||
|
"\n" +
|
||||||
|
" api/services/debug_service.proto\x12\fapi.services\x1a\x1cgoogle/api/annotations.proto\"=\n" +
|
||||||
|
"\n" +
|
||||||
|
"GetVersion\x1a\t\n" +
|
||||||
|
"\aRequest\x1a$\n" +
|
||||||
|
"\bResponse\x12\x18\n" +
|
||||||
|
"\aversion\x18\x01 \x01(\tR\aversion2v\n" +
|
||||||
|
"\bDebugAPI\x12j\n" +
|
||||||
|
"\n" +
|
||||||
|
"GetVersion\x12 .api.services.GetVersion.Request\x1a!.api.services.GetVersion.Response\"\x17\x82\xd3\xe4\x93\x02\x11\x12\x0f/api/v1/versionB\x15Z\x13pkg/pb/api/servicesb\x06proto3"
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_api_services_debug_service_proto_rawDescOnce sync.Once
|
||||||
|
file_api_services_debug_service_proto_rawDescData []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_api_services_debug_service_proto_rawDescGZIP() []byte {
|
||||||
|
file_api_services_debug_service_proto_rawDescOnce.Do(func() {
|
||||||
|
file_api_services_debug_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_services_debug_service_proto_rawDesc), len(file_api_services_debug_service_proto_rawDesc)))
|
||||||
|
})
|
||||||
|
return file_api_services_debug_service_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_api_services_debug_service_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||||
|
var file_api_services_debug_service_proto_goTypes = []any{
|
||||||
|
(*GetVersion)(nil), // 0: api.services.GetVersion
|
||||||
|
(*GetVersion_Request)(nil), // 1: api.services.GetVersion.Request
|
||||||
|
(*GetVersion_Response)(nil), // 2: api.services.GetVersion.Response
|
||||||
|
}
|
||||||
|
var file_api_services_debug_service_proto_depIdxs = []int32{
|
||||||
|
1, // 0: api.services.DebugAPI.GetVersion:input_type -> api.services.GetVersion.Request
|
||||||
|
2, // 1: api.services.DebugAPI.GetVersion:output_type -> api.services.GetVersion.Response
|
||||||
|
1, // [1:2] is the sub-list for method output_type
|
||||||
|
0, // [0:1] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_api_services_debug_service_proto_init() }
|
||||||
|
func file_api_services_debug_service_proto_init() {
|
||||||
|
if File_api_services_debug_service_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_services_debug_service_proto_rawDesc), len(file_api_services_debug_service_proto_rawDesc)),
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 3,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 1,
|
||||||
|
},
|
||||||
|
GoTypes: file_api_services_debug_service_proto_goTypes,
|
||||||
|
DependencyIndexes: file_api_services_debug_service_proto_depIdxs,
|
||||||
|
MessageInfos: file_api_services_debug_service_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_api_services_debug_service_proto = out.File
|
||||||
|
file_api_services_debug_service_proto_goTypes = nil
|
||||||
|
file_api_services_debug_service_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||||
|
// source: api/services/debug_service.proto
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package services is a reverse proxy.
|
||||||
|
|
||||||
|
It translates gRPC into RESTful JSON APIs.
|
||||||
|
*/
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||||
|
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/grpclog"
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Suppress "imported and not used" errors
|
||||||
|
var (
|
||||||
|
_ codes.Code
|
||||||
|
_ io.Reader
|
||||||
|
_ status.Status
|
||||||
|
_ = errors.New
|
||||||
|
_ = runtime.String
|
||||||
|
_ = utilities.NewDoubleArray
|
||||||
|
_ = metadata.Join
|
||||||
|
)
|
||||||
|
|
||||||
|
func request_DebugAPI_GetVersion_0(ctx context.Context, marshaler runtime.Marshaler, client DebugAPIClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var (
|
||||||
|
protoReq GetVersion_Request
|
||||||
|
metadata runtime.ServerMetadata
|
||||||
|
)
|
||||||
|
if req.Body != nil {
|
||||||
|
_, _ = io.Copy(io.Discard, req.Body)
|
||||||
|
}
|
||||||
|
msg, err := client.GetVersion(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||||
|
return msg, metadata, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func local_request_DebugAPI_GetVersion_0(ctx context.Context, marshaler runtime.Marshaler, server DebugAPIServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
|
var (
|
||||||
|
protoReq GetVersion_Request
|
||||||
|
metadata runtime.ServerMetadata
|
||||||
|
)
|
||||||
|
msg, err := server.GetVersion(ctx, &protoReq)
|
||||||
|
return msg, metadata, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterDebugAPIHandlerServer registers the http handlers for service DebugAPI to "mux".
|
||||||
|
// UnaryRPC :call DebugAPIServer directly.
|
||||||
|
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||||
|
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterDebugAPIHandlerFromEndpoint instead.
|
||||||
|
// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
|
||||||
|
func RegisterDebugAPIHandlerServer(ctx context.Context, mux *runtime.ServeMux, server DebugAPIServer) error {
|
||||||
|
mux.Handle(http.MethodGet, pattern_DebugAPI_GetVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
var stream runtime.ServerTransportStream
|
||||||
|
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/api.services.DebugAPI/GetVersion", runtime.WithHTTPPathPattern("/api/v1/version"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := local_request_DebugAPI_GetVersion_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||||
|
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||||
|
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
forward_DebugAPI_GetVersion_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterDebugAPIHandlerFromEndpoint is same as RegisterDebugAPIHandler but
|
||||||
|
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||||
|
func RegisterDebugAPIHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||||
|
conn, err := grpc.NewClient(endpoint, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
if cerr := conn.Close(); cerr != nil {
|
||||||
|
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
<-ctx.Done()
|
||||||
|
if cerr := conn.Close(); cerr != nil {
|
||||||
|
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}()
|
||||||
|
return RegisterDebugAPIHandler(ctx, mux, conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterDebugAPIHandler registers the http handlers for service DebugAPI to "mux".
|
||||||
|
// The handlers forward requests to the grpc endpoint over "conn".
|
||||||
|
func RegisterDebugAPIHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||||
|
return RegisterDebugAPIHandlerClient(ctx, mux, NewDebugAPIClient(conn))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterDebugAPIHandlerClient registers the http handlers for service DebugAPI
|
||||||
|
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "DebugAPIClient".
|
||||||
|
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "DebugAPIClient"
|
||||||
|
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||||
|
// "DebugAPIClient" to call the correct interceptors. This client ignores the HTTP middlewares.
|
||||||
|
func RegisterDebugAPIHandlerClient(ctx context.Context, mux *runtime.ServeMux, client DebugAPIClient) error {
|
||||||
|
mux.Handle(http.MethodGet, pattern_DebugAPI_GetVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
|
defer cancel()
|
||||||
|
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||||
|
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/api.services.DebugAPI/GetVersion", runtime.WithHTTPPathPattern("/api/v1/version"))
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, md, err := request_DebugAPI_GetVersion_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||||
|
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||||
|
if err != nil {
|
||||||
|
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
forward_DebugAPI_GetVersion_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
pattern_DebugAPI_GetVersion_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "version"}, ""))
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
forward_DebugAPI_GetVersion_0 = runtime.ForwardResponseMessage
|
||||||
|
)
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.6.2
|
||||||
|
// - protoc v7.36.0
|
||||||
|
// source: api/services/debug_service.proto
|
||||||
|
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
|
codes "google.golang.org/grpc/codes"
|
||||||
|
status "google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.64.0 or later.
|
||||||
|
const _ = grpc.SupportPackageIsVersion9
|
||||||
|
|
||||||
|
const (
|
||||||
|
DebugAPI_GetVersion_FullMethodName = "/api.services.DebugAPI/GetVersion"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DebugAPIClient is the client API for DebugAPI service.
|
||||||
|
//
|
||||||
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
|
type DebugAPIClient interface {
|
||||||
|
GetVersion(ctx context.Context, in *GetVersion_Request, opts ...grpc.CallOption) (*GetVersion_Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type debugAPIClient struct {
|
||||||
|
cc grpc.ClientConnInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDebugAPIClient(cc grpc.ClientConnInterface) DebugAPIClient {
|
||||||
|
return &debugAPIClient{cc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *debugAPIClient) GetVersion(ctx context.Context, in *GetVersion_Request, opts ...grpc.CallOption) (*GetVersion_Response, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(GetVersion_Response)
|
||||||
|
err := c.cc.Invoke(ctx, DebugAPI_GetVersion_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DebugAPIServer is the server API for DebugAPI service.
|
||||||
|
// All implementations must embed UnimplementedDebugAPIServer
|
||||||
|
// for forward compatibility.
|
||||||
|
type DebugAPIServer interface {
|
||||||
|
GetVersion(context.Context, *GetVersion_Request) (*GetVersion_Response, error)
|
||||||
|
mustEmbedUnimplementedDebugAPIServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedDebugAPIServer must be embedded to have
|
||||||
|
// forward compatible implementations.
|
||||||
|
//
|
||||||
|
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||||
|
// pointer dereference when methods are called.
|
||||||
|
type UnimplementedDebugAPIServer struct{}
|
||||||
|
|
||||||
|
func (UnimplementedDebugAPIServer) GetVersion(context.Context, *GetVersion_Request) (*GetVersion_Response, error) {
|
||||||
|
return nil, status.Error(codes.Unimplemented, "method GetVersion not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedDebugAPIServer) mustEmbedUnimplementedDebugAPIServer() {}
|
||||||
|
func (UnimplementedDebugAPIServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
|
// UnsafeDebugAPIServer may be embedded to opt out of forward compatibility for this service.
|
||||||
|
// Use of this interface is not recommended, as added methods to DebugAPIServer will
|
||||||
|
// result in compilation errors.
|
||||||
|
type UnsafeDebugAPIServer interface {
|
||||||
|
mustEmbedUnimplementedDebugAPIServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterDebugAPIServer(s grpc.ServiceRegistrar, srv DebugAPIServer) {
|
||||||
|
// If the following call panics, it indicates UnimplementedDebugAPIServer was
|
||||||
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||||
|
t.testEmbeddedByValue()
|
||||||
|
}
|
||||||
|
s.RegisterService(&DebugAPI_ServiceDesc, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _DebugAPI_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(GetVersion_Request)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(DebugAPIServer).GetVersion(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: DebugAPI_GetVersion_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(DebugAPIServer).GetVersion(ctx, req.(*GetVersion_Request))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DebugAPI_ServiceDesc is the grpc.ServiceDesc for DebugAPI service.
|
||||||
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
|
// and not to be introspected or modified (even as a copy)
|
||||||
|
var DebugAPI_ServiceDesc = grpc.ServiceDesc{
|
||||||
|
ServiceName: "api.services.DebugAPI",
|
||||||
|
HandlerType: (*DebugAPIServer)(nil),
|
||||||
|
Methods: []grpc.MethodDesc{
|
||||||
|
{
|
||||||
|
MethodName: "GetVersion",
|
||||||
|
Handler: _DebugAPI_GetVersion_Handler,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Streams: []grpc.StreamDesc{},
|
||||||
|
Metadata: "api/services/debug_service.proto",
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
!dist/.gitkeep
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# React + TypeScript + Vite
|
||||||
|
|
||||||
|
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||||
|
|
||||||
|
Currently, two official plugins are available:
|
||||||
|
|
||||||
|
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
|
||||||
|
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
|
||||||
|
|
||||||
|
## React Compiler
|
||||||
|
|
||||||
|
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
|
||||||
|
|
||||||
|
## Expanding the ESLint configuration
|
||||||
|
|
||||||
|
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['dist']),
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
// Other configs...
|
||||||
|
|
||||||
|
// Remove tseslint.configs.recommended and replace with this
|
||||||
|
tseslint.configs.recommendedTypeChecked,
|
||||||
|
// Alternatively, use this for stricter rules
|
||||||
|
tseslint.configs.strictTypeChecked,
|
||||||
|
// Optionally, add this for stylistic rules
|
||||||
|
tseslint.configs.stylisticTypeChecked,
|
||||||
|
|
||||||
|
// Other configs...
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
// other options...
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also install [eslint-plugin-react-x](https://npmx.dev/package/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://npmx.dev/package/eslint-plugin-react-dom) for React-specific lint rules:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// eslint.config.js
|
||||||
|
import reactX from 'eslint-plugin-react-x'
|
||||||
|
import reactDom from 'eslint-plugin-react-dom'
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['dist']),
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
// Other configs...
|
||||||
|
// Enable lint rules for React
|
||||||
|
reactX.configs['recommended-typescript'],
|
||||||
|
// Enable lint rules for React DOM
|
||||||
|
reactDom.configs.recommended,
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
// other options...
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
```
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import js from '@eslint/js'
|
||||||
|
import globals from 'globals'
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks'
|
||||||
|
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||||
|
import tseslint from 'typescript-eslint'
|
||||||
|
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['dist']),
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
js.configs.recommended,
|
||||||
|
tseslint.configs.recommended,
|
||||||
|
reactHooks.configs.flat.recommended,
|
||||||
|
reactRefresh.configs.vite,
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
globals: globals.browser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>app</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "app",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc -b && vite build",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^19.2.8",
|
||||||
|
"react-dom": "^19.2.8"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^10.0.1",
|
||||||
|
"@types/node": "^24.13.3",
|
||||||
|
"@types/react": "^19.2.18",
|
||||||
|
"@types/react-dom": "^19.2.7",
|
||||||
|
"@vitejs/plugin-react": "^6.1.1",
|
||||||
|
"eslint": "^10.10.0",
|
||||||
|
"eslint-plugin-react-hooks": "^7.1.1",
|
||||||
|
"eslint-plugin-react-refresh": "^0.5.6",
|
||||||
|
"globals": "^17.12.0",
|
||||||
|
"typescript": "~6.0.2",
|
||||||
|
"typescript-eslint": "^8.69.0",
|
||||||
|
"vite": "^8.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 9.3 KiB |
@@ -0,0 +1,24 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<symbol id="bluesky-icon" viewBox="0 0 16 17">
|
||||||
|
<g clip-path="url(#bluesky-clip)"><path fill="#08060d" d="M7.75 7.735c-.693-1.348-2.58-3.86-4.334-5.097-1.68-1.187-2.32-.981-2.74-.79C.188 2.065.1 2.812.1 3.251s.241 3.602.398 4.13c.52 1.744 2.367 2.333 4.07 2.145-2.495.37-4.71 1.278-1.805 4.512 3.196 3.309 4.38-.71 4.987-2.746.608 2.036 1.307 5.91 4.93 2.746 2.72-2.746.747-4.143-1.747-4.512 1.702.189 3.55-.4 4.07-2.145.156-.528.397-3.691.397-4.13s-.088-1.186-.575-1.406c-.42-.19-1.06-.395-2.741.79-1.755 1.24-3.64 3.752-4.334 5.099"/></g>
|
||||||
|
<defs><clipPath id="bluesky-clip"><path fill="#fff" d="M.1.85h15.3v15.3H.1z"/></clipPath></defs>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="discord-icon" viewBox="0 0 20 19">
|
||||||
|
<path fill="#08060d" d="M16.224 3.768a14.5 14.5 0 0 0-3.67-1.153c-.158.286-.343.67-.47.976a13.5 13.5 0 0 0-4.067 0c-.128-.306-.317-.69-.476-.976A14.4 14.4 0 0 0 3.868 3.77C1.546 7.28.916 10.703 1.231 14.077a14.7 14.7 0 0 0 4.5 2.306q.545-.748.965-1.587a9.5 9.5 0 0 1-1.518-.74q.191-.14.372-.293c2.927 1.369 6.107 1.369 8.999 0q.183.152.372.294-.723.437-1.52.74.418.838.963 1.588a14.6 14.6 0 0 0 4.504-2.308c.37-3.911-.63-7.302-2.644-10.309m-9.13 8.234c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.894 0 1.614.82 1.599 1.82.001 1-.705 1.82-1.6 1.82m5.91 0c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.893 0 1.614.82 1.599 1.82 0 1-.706 1.82-1.6 1.82"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="documentation-icon" viewBox="0 0 21 20">
|
||||||
|
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="m15.5 13.333 1.533 1.322c.645.555.967.833.967 1.178s-.322.623-.967 1.179L15.5 18.333m-3.333-5-1.534 1.322c-.644.555-.966.833-.966 1.178s.322.623.966 1.179l1.534 1.321"/>
|
||||||
|
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M17.167 10.836v-4.32c0-1.41 0-2.117-.224-2.68-.359-.906-1.118-1.621-2.08-1.96-.599-.21-1.349-.21-2.848-.21-2.623 0-3.935 0-4.983.369-1.684.591-3.013 1.842-3.641 3.428C3 6.449 3 7.684 3 10.154v2.122c0 2.558 0 3.838.706 4.726q.306.383.713.671c.76.536 1.79.64 3.581.66"/>
|
||||||
|
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M3 10a2.78 2.78 0 0 1 2.778-2.778c.555 0 1.209.097 1.748-.047.48-.129.854-.503.982-.982.145-.54.048-1.194.048-1.749a2.78 2.78 0 0 1 2.777-2.777"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="github-icon" viewBox="0 0 19 19">
|
||||||
|
<path fill="#08060d" fill-rule="evenodd" d="M9.356 1.85C5.05 1.85 1.57 5.356 1.57 9.694a7.84 7.84 0 0 0 5.324 7.44c.387.079.528-.168.528-.376 0-.182-.013-.805-.013-1.454-2.165.467-2.616-.935-2.616-.935-.349-.91-.864-1.143-.864-1.143-.71-.48.051-.48.051-.48.787.051 1.2.805 1.2.805.695 1.194 1.817.857 2.268.649.064-.507.27-.857.49-1.052-1.728-.182-3.545-.857-3.545-3.87 0-.857.31-1.558.8-2.104-.078-.195-.349-1 .077-2.078 0 0 .657-.208 2.14.805a7.5 7.5 0 0 1 1.946-.26c.657 0 1.328.092 1.946.26 1.483-1.013 2.14-.805 2.14-.805.426 1.078.155 1.883.078 2.078.502.546.799 1.247.799 2.104 0 3.013-1.818 3.675-3.558 3.87.284.247.528.714.528 1.454 0 1.052-.012 1.896-.012 2.156 0 .208.142.455.528.377a7.84 7.84 0 0 0 5.324-7.441c.013-4.338-3.48-7.844-7.773-7.844" clip-rule="evenodd"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="social-icon" viewBox="0 0 20 20">
|
||||||
|
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M12.5 6.667a4.167 4.167 0 1 0-8.334 0 4.167 4.167 0 0 0 8.334 0"/>
|
||||||
|
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M2.5 16.667a5.833 5.833 0 0 1 8.75-5.053m3.837.474.513 1.035c.07.144.257.282.414.309l.93.155c.596.1.736.536.307.965l-.723.73a.64.64 0 0 0-.152.531l.207.903c.164.715-.213.991-.84.618l-.872-.52a.63.63 0 0 0-.577 0l-.872.52c-.624.373-1.003.094-.84-.618l.207-.903a.64.64 0 0 0-.152-.532l-.723-.729c-.426-.43-.289-.864.306-.964l.93-.156a.64.64 0 0 0 .412-.31l.513-1.034c.28-.562.735-.562 1.012 0"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="x-icon" viewBox="0 0 19 19">
|
||||||
|
<path fill="#08060d" fill-rule="evenodd" d="M1.893 1.98c.052.072 1.245 1.769 2.653 3.77l2.892 4.114c.183.261.333.48.333.486s-.068.089-.152.183l-.522.593-.765.867-3.597 4.087c-.375.426-.734.834-.798.905a1 1 0 0 0-.118.148c0 .01.236.017.664.017h.663l.729-.83c.4-.457.796-.906.879-.999a692 692 0 0 0 1.794-2.038c.034-.037.301-.34.594-.675l.551-.624.345-.392a7 7 0 0 1 .34-.374c.006 0 .93 1.306 2.052 2.903l2.084 2.965.045.063h2.275c1.87 0 2.273-.003 2.266-.021-.008-.02-1.098-1.572-3.894-5.547-2.013-2.862-2.28-3.246-2.273-3.266.008-.019.282-.332 2.085-2.38l2-2.274 1.567-1.782c.022-.028-.016-.03-.65-.03h-.674l-.3.342a871 871 0 0 1-1.782 2.025c-.067.075-.405.458-.75.852a100 100 0 0 1-.803.91c-.148.172-.299.344-.99 1.127-.304.343-.32.358-.345.327-.015-.019-.904-1.282-1.976-2.808L6.365 1.85H1.8zm1.782.91 8.078 11.294c.772 1.08 1.413 1.973 1.425 1.984.016.017.241.02 1.05.017l1.03-.004-2.694-3.766L7.796 5.75 5.722 2.852l-1.039-.004-1.039-.004z" clip-rule="evenodd"/>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.9 KiB |
@@ -0,0 +1,184 @@
|
|||||||
|
.counter {
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: var(--accent);
|
||||||
|
background: var(--accent-bg);
|
||||||
|
border: 2px solid transparent;
|
||||||
|
transition: border-color 0.3s;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--accent-border);
|
||||||
|
}
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 2px solid var(--accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.base,
|
||||||
|
.framework,
|
||||||
|
.vite {
|
||||||
|
inset-inline: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.base {
|
||||||
|
width: 170px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.framework,
|
||||||
|
.vite {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.framework {
|
||||||
|
z-index: 1;
|
||||||
|
top: 34px;
|
||||||
|
height: 28px;
|
||||||
|
transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
|
||||||
|
scale(1.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vite {
|
||||||
|
z-index: 0;
|
||||||
|
top: 107px;
|
||||||
|
height: 26px;
|
||||||
|
width: auto;
|
||||||
|
transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
|
||||||
|
scale(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#center {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 25px;
|
||||||
|
place-content: center;
|
||||||
|
place-items: center;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
padding: 32px 20px 24px;
|
||||||
|
gap: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#next-steps {
|
||||||
|
display: flex;
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
& > div {
|
||||||
|
flex: 1 1 0;
|
||||||
|
padding: 32px;
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
padding: 24px 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#docs {
|
||||||
|
border-right: 1px solid var(--border);
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
border-right: none;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#next-steps ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin: 32px 0 0;
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--text-h);
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: var(--social-bg);
|
||||||
|
display: flex;
|
||||||
|
padding: 6px 12px;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: box-shadow 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
.button-icon {
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
margin-top: 20px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
li {
|
||||||
|
flex: 1 1 calc(50% - 8px);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#spacer {
|
||||||
|
height: 88px;
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticks {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -4.5px;
|
||||||
|
border: 5px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
left: 0;
|
||||||
|
border-left-color: var(--border);
|
||||||
|
}
|
||||||
|
&::after {
|
||||||
|
right: 0;
|
||||||
|
border-right-color: var(--border);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import heroImg from './assets/hero.png'
|
||||||
|
import reactLogo from './assets/react.svg'
|
||||||
|
import viteLogo from './assets/vite.svg'
|
||||||
|
import './App.css'
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
const [count, setCount] = useState(0)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<section id="center">
|
||||||
|
<div className="hero">
|
||||||
|
<img src={heroImg} className="base" width="170" height="179" alt="" />
|
||||||
|
<img src={reactLogo} className="framework" alt="React logo" />
|
||||||
|
<img src={viteLogo} className="vite" alt="Vite logo" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h1>Get started</h1>
|
||||||
|
<p>
|
||||||
|
Edit <code>src/App.tsx</code> and save to test <code>HMR</code>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="counter"
|
||||||
|
onClick={() => setCount((count) => count + 1)}
|
||||||
|
>
|
||||||
|
Count is {count}
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div className="ticks"></div>
|
||||||
|
|
||||||
|
<section id="next-steps">
|
||||||
|
<div id="docs">
|
||||||
|
<svg className="icon" role="presentation" aria-hidden="true">
|
||||||
|
<use href="/icons.svg#documentation-icon"></use>
|
||||||
|
</svg>
|
||||||
|
<h2>Documentation</h2>
|
||||||
|
<p>Your questions, answered</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="https://vite.dev/" target="_blank">
|
||||||
|
<img className="logo" src={viteLogo} alt="" />
|
||||||
|
Explore Vite
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://react.dev/" target="_blank">
|
||||||
|
<img className="button-icon" src={reactLogo} alt="" />
|
||||||
|
Learn more
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="social">
|
||||||
|
<svg className="icon" role="presentation" aria-hidden="true">
|
||||||
|
<use href="/icons.svg#social-icon"></use>
|
||||||
|
</svg>
|
||||||
|
<h2>Connect with us</h2>
|
||||||
|
<p>Join the Vite community</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="https://github.com/vitejs/vite" target="_blank">
|
||||||
|
<svg
|
||||||
|
className="button-icon"
|
||||||
|
role="presentation"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<use href="/icons.svg#github-icon"></use>
|
||||||
|
</svg>
|
||||||
|
GitHub
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://chat.vite.dev/" target="_blank">
|
||||||
|
<svg
|
||||||
|
className="button-icon"
|
||||||
|
role="presentation"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<use href="/icons.svg#discord-icon"></use>
|
||||||
|
</svg>
|
||||||
|
Discord
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://x.com/vite_js" target="_blank">
|
||||||
|
<svg
|
||||||
|
className="button-icon"
|
||||||
|
role="presentation"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<use href="/icons.svg#x-icon"></use>
|
||||||
|
</svg>
|
||||||
|
X.com
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://bsky.app/profile/vite.dev" target="_blank">
|
||||||
|
<svg
|
||||||
|
className="button-icon"
|
||||||
|
role="presentation"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<use href="/icons.svg#bluesky-icon"></use>
|
||||||
|
</svg>
|
||||||
|
Bluesky
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div className="ticks"></div>
|
||||||
|
<section id="spacer"></section>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App
|
||||||
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
@@ -0,0 +1,111 @@
|
|||||||
|
:root {
|
||||||
|
--text: #6b6375;
|
||||||
|
--text-h: #08060d;
|
||||||
|
--bg: #fff;
|
||||||
|
--border: #e5e4e7;
|
||||||
|
--code-bg: #f4f3ec;
|
||||||
|
--accent: #aa3bff;
|
||||||
|
--accent-bg: rgba(170, 59, 255, 0.1);
|
||||||
|
--accent-border: rgba(170, 59, 255, 0.5);
|
||||||
|
--social-bg: rgba(244, 243, 236, 0.5);
|
||||||
|
--shadow:
|
||||||
|
rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;
|
||||||
|
|
||||||
|
--sans: system-ui, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
--heading: system-ui, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
--mono: ui-monospace, Consolas, monospace;
|
||||||
|
|
||||||
|
font: 18px/145% var(--sans);
|
||||||
|
letter-spacing: 0.18px;
|
||||||
|
color-scheme: light dark;
|
||||||
|
color: var(--text);
|
||||||
|
background: var(--bg);
|
||||||
|
font-synthesis: none;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--text: #9ca3af;
|
||||||
|
--text-h: #f3f4f6;
|
||||||
|
--bg: #16171d;
|
||||||
|
--border: #2e303a;
|
||||||
|
--code-bg: #1f2028;
|
||||||
|
--accent: #c084fc;
|
||||||
|
--accent-bg: rgba(192, 132, 252, 0.15);
|
||||||
|
--accent-border: rgba(192, 132, 252, 0.5);
|
||||||
|
--social-bg: rgba(47, 48, 58, 0.5);
|
||||||
|
--shadow:
|
||||||
|
rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#social .button-icon {
|
||||||
|
filter: invert(1) brightness(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#root {
|
||||||
|
width: 1126px;
|
||||||
|
max-width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
border-inline: 1px solid var(--border);
|
||||||
|
min-height: 100svh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
font-family: var(--heading);
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-h);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 56px;
|
||||||
|
letter-spacing: -1.68px;
|
||||||
|
margin: 32px 0;
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
font-size: 36px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 118%;
|
||||||
|
letter-spacing: -0.24px;
|
||||||
|
margin: 0 0 8px;
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code,
|
||||||
|
.counter {
|
||||||
|
font-family: var(--mono);
|
||||||
|
display: inline-flex;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: var(--text-h);
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 135%;
|
||||||
|
padding: 4px 8px;
|
||||||
|
background: var(--code-bg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { StrictMode } from 'react'
|
||||||
|
import { createRoot } from 'react-dom/client'
|
||||||
|
import './index.css'
|
||||||
|
import App from './App.tsx'
|
||||||
|
|
||||||
|
createRoot(document.getElementById('root')!).render(
|
||||||
|
<StrictMode>
|
||||||
|
<App />
|
||||||
|
</StrictMode>,
|
||||||
|
)
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
|
"target": "es2023",
|
||||||
|
"lib": ["ES2023", "DOM"],
|
||||||
|
"module": "esnext",
|
||||||
|
"types": ["vite/client"],
|
||||||
|
"allowArbitraryExtensions": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"erasableSyntaxOnly": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{ "path": "./tsconfig.app.json" },
|
||||||
|
{ "path": "./tsconfig.node.json" }
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||||
|
"target": "es2023",
|
||||||
|
"lib": ["ES2023"],
|
||||||
|
"types": ["node"],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"module": "nodenext",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"erasableSyntaxOnly": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
|
||||||
|
// https://vite.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
})
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package static
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed app/dist
|
||||||
|
var appFS embed.FS
|
||||||
|
|
||||||
|
var Handler = func() http.HandlerFunc {
|
||||||
|
distFS, err := fs.Sub(appFS, "app/dist")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
fileServer := http.FileServer(http.FS(distFS))
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
path := strings.TrimPrefix(r.URL.Path, "/")
|
||||||
|
_, err := distFS.Open(path)
|
||||||
|
if err == nil || path == "" {
|
||||||
|
fileServer.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
indexFile, err := distFS.Open("index.html")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "frontend build not found", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() { _ = indexFile.Close() }()
|
||||||
|
stat, _ := indexFile.Stat()
|
||||||
|
http.ServeContent(w, r, "index.html", stat.ModTime(), indexFile.(io.ReadSeeker))
|
||||||
|
}
|
||||||
|
}()
|
||||||