feat: embed frontend dist

prod
Steven 5 months ago
parent 70602b8c6c
commit 8aebafd531

@ -15,6 +15,7 @@ FROM golang:1.22-alpine AS backend
WORKDIR /backend-build
COPY . .
COPY --from=frontend /frontend-build/frontend/web/dist /backend-build/server/route/frontend/dist
RUN CGO_ENABLED=0 go build -o slash ./bin/slash/main.go
@ -25,7 +26,6 @@ WORKDIR /usr/local/slash
RUN apk add --no-cache tzdata
ENV TZ="UTC"
COPY --from=frontend /frontend-build/frontend/web/dist /usr/local/slash/dist
COPY --from=backend /backend-build/slash /usr/local/slash/
EXPOSE 5231

@ -6,20 +6,20 @@ managed:
except:
- buf.build/googleapis/googleapis
plugins:
- plugin: buf.build/protocolbuffers/go:v1.31.0
- plugin: buf.build/protocolbuffers/go
out: gen
opt:
- paths=source_relative
- plugin: buf.build/grpc/go:v1.3.0
- plugin: buf.build/grpc/go
out: gen
opt:
- paths=source_relative
- plugin: buf.build/grpc-ecosystem/gateway:v2.16.1
- plugin: buf.build/grpc-ecosystem/gateway
out: gen
opt:
- paths=source_relative
# Generate types for the web client.
- plugin: buf.build/community/stephenh-ts-proto:v1.152.1
- plugin: buf.build/community/stephenh-ts-proto
out: ../frontend/web/src/types/proto
# reference: https://github.com/deeplay-io/nice-grpc/blob/master/packages/nice-grpc-web/README.md#using-ts-proto
opt:
@ -31,7 +31,7 @@ plugins:
- esModuleInterop=true
- stringEnums=true
# Generate types for the extension client.
- plugin: buf.build/community/stephenh-ts-proto:v1.152.1
- plugin: buf.build/community/stephenh-ts-proto
out: ../frontend/extension/src/types/proto
# reference: https://github.com/deeplay-io/nice-grpc/blob/master/packages/nice-grpc-web/README.md#using-ts-proto
opt:
@ -42,10 +42,10 @@ plugins:
- useExactTypes=false
- esModuleInterop=true
- stringEnums=true
- plugin: buf.build/community/pseudomuto-doc:v1.5.1
- plugin: buf.build/community/pseudomuto-doc
out: gen
opt:
- markdown,README.md,source_relative
- plugin: buf.build/grpc-ecosystem/openapiv2:v2.19.0
- plugin: buf.build/grpc-ecosystem/openapiv2
out: gen
opt: output_format=yaml,allow_merge=true

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: api/v1/auth_service.proto

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: api/v1/collection_service.proto

@ -105,11 +105,7 @@ func request_CollectionService_CreateCollection_0(ctx context.Context, marshaler
var protoReq CreateCollectionRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Collection); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Collection); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -122,11 +118,7 @@ func local_request_CollectionService_CreateCollection_0(ctx context.Context, mar
var protoReq CreateCollectionRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Collection); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Collection); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -136,18 +128,14 @@ func local_request_CollectionService_CreateCollection_0(ctx context.Context, mar
}
var (
filter_CollectionService_UpdateCollection_0 = &utilities.DoubleArray{Encoding: map[string]int{"collection": 0, "id": 1}, Base: []int{1, 4, 5, 2, 0, 0, 0, 0}, Check: []int{0, 1, 1, 2, 4, 2, 2, 3}}
filter_CollectionService_UpdateCollection_0 = &utilities.DoubleArray{Encoding: map[string]int{"collection": 0, "id": 1}, Base: []int{1, 2, 1, 0, 0}, Check: []int{0, 1, 2, 3, 2}}
)
func request_CollectionService_UpdateCollection_0(ctx context.Context, marshaler runtime.Marshaler, client CollectionServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq UpdateCollectionRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Collection); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Collection); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -184,11 +172,7 @@ func local_request_CollectionService_UpdateCollection_0(ctx context.Context, mar
var protoReq UpdateCollectionRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Collection); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Collection); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: api/v1/common.proto

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: api/v1/shortcut_service.proto

@ -105,11 +105,7 @@ func request_ShortcutService_CreateShortcut_0(ctx context.Context, marshaler run
var protoReq CreateShortcutRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Shortcut); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Shortcut); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -122,11 +118,7 @@ func local_request_ShortcutService_CreateShortcut_0(ctx context.Context, marshal
var protoReq CreateShortcutRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Shortcut); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Shortcut); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -136,18 +128,14 @@ func local_request_ShortcutService_CreateShortcut_0(ctx context.Context, marshal
}
var (
filter_ShortcutService_UpdateShortcut_0 = &utilities.DoubleArray{Encoding: map[string]int{"shortcut": 0, "id": 1}, Base: []int{1, 4, 5, 2, 0, 0, 0, 0}, Check: []int{0, 1, 1, 2, 4, 2, 2, 3}}
filter_ShortcutService_UpdateShortcut_0 = &utilities.DoubleArray{Encoding: map[string]int{"shortcut": 0, "id": 1}, Base: []int{1, 2, 1, 0, 0}, Check: []int{0, 1, 2, 3, 2}}
)
func request_ShortcutService_UpdateShortcut_0(ctx context.Context, marshaler runtime.Marshaler, client ShortcutServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq UpdateShortcutRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Shortcut); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Shortcut); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -184,11 +172,7 @@ func local_request_ShortcutService_UpdateShortcut_0(ctx context.Context, marshal
var protoReq UpdateShortcutRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Shortcut); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Shortcut); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: api/v1/subscription_service.proto

@ -53,11 +53,7 @@ func request_SubscriptionService_UpdateSubscription_0(ctx context.Context, marsh
var protoReq UpdateSubscriptionRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -70,11 +66,7 @@ func local_request_SubscriptionService_UpdateSubscription_0(ctx context.Context,
var protoReq UpdateSubscriptionRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: api/v1/user_service.proto

@ -105,11 +105,7 @@ func request_UserService_CreateUser_0(ctx context.Context, marshaler runtime.Mar
var protoReq CreateUserRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.User); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.User); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -122,11 +118,7 @@ func local_request_UserService_CreateUser_0(ctx context.Context, marshaler runti
var protoReq CreateUserRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.User); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.User); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -136,7 +128,7 @@ func local_request_UserService_CreateUser_0(ctx context.Context, marshaler runti
}
var (
filter_UserService_UpdateUser_0 = &utilities.DoubleArray{Encoding: map[string]int{"user": 0, "id": 1}, Base: []int{1, 4, 5, 2, 0, 0, 0, 0}, Check: []int{0, 1, 1, 2, 4, 2, 2, 3}}
filter_UserService_UpdateUser_0 = &utilities.DoubleArray{Encoding: map[string]int{"user": 0, "id": 1}, Base: []int{1, 2, 1, 0, 0}, Check: []int{0, 1, 2, 3, 2}}
)
func request_UserService_UpdateUser_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@ -343,11 +335,7 @@ func request_UserService_CreateUserAccessToken_0(ctx context.Context, marshaler
var protoReq CreateUserAccessTokenRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -377,11 +365,7 @@ func local_request_UserService_CreateUserAccessToken_0(ctx context.Context, mars
var protoReq CreateUserAccessTokenRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: api/v1/user_setting_service.proto

@ -84,7 +84,7 @@ func local_request_UserSettingService_GetUserSetting_0(ctx context.Context, mars
}
var (
filter_UserSettingService_UpdateUserSetting_0 = &utilities.DoubleArray{Encoding: map[string]int{"user_setting": 0, "userSetting": 1, "id": 2}, Base: []int{1, 1, 2, 4, 0, 0, 0, 0}, Check: []int{0, 1, 1, 1, 2, 3, 4, 4}}
filter_UserSettingService_UpdateUserSetting_0 = &utilities.DoubleArray{Encoding: map[string]int{"user_setting": 0, "id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
)
func request_UserSettingService_UpdateUserSetting_0(ctx context.Context, marshaler runtime.Marshaler, client UserSettingServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: api/v1/workspace_service.proto

@ -68,7 +68,7 @@ func local_request_WorkspaceService_GetWorkspaceSetting_0(ctx context.Context, m
}
var (
filter_WorkspaceService_UpdateWorkspaceSetting_0 = &utilities.DoubleArray{Encoding: map[string]int{"setting": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}}
filter_WorkspaceService_UpdateWorkspaceSetting_0 = &utilities.DoubleArray{Encoding: map[string]int{"setting": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
)
func request_WorkspaceService_UpdateWorkspaceSetting_0(ctx context.Context, marshaler runtime.Marshaler, client WorkspaceServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: store/activity.proto

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: store/collection.proto

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: store/common.proto

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: store/shortcut.proto

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: store/user_setting.proto

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: store/workspace_setting.proto

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Slash</title>
</head>
<body>
No embeddable frontend found.
</body>
</html>

@ -2,9 +2,10 @@ package frontend
import (
"context"
"embed"
"fmt"
"io/fs"
"net/http"
"os"
"strings"
"github.com/labstack/echo/v4"
@ -17,6 +18,9 @@ import (
"github.com/yourselfhosted/slash/store"
)
//go:embed dist
var embeddedFiles embed.FS
const (
headerMetadataPlaceholder = "<!-- slash.metadata -->"
)
@ -37,10 +41,10 @@ func (s *FrontendService) Serve(ctx context.Context, e *echo.Echo) {
// Use echo static middleware to serve the built dist folder.
// refer: https://github.com/labstack/echo/blob/master/middleware/static.go
e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
HTML5: true,
Root: "dist",
HTML5: true,
Filesystem: getFileSystem("dist"),
Skipper: func(c echo.Context) bool {
return util.HasPrefixes(c.Path(), "/api", "/slash.api.v1", "/robots.txt", "/sitemap.xml", "/s/:shortcutName")
return util.HasPrefixes(c.Path(), "/api", "/slash.api.v1", "/robots.txt", "/sitemap.xml", "/s/:shortcutName", "/c/:collectionName")
},
}))
@ -138,6 +142,15 @@ Sitemap: %s/sitemap.xml`, instanceURL, instanceURL)
})
}
func getFileSystem(path string) http.FileSystem {
fs, err := fs.Sub(embeddedFiles, path)
if err != nil {
panic(err)
}
return http.FS(fs)
}
func generateShortcutMetadata(shortcut *storepb.Shortcut) *Metadata {
metadata := getDefaultMetadata()
title, description := shortcut.Title, shortcut.Description
@ -163,7 +176,7 @@ func generateCollectionMetadata(collection *storepb.Collection) *Metadata {
}
func getRawIndexHTML() string {
bytes, _ := os.ReadFile("dist/index.html")
bytes, _ := embeddedFiles.ReadFile("dist/index.html")
return string(bytes)
}

Loading…
Cancel
Save