feat: migrate part of shortcut store to v1

prod
Steven 1 year ago
parent 977ac76928
commit fcf5981b97

@ -8,6 +8,7 @@ import (
"strings"
"github.com/boojack/slash/internal/util"
storepb "github.com/boojack/slash/proto/gen/store"
"github.com/boojack/slash/store"
"github.com/labstack/echo/v4"
"github.com/pkg/errors"
@ -205,9 +206,9 @@ func (s *APIV1Service) registerShortcutRoutes(g *echo.Group) {
find.Tag = &tag
}
list := []*store.Shortcut{}
list := []*storepb.Shortcut{}
find.VisibilityList = []store.Visibility{store.VisibilityWorkspace, store.VisibilityPublic}
visibleShortcutList, err := s.Store.ListShortcuts(ctx, find)
visibleShortcutList, err := s.Store.ListShortcutsV1(ctx, find)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to fetch shortcut list, err: %s", err)).SetInternal(err)
}
@ -215,7 +216,7 @@ func (s *APIV1Service) registerShortcutRoutes(g *echo.Group) {
find.VisibilityList = []store.Visibility{store.VisibilityPrivate}
find.CreatorID = &userID
privateShortcutList, err := s.Store.ListShortcuts(ctx, find)
privateShortcutList, err := s.Store.ListShortcutsV1(ctx, find)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to fetch private shortcut list, err: %s", err)).SetInternal(err)
}
@ -223,7 +224,7 @@ func (s *APIV1Service) registerShortcutRoutes(g *echo.Group) {
shortcutMessageList := []*Shortcut{}
for _, shortcut := range list {
shortcutMessage, err := s.composeShortcut(ctx, convertShortcutFromStore(shortcut))
shortcutMessage, err := s.composeShortcut(ctx, convertShortcutFromStorepb(shortcut))
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to compose shortcut, err: %s", err)).SetInternal(err)
}
@ -349,6 +350,27 @@ func convertShortcutFromStore(shortcut *store.Shortcut) *Shortcut {
}
}
func convertShortcutFromStorepb(shortcut *storepb.Shortcut) *Shortcut {
return &Shortcut{
ID: shortcut.Id,
CreatedTs: shortcut.CreatedTs,
UpdatedTs: shortcut.UpdatedTs,
CreatorID: shortcut.CreatorId,
RowStatus: RowStatus(shortcut.RowStatus.String()),
Name: shortcut.Name,
Link: shortcut.Link,
Title: shortcut.Title,
Description: shortcut.Description,
Visibility: Visibility(shortcut.Visibility.String()),
Tags: shortcut.Tags,
OpenGraphMetadata: &OpenGraphMetadata{
Title: shortcut.OgMetadata.Title,
Description: shortcut.OgMetadata.Description,
Image: shortcut.OgMetadata.Image,
},
}
}
func (s *APIV1Service) createShortcutCreateActivity(ctx context.Context, shortcut *store.Shortcut) error {
payload := &ActivityShorcutCreatePayload{
ShortcutID: shortcut.ID,

@ -8,7 +8,7 @@ import (
func convertRowStatusFromStore(rowStatus store.RowStatus) apiv2pb.RowStatus {
switch rowStatus {
case store.Normal:
return apiv2pb.RowStatus_ACTIVE
return apiv2pb.RowStatus_NORMAL
case store.Archived:
return apiv2pb.RowStatus_ARCHIVED
default:

@ -7,7 +7,7 @@ option go_package = "gen/api/v2";
enum RowStatus {
ROW_STATUS_UNSPECIFIED = 0;
ACTIVE = 1;
NORMAL = 1;
ARCHIVED = 2;
}

@ -36,7 +36,7 @@
| Name | Number | Description |
| ---- | ------ | ----------- |
| ROW_STATUS_UNSPECIFIED | 0 | |
| ACTIVE | 1 | |
| NORMAL | 1 | |
| ARCHIVED | 2 | |

@ -24,7 +24,7 @@ type RowStatus int32
const (
RowStatus_ROW_STATUS_UNSPECIFIED RowStatus = 0
RowStatus_ACTIVE RowStatus = 1
RowStatus_NORMAL RowStatus = 1
RowStatus_ARCHIVED RowStatus = 2
)
@ -32,12 +32,12 @@ const (
var (
RowStatus_name = map[int32]string{
0: "ROW_STATUS_UNSPECIFIED",
1: "ACTIVE",
1: "NORMAL",
2: "ARCHIVED",
}
RowStatus_value = map[string]int32{
"ROW_STATUS_UNSPECIFIED": 0,
"ACTIVE": 1,
"NORMAL": 1,
"ARCHIVED": 2,
}
)
@ -77,7 +77,7 @@ var file_api_v2_common_proto_rawDesc = []byte{
0x2e, 0x76, 0x32, 0x2a, 0x41, 0x0a, 0x09, 0x52, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
0x12, 0x1a, 0x0a, 0x16, 0x52, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55,
0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06,
0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x52, 0x43, 0x48,
0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x52, 0x43, 0x48,
0x49, 0x56, 0x45, 0x44, 0x10, 0x02, 0x42, 0xa2, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x73,
0x6c, 0x61, 0x73, 0x68, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x42, 0x0b, 0x43, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68,

@ -0,0 +1,140 @@
# Protocol Documentation
<a name="top"></a>
## Table of Contents
- [store/common.proto](#store_common-proto)
- [RowStatus](#slash-store-RowStatus)
- [store/shortcut.proto](#store_shortcut-proto)
- [OpenGraphMetadata](#slash-store-OpenGraphMetadata)
- [Shortcut](#slash-store-Shortcut)
- [Visibility](#slash-store-Visibility)
- [Scalar Value Types](#scalar-value-types)
<a name="store_common-proto"></a>
<p align="right"><a href="#top">Top</a></p>
## store/common.proto
<a name="slash-store-RowStatus"></a>
### RowStatus
| Name | Number | Description |
| ---- | ------ | ----------- |
| ROW_STATUS_UNSPECIFIED | 0 | |
| NORMAL | 1 | |
| ARCHIVED | 2 | |
<a name="store_shortcut-proto"></a>
<p align="right"><a href="#top">Top</a></p>
## store/shortcut.proto
<a name="slash-store-OpenGraphMetadata"></a>
### OpenGraphMetadata
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| title | [string](#string) | | |
| description | [string](#string) | | |
| image | [string](#string) | | |
<a name="slash-store-Shortcut"></a>
### Shortcut
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| id | [int32](#int32) | | |
| creator_id | [int32](#int32) | | |
| created_ts | [int64](#int64) | | |
| updated_ts | [int64](#int64) | | |
| row_status | [RowStatus](#slash-store-RowStatus) | | |
| name | [string](#string) | | |
| link | [string](#string) | | |
| title | [string](#string) | | |
| tags | [string](#string) | repeated | |
| description | [string](#string) | | |
| visibility | [Visibility](#slash-store-Visibility) | | |
| og_metadata | [OpenGraphMetadata](#slash-store-OpenGraphMetadata) | | |
<a name="slash-store-Visibility"></a>
### Visibility
| Name | Number | Description |
| ---- | ------ | ----------- |
| VISIBILITY_UNSPECIFIED | 0 | |
| PRIVATE | 1 | |
| WORKSPACE | 2 | |
| PUBLIC | 3 | |
## Scalar Value Types
| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby |
| ----------- | ----- | --- | ---- | ------ | -- | -- | --- | ---- |
| <a name="double" /> double | | double | double | float | float64 | double | float | Float |
| <a name="float" /> float | | float | float | float | float32 | float | float | Float |
| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) |
| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) |
| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) |
| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum |
| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| <a name="bool" /> bool | | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass |
| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) |
| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) |

@ -0,0 +1,141 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc (unknown)
// source: store/common.proto
package store
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
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 RowStatus int32
const (
RowStatus_ROW_STATUS_UNSPECIFIED RowStatus = 0
RowStatus_NORMAL RowStatus = 1
RowStatus_ARCHIVED RowStatus = 2
)
// Enum value maps for RowStatus.
var (
RowStatus_name = map[int32]string{
0: "ROW_STATUS_UNSPECIFIED",
1: "NORMAL",
2: "ARCHIVED",
}
RowStatus_value = map[string]int32{
"ROW_STATUS_UNSPECIFIED": 0,
"NORMAL": 1,
"ARCHIVED": 2,
}
)
func (x RowStatus) Enum() *RowStatus {
p := new(RowStatus)
*p = x
return p
}
func (x RowStatus) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (RowStatus) Descriptor() protoreflect.EnumDescriptor {
return file_store_common_proto_enumTypes[0].Descriptor()
}
func (RowStatus) Type() protoreflect.EnumType {
return &file_store_common_proto_enumTypes[0]
}
func (x RowStatus) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use RowStatus.Descriptor instead.
func (RowStatus) EnumDescriptor() ([]byte, []int) {
return file_store_common_proto_rawDescGZIP(), []int{0}
}
var File_store_common_proto protoreflect.FileDescriptor
var file_store_common_proto_rawDesc = []byte{
0x0a, 0x12, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x73, 0x74, 0x6f, 0x72,
0x65, 0x2a, 0x41, 0x0a, 0x09, 0x52, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a,
0x0a, 0x16, 0x52, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53,
0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f,
0x52, 0x4d, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56,
0x45, 0x44, 0x10, 0x02, 0x42, 0x95, 0x01, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x6c, 0x61,
0x73, 0x68, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x6f, 0x6f, 0x6a, 0x61, 0x63, 0x6b, 0x2f, 0x73, 0x6c, 0x61, 0x73,
0x68, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x73, 0x74, 0x6f, 0x72,
0x65, 0xa2, 0x02, 0x03, 0x53, 0x53, 0x58, 0xaa, 0x02, 0x0b, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x2e,
0x53, 0x74, 0x6f, 0x72, 0x65, 0xca, 0x02, 0x0b, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x5c, 0x53, 0x74,
0x6f, 0x72, 0x65, 0xe2, 0x02, 0x17, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x5c, 0x53, 0x74, 0x6f, 0x72,
0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c,
0x53, 0x6c, 0x61, 0x73, 0x68, 0x3a, 0x3a, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (
file_store_common_proto_rawDescOnce sync.Once
file_store_common_proto_rawDescData = file_store_common_proto_rawDesc
)
func file_store_common_proto_rawDescGZIP() []byte {
file_store_common_proto_rawDescOnce.Do(func() {
file_store_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_store_common_proto_rawDescData)
})
return file_store_common_proto_rawDescData
}
var file_store_common_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_store_common_proto_goTypes = []interface{}{
(RowStatus)(0), // 0: slash.store.RowStatus
}
var file_store_common_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_store_common_proto_init() }
func file_store_common_proto_init() {
if File_store_common_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_store_common_proto_rawDesc,
NumEnums: 1,
NumMessages: 0,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_store_common_proto_goTypes,
DependencyIndexes: file_store_common_proto_depIdxs,
EnumInfos: file_store_common_proto_enumTypes,
}.Build()
File_store_common_proto = out.File
file_store_common_proto_rawDesc = nil
file_store_common_proto_goTypes = nil
file_store_common_proto_depIdxs = nil
}

@ -0,0 +1,411 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc (unknown)
// source: store/shortcut.proto
package store
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
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 Visibility int32
const (
Visibility_VISIBILITY_UNSPECIFIED Visibility = 0
Visibility_PRIVATE Visibility = 1
Visibility_WORKSPACE Visibility = 2
Visibility_PUBLIC Visibility = 3
)
// Enum value maps for Visibility.
var (
Visibility_name = map[int32]string{
0: "VISIBILITY_UNSPECIFIED",
1: "PRIVATE",
2: "WORKSPACE",
3: "PUBLIC",
}
Visibility_value = map[string]int32{
"VISIBILITY_UNSPECIFIED": 0,
"PRIVATE": 1,
"WORKSPACE": 2,
"PUBLIC": 3,
}
)
func (x Visibility) Enum() *Visibility {
p := new(Visibility)
*p = x
return p
}
func (x Visibility) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Visibility) Descriptor() protoreflect.EnumDescriptor {
return file_store_shortcut_proto_enumTypes[0].Descriptor()
}
func (Visibility) Type() protoreflect.EnumType {
return &file_store_shortcut_proto_enumTypes[0]
}
func (x Visibility) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Visibility.Descriptor instead.
func (Visibility) EnumDescriptor() ([]byte, []int) {
return file_store_shortcut_proto_rawDescGZIP(), []int{0}
}
type Shortcut struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
CreatorId int32 `protobuf:"varint,2,opt,name=creator_id,json=creatorId,proto3" json:"creator_id,omitempty"`
CreatedTs int64 `protobuf:"varint,3,opt,name=created_ts,json=createdTs,proto3" json:"created_ts,omitempty"`
UpdatedTs int64 `protobuf:"varint,4,opt,name=updated_ts,json=updatedTs,proto3" json:"updated_ts,omitempty"`
RowStatus RowStatus `protobuf:"varint,5,opt,name=row_status,json=rowStatus,proto3,enum=slash.store.RowStatus" json:"row_status,omitempty"`
Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"`
Link string `protobuf:"bytes,7,opt,name=link,proto3" json:"link,omitempty"`
Title string `protobuf:"bytes,8,opt,name=title,proto3" json:"title,omitempty"`
Tags []string `protobuf:"bytes,9,rep,name=tags,proto3" json:"tags,omitempty"`
Description string `protobuf:"bytes,10,opt,name=description,proto3" json:"description,omitempty"`
Visibility Visibility `protobuf:"varint,11,opt,name=visibility,proto3,enum=slash.store.Visibility" json:"visibility,omitempty"`
OgMetadata *OpenGraphMetadata `protobuf:"bytes,12,opt,name=og_metadata,json=ogMetadata,proto3" json:"og_metadata,omitempty"`
}
func (x *Shortcut) Reset() {
*x = Shortcut{}
if protoimpl.UnsafeEnabled {
mi := &file_store_shortcut_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Shortcut) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Shortcut) ProtoMessage() {}
func (x *Shortcut) ProtoReflect() protoreflect.Message {
mi := &file_store_shortcut_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Shortcut.ProtoReflect.Descriptor instead.
func (*Shortcut) Descriptor() ([]byte, []int) {
return file_store_shortcut_proto_rawDescGZIP(), []int{0}
}
func (x *Shortcut) GetId() int32 {
if x != nil {
return x.Id
}
return 0
}
func (x *Shortcut) GetCreatorId() int32 {
if x != nil {
return x.CreatorId
}
return 0
}
func (x *Shortcut) GetCreatedTs() int64 {
if x != nil {
return x.CreatedTs
}
return 0
}
func (x *Shortcut) GetUpdatedTs() int64 {
if x != nil {
return x.UpdatedTs
}
return 0
}
func (x *Shortcut) GetRowStatus() RowStatus {
if x != nil {
return x.RowStatus
}
return RowStatus_ROW_STATUS_UNSPECIFIED
}
func (x *Shortcut) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Shortcut) GetLink() string {
if x != nil {
return x.Link
}
return ""
}
func (x *Shortcut) GetTitle() string {
if x != nil {
return x.Title
}
return ""
}
func (x *Shortcut) GetTags() []string {
if x != nil {
return x.Tags
}
return nil
}
func (x *Shortcut) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
func (x *Shortcut) GetVisibility() Visibility {
if x != nil {
return x.Visibility
}
return Visibility_VISIBILITY_UNSPECIFIED
}
func (x *Shortcut) GetOgMetadata() *OpenGraphMetadata {
if x != nil {
return x.OgMetadata
}
return nil
}
type OpenGraphMetadata struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"`
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
Image string `protobuf:"bytes,3,opt,name=image,proto3" json:"image,omitempty"`
}
func (x *OpenGraphMetadata) Reset() {
*x = OpenGraphMetadata{}
if protoimpl.UnsafeEnabled {
mi := &file_store_shortcut_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *OpenGraphMetadata) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*OpenGraphMetadata) ProtoMessage() {}
func (x *OpenGraphMetadata) ProtoReflect() protoreflect.Message {
mi := &file_store_shortcut_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use OpenGraphMetadata.ProtoReflect.Descriptor instead.
func (*OpenGraphMetadata) Descriptor() ([]byte, []int) {
return file_store_shortcut_proto_rawDescGZIP(), []int{1}
}
func (x *OpenGraphMetadata) GetTitle() string {
if x != nil {
return x.Title
}
return ""
}
func (x *OpenGraphMetadata) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
func (x *OpenGraphMetadata) GetImage() string {
if x != nil {
return x.Image
}
return ""
}
var File_store_shortcut_proto protoreflect.FileDescriptor
var file_store_shortcut_proto_rawDesc = []byte{
0x0a, 0x14, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x63, 0x75, 0x74,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x73, 0x74,
0x6f, 0x72, 0x65, 0x1a, 0x12, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9c, 0x03, 0x0a, 0x08, 0x53, 0x68, 0x6f, 0x72,
0x74, 0x63, 0x75, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x5f,
0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f,
0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74,
0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x54, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x73,
0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x54,
0x73, 0x12, 0x35, 0x0a, 0x0a, 0x72, 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18,
0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x73, 0x74,
0x6f, 0x72, 0x65, 0x2e, 0x52, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x09, 0x72,
0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04,
0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b,
0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52,
0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x09,
0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0a,
0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0e,
0x32, 0x17, 0x2e, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x56,
0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62,
0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0b, 0x6f, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x61,
0x64, 0x61, 0x74, 0x61, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x6c, 0x61,
0x73, 0x68, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x47, 0x72, 0x61,
0x70, 0x68, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x6f, 0x67, 0x4d, 0x65,
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x61, 0x0a, 0x11, 0x4f, 0x70, 0x65, 0x6e, 0x47, 0x72,
0x61, 0x70, 0x68, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x74,
0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c,
0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01,
0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2a, 0x50, 0x0a, 0x0a, 0x56, 0x69, 0x73,
0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x49, 0x53, 0x49, 0x42,
0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x01,
0x12, 0x0d, 0x0a, 0x09, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x50, 0x41, 0x43, 0x45, 0x10, 0x02, 0x12,
0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x03, 0x42, 0x97, 0x01, 0x0a, 0x0f,
0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42,
0x0d, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x63, 0x75, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x6f, 0x6f,
0x6a, 0x61, 0x63, 0x6b, 0x2f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0xa2, 0x02, 0x03, 0x53, 0x53, 0x58,
0xaa, 0x02, 0x0b, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0xca, 0x02,
0x0b, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0xe2, 0x02, 0x17, 0x53,
0x6c, 0x61, 0x73, 0x68, 0x5c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65,
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x3a, 0x3a,
0x53, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_store_shortcut_proto_rawDescOnce sync.Once
file_store_shortcut_proto_rawDescData = file_store_shortcut_proto_rawDesc
)
func file_store_shortcut_proto_rawDescGZIP() []byte {
file_store_shortcut_proto_rawDescOnce.Do(func() {
file_store_shortcut_proto_rawDescData = protoimpl.X.CompressGZIP(file_store_shortcut_proto_rawDescData)
})
return file_store_shortcut_proto_rawDescData
}
var file_store_shortcut_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_store_shortcut_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_store_shortcut_proto_goTypes = []interface{}{
(Visibility)(0), // 0: slash.store.Visibility
(*Shortcut)(nil), // 1: slash.store.Shortcut
(*OpenGraphMetadata)(nil), // 2: slash.store.OpenGraphMetadata
(RowStatus)(0), // 3: slash.store.RowStatus
}
var file_store_shortcut_proto_depIdxs = []int32{
3, // 0: slash.store.Shortcut.row_status:type_name -> slash.store.RowStatus
0, // 1: slash.store.Shortcut.visibility:type_name -> slash.store.Visibility
2, // 2: slash.store.Shortcut.og_metadata:type_name -> slash.store.OpenGraphMetadata
3, // [3:3] is the sub-list for method output_type
3, // [3:3] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_store_shortcut_proto_init() }
func file_store_shortcut_proto_init() {
if File_store_shortcut_proto != nil {
return
}
file_store_common_proto_init()
if !protoimpl.UnsafeEnabled {
file_store_shortcut_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Shortcut); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_store_shortcut_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OpenGraphMetadata); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_store_shortcut_proto_rawDesc,
NumEnums: 1,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_store_shortcut_proto_goTypes,
DependencyIndexes: file_store_shortcut_proto_depIdxs,
EnumInfos: file_store_shortcut_proto_enumTypes,
MessageInfos: file_store_shortcut_proto_msgTypes,
}.Build()
File_store_shortcut_proto = out.File
file_store_shortcut_proto_rawDesc = nil
file_store_shortcut_proto_goTypes = nil
file_store_shortcut_proto_depIdxs = nil
}

@ -0,0 +1,13 @@
syntax = "proto3";
package slash.store;
option go_package = "gen/store";
enum RowStatus {
ROW_STATUS_UNSPECIFIED = 0;
NORMAL = 1;
ARCHIVED = 2;
}

@ -0,0 +1,51 @@
syntax = "proto3";
package slash.store;
import "store/common.proto";
option go_package = "gen/store";
message Shortcut {
int32 id = 1;
int32 creator_id = 2;
int64 created_ts = 3;
int64 updated_ts = 4;
RowStatus row_status = 5;
string name = 6;
string link = 7;
string title = 8;
repeated string tags = 9;
string description = 10;
Visibility visibility = 11;
OpenGraphMetadata og_metadata = 12;
}
message OpenGraphMetadata {
string title = 1;
string description = 2;
string image = 3;
}
enum Visibility {
VISIBILITY_UNSPECIFIED = 0;
PRIVATE = 1;
WORKSPACE = 2;
PUBLIC = 3;
}

@ -1,5 +1,9 @@
package store
import (
storepb "github.com/boojack/slash/proto/gen/store"
)
// RowStatus is the status for a row.
type RowStatus string
@ -19,3 +23,13 @@ func (e RowStatus) String() string {
}
return ""
}
func convertStorepbRowStatus(status string) storepb.RowStatus {
switch status {
case "NORMAL":
return storepb.RowStatus_NORMAL
case "ARCHIVED":
return storepb.RowStatus_ARCHIVED
}
return storepb.RowStatus_ROW_STATUS_UNSPECIFIED
}

@ -6,6 +6,9 @@ import (
"encoding/json"
"fmt"
"strings"
storepb "github.com/boojack/slash/proto/gen/store"
"google.golang.org/protobuf/encoding/protojson"
)
// Visibility is the type of a visibility.
@ -116,6 +119,41 @@ func (s *Store) CreateShortcut(ctx context.Context, create *Shortcut) (*Shortcut
return create, nil
}
func (s *Store) CreateShortcutV1(ctx context.Context, create *storepb.Shortcut) (*storepb.Shortcut, error) {
set := []string{"creator_id", "name", "link", "title", "description", "visibility", "tag"}
args := []any{create.CreatorId, create.Name, create.Link, create.Title, create.Description, create.Visibility.String(), strings.Join(create.Tags, " ")}
placeholder := []string{"?", "?", "?", "?", "?", "?", "?"}
if create.OgMetadata != nil {
set = append(set, "og_metadata")
openGraphMetadataBytes, err := protojson.Marshal(create.OgMetadata)
if err != nil {
return nil, err
}
args = append(args, string(openGraphMetadataBytes))
placeholder = append(placeholder, "?")
}
stmt := `
INSERT INTO shortcut (
` + strings.Join(set, ", ") + `
)
VALUES (` + strings.Join(placeholder, ",") + `)
RETURNING id, created_ts, updated_ts, row_status
`
var rowStatus string
if err := s.db.QueryRowContext(ctx, stmt, args...).Scan(
&create.Id,
&create.CreatedTs,
&create.UpdatedTs,
&rowStatus,
); err != nil {
return nil, err
}
create.RowStatus = convertStorepbRowStatus(rowStatus)
return create, nil
}
func (s *Store) UpdateShortcut(ctx context.Context, update *UpdateShortcut) (*Shortcut, error) {
set, args := []string{}, []any{}
if update.RowStatus != nil {
@ -277,6 +315,93 @@ func (s *Store) ListShortcuts(ctx context.Context, find *FindShortcut) ([]*Short
return list, nil
}
func (s *Store) ListShortcutsV1(ctx context.Context, find *FindShortcut) ([]*storepb.Shortcut, error) {
where, args := []string{"1 = 1"}, []any{}
if v := find.ID; v != nil {
where, args = append(where, "id = ?"), append(args, *v)
}
if v := find.CreatorID; v != nil {
where, args = append(where, "creator_id = ?"), append(args, *v)
}
if v := find.RowStatus; v != nil {
where, args = append(where, "row_status = ?"), append(args, *v)
}
if v := find.Name; v != nil {
where, args = append(where, "name = ?"), append(args, *v)
}
if v := find.VisibilityList; len(v) != 0 {
list := []string{}
for _, visibility := range v {
list = append(list, fmt.Sprintf("$%d", len(args)+1))
args = append(args, visibility)
}
where = append(where, fmt.Sprintf("visibility in (%s)", strings.Join(list, ",")))
}
if v := find.Tag; v != nil {
where, args = append(where, "tag LIKE ?"), append(args, "%"+*v+"%")
}
rows, err := s.db.QueryContext(ctx, `
SELECT
id,
creator_id,
created_ts,
updated_ts,
row_status,
name,
link,
title,
description,
visibility,
tag,
og_metadata
FROM shortcut
WHERE `+strings.Join(where, " AND ")+`
ORDER BY created_ts DESC`,
args...,
)
if err != nil {
return nil, err
}
defer rows.Close()
list := make([]*storepb.Shortcut, 0)
for rows.Next() {
shortcut := &storepb.Shortcut{}
var rowStatus, visibility, tags, openGraphMetadataString string
if err := rows.Scan(
&shortcut.Id,
&shortcut.CreatorId,
&shortcut.CreatedTs,
&shortcut.UpdatedTs,
&rowStatus,
&shortcut.Name,
&shortcut.Link,
&shortcut.Title,
&shortcut.Description,
&visibility,
&tags,
&openGraphMetadataString,
); err != nil {
return nil, err
}
shortcut.RowStatus = convertStorepbRowStatus(rowStatus)
shortcut.Visibility = storepb.Visibility(storepb.Visibility_value[visibility])
shortcut.Tags = strings.Split(tags, " ")
var ogMetadata storepb.OpenGraphMetadata
if err := protojson.Unmarshal([]byte(openGraphMetadataString), &ogMetadata); err != nil {
return nil, err
}
shortcut.OgMetadata = &ogMetadata
list = append(list, shortcut)
}
if err := rows.Err(); err != nil {
return nil, err
}
return list, nil
}
func (s *Store) GetShortcut(ctx context.Context, find *FindShortcut) (*Shortcut, error) {
if find.ID != nil {
if cache, ok := s.shortcutCache.Load(*find.ID); ok {
@ -298,6 +423,20 @@ func (s *Store) GetShortcut(ctx context.Context, find *FindShortcut) (*Shortcut,
return shortcut, nil
}
func (s *Store) GetShortcutV1(ctx context.Context, find *FindShortcut) (*storepb.Shortcut, error) {
shortcuts, err := s.ListShortcutsV1(ctx, find)
if err != nil {
return nil, err
}
if len(shortcuts) == 0 {
return nil, nil
}
shortcut := shortcuts[0]
return shortcut, nil
}
func (s *Store) DeleteShortcut(ctx context.Context, delete *DeleteShortcut) error {
if _, err := s.db.ExecContext(ctx, `DELETE FROM shortcut WHERE id = ?`, delete.ID); err != nil {
return err

@ -4,6 +4,7 @@ import (
"context"
"testing"
storepb "github.com/boojack/slash/proto/gen/store"
"github.com/boojack/slash/store"
"github.com/stretchr/testify/require"
)
@ -13,17 +14,17 @@ func TestShortcutStore(t *testing.T) {
ts := NewTestingStore(ctx, t)
user, err := createTestingAdminUser(ctx, ts)
require.NoError(t, err)
shortcut, err := ts.CreateShortcut(ctx, &store.Shortcut{
CreatorID: user.ID,
Name: "test",
Link: "https://test.link",
Description: "A test shortcut",
Visibility: store.VisibilityPrivate,
Tag: "test link",
OpenGraphMetadata: &store.OpenGraphMetadata{},
shortcut, err := ts.CreateShortcutV1(ctx, &storepb.Shortcut{
CreatorId: user.ID,
Name: "test",
Link: "https://test.link",
Description: "A test shortcut",
Visibility: storepb.Visibility_PRIVATE,
Tags: []string{"test", "shortcut"},
OgMetadata: &storepb.OpenGraphMetadata{},
})
require.NoError(t, err)
shortcuts, err := ts.ListShortcuts(ctx, &store.FindShortcut{
shortcuts, err := ts.ListShortcutsV1(ctx, &store.FindShortcut{
CreatorID: &user.ID,
})
require.NoError(t, err)
@ -31,22 +32,21 @@ func TestShortcutStore(t *testing.T) {
require.Equal(t, shortcut, shortcuts[0])
newLink := "https://new.link"
updatedShortcut, err := ts.UpdateShortcut(ctx, &store.UpdateShortcut{
ID: shortcut.ID,
ID: shortcut.Id,
Link: &newLink,
})
require.NoError(t, err)
require.Equal(t, newLink, updatedShortcut.Link)
tag := "test"
shortcut, err = ts.GetShortcut(ctx, &store.FindShortcut{
shortcut, err = ts.GetShortcutV1(ctx, &store.FindShortcut{
Tag: &tag,
})
require.NoError(t, err)
require.Equal(t, updatedShortcut, shortcut)
err = ts.DeleteShortcut(ctx, &store.DeleteShortcut{
ID: shortcut.ID,
ID: shortcut.Id,
})
require.NoError(t, err)
shortcuts, err = ts.ListShortcuts(ctx, &store.FindShortcut{
shortcuts, err = ts.ListShortcutsV1(ctx, &store.FindShortcut{
CreatorID: &user.ID,
})
require.NoError(t, err)

@ -41,7 +41,7 @@ func TestUserStore(t *testing.T) {
users, err = ts.ListUsers(ctx, &store.FindUser{})
require.NoError(t, err)
require.Equal(t, 0, len(users))
shortcuts, err := ts.ListShortcuts(ctx, &store.FindShortcut{})
shortcuts, err := ts.ListShortcutsV1(ctx, &store.FindShortcut{})
require.NoError(t, err)
require.Equal(t, 0, len(shortcuts))
}

Loading…
Cancel
Save