playing with FFI to golang to make graphql calls...gruesome
This commit is contained in:
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
go build -o libgraphql.dylib -buildmode=c-shared cmd/main.go
|
||||
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
"fmt"
|
||||
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
)
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"unsafe"
|
||||
|
||||
"github.com/flowy-live/admin-cli/go/internal/graph"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//export QueryGraphQL
|
||||
func QueryGraphQL(query *C.char) *C.char {
|
||||
goQuery := C.GoString(query)
|
||||
result := fmt.Sprintf("GraphQL Response for: %s", goQuery)
|
||||
return C.CString(result)
|
||||
}
|
||||
|
||||
//export GetWaitlist
|
||||
func GetWaitlist() (**C.char, C.long) {
|
||||
heliosAddr := "https://helios.dev.flowy.live"
|
||||
heliosFullAddr := fmt.Sprintf("%s/%s", heliosAddr, "query")
|
||||
gqlClient := graphql.NewClient(heliosFullAddr, http.DefaultClient)
|
||||
|
||||
response, err := graph.GetWaitlist(context.Background(), gqlClient)
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
cArray := C.malloc(C.size_t(len(response.GetWaitlist)+1) * C.size_t(unsafe.Sizeof(uintptr(0))))
|
||||
arrayPtr := (*[1 << 30]*C.char)(cArray)[: len(response.GetWaitlist)+1 : len(response.GetWaitlist)+1] // Unsafe slice
|
||||
|
||||
for i, s := range response.GetWaitlist {
|
||||
arrayPtr[i] = C.CString(s.Email)
|
||||
}
|
||||
arrayPtr[len(response.GetWaitlist)] = nil // Null-terminate
|
||||
|
||||
return (**C.char)(cArray), 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package tools
|
||||
|
||||
//go:generate go run github.com/Khan/genqlient@latest ./internal/graph/genqlient.yaml
|
||||
@@ -0,0 +1,14 @@
|
||||
module github.com/flowy-live/admin-cli/go
|
||||
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/Khan/genqlient v0.8.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/vektah/gqlparser/v2 v2.5.19 // indirect
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
github.com/Khan/genqlient v0.8.0 h1:Hd1a+E1CQHYbMEKakIkvBH3zW0PWEeiX6Hp1i2kP2WE=
|
||||
github.com/Khan/genqlient v0.8.0/go.mod h1:hn70SpYjWteRGvxTwo0kfaqg4wxvndECGkfa1fdDdYI=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
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/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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/vektah/gqlparser/v2 v2.5.19 h1:bhCPCX1D4WWzCDvkPl4+TP1N8/kLrWnp43egplt7iSg=
|
||||
github.com/vektah/gqlparser/v2 v2.5.19/go.mod h1:y7kvl5bBlDeuWIvLtA9849ncyvx6/lj06RsMrEjVy3U=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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,58 @@
|
||||
// Code generated by github.com/Khan/genqlient, DO NOT EDIT.
|
||||
|
||||
package graph
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
)
|
||||
|
||||
// GetWaitlistGetWaitlistWaitlistEntry includes the requested fields of the GraphQL type WaitlistEntry.
|
||||
type GetWaitlistGetWaitlistWaitlistEntry struct {
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// GetEmail returns GetWaitlistGetWaitlistWaitlistEntry.Email, and is useful for accessing the field via an interface.
|
||||
func (v *GetWaitlistGetWaitlistWaitlistEntry) GetEmail() string { return v.Email }
|
||||
|
||||
// GetWaitlistResponse is returned by GetWaitlist on success.
|
||||
type GetWaitlistResponse struct {
|
||||
// Roles: flowy-admin
|
||||
GetWaitlist []GetWaitlistGetWaitlistWaitlistEntry `json:"getWaitlist"`
|
||||
}
|
||||
|
||||
// GetGetWaitlist returns GetWaitlistResponse.GetWaitlist, and is useful for accessing the field via an interface.
|
||||
func (v *GetWaitlistResponse) GetGetWaitlist() []GetWaitlistGetWaitlistWaitlistEntry {
|
||||
return v.GetWaitlist
|
||||
}
|
||||
|
||||
// The query executed by GetWaitlist.
|
||||
const GetWaitlist_Operation = `
|
||||
query GetWaitlist {
|
||||
getWaitlist {
|
||||
email
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
func GetWaitlist(
|
||||
ctx_ context.Context,
|
||||
client_ graphql.Client,
|
||||
) (data_ *GetWaitlistResponse, err_ error) {
|
||||
req_ := &graphql.Request{
|
||||
OpName: "GetWaitlist",
|
||||
Query: GetWaitlist_Operation,
|
||||
}
|
||||
|
||||
data_ = &GetWaitlistResponse{}
|
||||
resp_ := &graphql.Response{Data: data_}
|
||||
|
||||
err_ = client_.MakeRequest(
|
||||
ctx_,
|
||||
req_,
|
||||
resp_,
|
||||
)
|
||||
|
||||
return data_, err_
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
query GetWaitlist {
|
||||
getWaitlist {
|
||||
email
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# Default genqlient config; for full documentation see:
|
||||
# https://github.com/Khan/genqlient/blob/main/docs/genqlient.yaml
|
||||
schema: schema.graphql
|
||||
operations:
|
||||
- genqlient.graphql
|
||||
generated: generated.go
|
||||
package: graph
|
||||
optional: pointer
|
||||
bindings:
|
||||
# To bind a scalar:
|
||||
DateTime:
|
||||
type: time.Time
|
||||
URL:
|
||||
type: string
|
||||
@@ -0,0 +1,861 @@
|
||||
scalar URL
|
||||
scalar Time
|
||||
scalar Upload
|
||||
|
||||
enum ErrorCode {
|
||||
NOT_REGISTERED
|
||||
ALREADY_REGISTERED
|
||||
INVALID_EMAIL
|
||||
INVALID_CODE
|
||||
BAD_USER_INPUT
|
||||
UNAUTHENTICATED
|
||||
FORBIDDEN
|
||||
NOT_FOUND
|
||||
INTERNAL_SERVER_ERROR
|
||||
SIGNIN_CODE_EXPIRED_OR_NOT_FOUND
|
||||
}
|
||||
|
||||
type Query {
|
||||
"""
|
||||
Roles: flowy-admin
|
||||
"""
|
||||
getWaitlist: [WaitlistEntry!]!
|
||||
|
||||
"""
|
||||
Temporary public way to pull all humans.
|
||||
"""
|
||||
humans: [Human!]!
|
||||
|
||||
"""
|
||||
"""
|
||||
human(id: ID!): Human!
|
||||
|
||||
"""
|
||||
[Temporary] Must set 'Authorization' header to auth-token.
|
||||
"""
|
||||
viewer: Human!
|
||||
|
||||
"""
|
||||
Search for humans including contacts by their display name, email.
|
||||
"""
|
||||
searchHumans(query: String!): [Human!]!
|
||||
|
||||
"""
|
||||
Returns all of the spaces for the authed human.
|
||||
"""
|
||||
spaces: SpaceConnection!
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
"""
|
||||
Subscribes to new echoes relevant to the authed human. This means the echo is in 'SENT' state.
|
||||
Includes echoes sent by the authed human.
|
||||
"""
|
||||
echoSent: Echo!
|
||||
|
||||
"""
|
||||
Notifies authed human when relevant echo is expired.
|
||||
"""
|
||||
echoExpired(echoId: ID!): Echo!
|
||||
|
||||
"""
|
||||
New conversation created which involves the authed human.
|
||||
"""
|
||||
newConversation: ID!
|
||||
|
||||
"""
|
||||
Watch the basic online status of a human.
|
||||
"""
|
||||
humanStatus(humanId: ID!): Boolean!
|
||||
|
||||
"""
|
||||
Watches for signals for people echoing in a conversation.
|
||||
"""
|
||||
echoSignal(conversationId: ID!): ID!
|
||||
|
||||
"""
|
||||
Receive instructions (for the chrome extension) sent by given human on the keypad.
|
||||
"""
|
||||
instruction(humanId: ID!): Instruction!
|
||||
|
||||
"""
|
||||
Receive messages from the chrome extension.
|
||||
"""
|
||||
peripheralMessage: PeripheralMessage!
|
||||
}
|
||||
|
||||
type OpenUrlInstruction {
|
||||
url: URL!
|
||||
}
|
||||
type ChatGptFollowUpInstruction {
|
||||
query: String!
|
||||
}
|
||||
type ChatGptToggleWebSearchInstruction {
|
||||
# FIX: required to have one field for some reason
|
||||
fakeField: Boolean
|
||||
}
|
||||
type GoogleCalendarUpdateViewInstruction {
|
||||
hotkey: String!
|
||||
}
|
||||
type VariableInstruction {
|
||||
"""
|
||||
Will be a json representation of a instruction defined in keypad & chrome extension.
|
||||
"""
|
||||
message: String!
|
||||
}
|
||||
union Instruction = OpenUrlInstruction | ChatGptFollowUpInstruction | ChatGptToggleWebSearchInstruction | GoogleCalendarUpdateViewInstruction | VariableInstruction
|
||||
|
||||
type UrlUpdatedMessage {
|
||||
currentUrl: URL!
|
||||
}
|
||||
type StateUpdateMessage {
|
||||
url: URL!
|
||||
"""
|
||||
Json representation for specific application context.
|
||||
"""
|
||||
state: String
|
||||
}
|
||||
union PeripheralMessage = UrlUpdatedMessage | StateUpdateMessage
|
||||
|
||||
type Mutation {
|
||||
"""
|
||||
Registers a new human.
|
||||
Errors if already registered.
|
||||
"""
|
||||
register(email: String!, displayName: String!): Boolean!
|
||||
|
||||
"""
|
||||
Sends email with a code.
|
||||
ErrorCodeNotFound if not registered.
|
||||
"""
|
||||
signIn(email: String!): Boolean!
|
||||
|
||||
"""
|
||||
Verifies the code and returns a token.
|
||||
ErrorCodeNotFound if not registered.
|
||||
ErrorSignInCodeExpiredOrNotFound if the code is expired or not found.
|
||||
"""
|
||||
signInVerify(email: String!, code: String!): TokenOutput!
|
||||
|
||||
"""
|
||||
If already in the waitlist, gracefully returns success.
|
||||
Roles: public
|
||||
"""
|
||||
joinWaitlist(input: JoinWaitlistInput!): Boolean!
|
||||
|
||||
"""
|
||||
Add a human into the system.
|
||||
Returns the human.
|
||||
"""
|
||||
addHuman(input: AddHumanInput!): Human!
|
||||
|
||||
"""
|
||||
The first step in flowy.llink (thought).
|
||||
Returns ID of the draft echo.
|
||||
"""
|
||||
draftEcho(input: DraftEchoInput!): DraftEchoOutput!
|
||||
|
||||
"""
|
||||
The second step in flowy.llink (top-of-mind people).
|
||||
Requires authentication as the human who drafted.
|
||||
The system will prepare and send the echo after this step and you will be notified in echoReceived subscription.
|
||||
Returns true if successful.
|
||||
"""
|
||||
commitEcho(input: CommitEchoInput!): Boolean!
|
||||
|
||||
"""
|
||||
Adds a human to a conversation.
|
||||
Requires authentication as the admin of the conversation.
|
||||
"""
|
||||
addHumanToConversation(input: AddHumanToConversationInput!): Boolean!
|
||||
|
||||
"""
|
||||
Updates the profile picture of the authed human.
|
||||
"""
|
||||
updateHumanProfile(input: UpdateHumanProfileInput!): Boolean!
|
||||
|
||||
"""
|
||||
Updates the playback marker for the authed human in a conversation.
|
||||
Must be a member of the conversation.
|
||||
"""
|
||||
updatePlaybackMarker(conversationId: ID!, echoId: ID!, currentPositionSeconds: Int!): ConversationPlaybackMarker!
|
||||
|
||||
"""
|
||||
Updates the last seen time of the authed human.
|
||||
"""
|
||||
updateLastSeen: Boolean!
|
||||
"""
|
||||
Updates the presence of the authed human.
|
||||
"""
|
||||
disconnectPresence: Boolean!
|
||||
|
||||
"""
|
||||
Must be a member of the conversation.
|
||||
Signals to others in the conversation that the authed human is echoing.
|
||||
"""
|
||||
sendEchoSignal(conversationId: ID!): Boolean!
|
||||
|
||||
"""
|
||||
Generates a token to join the live room.
|
||||
"""
|
||||
generateLiveToken(conversationId: ID!): String!
|
||||
|
||||
"""
|
||||
Sends instruction to chrome extension.
|
||||
"""
|
||||
sendInstruction(input: SendInstructionInput!): Boolean!
|
||||
|
||||
"""
|
||||
For sending responses/messages from the chrome extension to the keypad.
|
||||
"""
|
||||
sendMessageToKeypad(input: SendMessageToKeypadInput!): Boolean!
|
||||
|
||||
addSpace(input: AddSpaceInput!): Space!
|
||||
updateSpace(input: UpdateSpaceInput!): Space!
|
||||
moveSpace(input: MoveSpaceInput!): Boolean!
|
||||
deleteSpace(input: DeleteSpaceInput!): Boolean!
|
||||
setKey(input: SetKeyInput!): Key!
|
||||
swapKeys(input: SwapKeysInput!): Boolean!
|
||||
deleteKey(input: DeleteKeyInput!): Boolean!
|
||||
}
|
||||
|
||||
input AddSpaceInput {
|
||||
name: String!
|
||||
|
||||
"""
|
||||
Optional. Either set this or `iconUrl`, not both.
|
||||
"""
|
||||
iconName: String
|
||||
"""
|
||||
Optional. Either set this or `iconName`, not both.
|
||||
"""
|
||||
iconUrl: URL
|
||||
|
||||
"""
|
||||
Optional. Either specify a domain or an app name followed by the extension
|
||||
(e.g. 'app:Visual Studio Code' or 'url_contains:flowy.com' or 'url_contains:youtube.com/watch').
|
||||
"""
|
||||
trigger: String
|
||||
}
|
||||
|
||||
input UpdateSpaceInput {
|
||||
spaceId: ID!
|
||||
|
||||
name: String!
|
||||
|
||||
"""
|
||||
Optional. Either set this or `iconUrl`, not both.
|
||||
"""
|
||||
iconName: String
|
||||
"""
|
||||
Optional. Either set this or `iconName`, not both.
|
||||
"""
|
||||
iconUrl: URL
|
||||
|
||||
"""
|
||||
Optional. Either specify a domain or an app name followed by the extension
|
||||
(e.g. 'app:Visual Studio Code' or 'url_contains:flowy.com' or 'url_contains:youtube.com/watch').
|
||||
"""
|
||||
trigger: String
|
||||
}
|
||||
|
||||
enum MoveSpaceDirection {
|
||||
UP
|
||||
DOWN
|
||||
}
|
||||
|
||||
input MoveSpaceInput {
|
||||
spaceId: ID!
|
||||
direction: MoveSpaceDirection!
|
||||
}
|
||||
|
||||
input DeleteSpaceInput {
|
||||
spaceId: ID!
|
||||
}
|
||||
|
||||
input KeyTypeKeypressInput {
|
||||
mainKey: String!
|
||||
shiftKey: Boolean!
|
||||
commandKey: Boolean!
|
||||
optionKey: Boolean!
|
||||
controlKey: Boolean!
|
||||
}
|
||||
|
||||
input KeyTypeOpenUrlInput {
|
||||
url: String! # URL is typically represented as a String in GraphQL
|
||||
newWindow: Boolean!
|
||||
}
|
||||
|
||||
input KeyTypeOpenAppInput {
|
||||
appName: String!
|
||||
}
|
||||
|
||||
input KeyTypeTextSnippetInput {
|
||||
text: String!
|
||||
pasteInCurrentInput: Boolean!
|
||||
copyToClipboard: Boolean!
|
||||
}
|
||||
|
||||
input KeyTypeTerminalCommandInput {
|
||||
command: String!
|
||||
directory: String!
|
||||
}
|
||||
|
||||
input KeyTypeWriteForMeInput {
|
||||
prependedInstruction: String!
|
||||
writingStyle: String
|
||||
formatForCurrentApp: Boolean!
|
||||
attachScreenshot: Boolean!
|
||||
}
|
||||
|
||||
input KeyTypeTypeForMeInput {
|
||||
minimallyProcess: Boolean!
|
||||
formatForCurrentApp: Boolean!
|
||||
}
|
||||
|
||||
input KeyTypeFlowyChatInput {
|
||||
prependedInstruction: String!
|
||||
}
|
||||
|
||||
input KeyTypeMacOsCommandInput {
|
||||
commandType: MacOsCommandType!
|
||||
}
|
||||
|
||||
input KeyConfigurationInput {
|
||||
keypress: KeyTypeKeypressInput
|
||||
openUrl: KeyTypeOpenUrlInput
|
||||
openApp: KeyTypeOpenAppInput
|
||||
textSnippet: KeyTypeTextSnippetInput
|
||||
terminalCommand: KeyTypeTerminalCommandInput
|
||||
writeForMe: KeyTypeWriteForMeInput
|
||||
typeForMe: KeyTypeTypeForMeInput
|
||||
flowyChat: KeyTypeFlowyChatInput
|
||||
macOsCommand: KeyTypeMacOsCommandInput
|
||||
}
|
||||
input SetKeyInput {
|
||||
spaceId: ID!
|
||||
position: Int!
|
||||
|
||||
title: String!
|
||||
|
||||
"""
|
||||
Optional. Either set this or `iconUrl`, not both.
|
||||
"""
|
||||
iconName: String
|
||||
"""
|
||||
Optional. Either set this or `iconName`, not both.
|
||||
"""
|
||||
iconUrl: URL
|
||||
|
||||
hexColor: String
|
||||
|
||||
"""
|
||||
Must specify one of the inputs.
|
||||
"""
|
||||
keyConfiguration: KeyConfigurationInput!
|
||||
}
|
||||
|
||||
input SwapKeysInput {
|
||||
spaceId: ID!
|
||||
positionA: Int!
|
||||
positionB: Int!
|
||||
}
|
||||
|
||||
input DeleteKeyInput {
|
||||
spaceId: ID!
|
||||
position: Int!
|
||||
}
|
||||
|
||||
enum Role {
|
||||
ADMIN,
|
||||
HUMAN,
|
||||
}
|
||||
|
||||
type TokenOutput {
|
||||
token: String!
|
||||
role: Role!
|
||||
}
|
||||
|
||||
input UrlUpdatedMessageInput {
|
||||
"""
|
||||
Current url of the active tab and focused window.
|
||||
"""
|
||||
currentUrl: URL!
|
||||
}
|
||||
input StateUpdateInput {
|
||||
url: URL!
|
||||
|
||||
"""
|
||||
State of specific site in url in json form.
|
||||
"""
|
||||
state: String
|
||||
}
|
||||
input SendMessageToKeypadInput {
|
||||
humanId: ID!
|
||||
urlUpdated: UrlUpdatedMessageInput
|
||||
stateUpdate: StateUpdateInput
|
||||
}
|
||||
|
||||
input SendInstructionUpdateGoogleCalendarViewInput {
|
||||
"""
|
||||
The hotkey to update the google calendar view.
|
||||
"""
|
||||
hotkey: String!
|
||||
}
|
||||
input SendInstructionOpenUrlInput {
|
||||
url: URL!
|
||||
}
|
||||
input SendInstructionChatGptFollowUpInput {
|
||||
query: String!
|
||||
}
|
||||
input SendInstructionChatGptToggleWebSearchInput {
|
||||
# FIX: required to have one field for some reason
|
||||
fakeField: Boolean
|
||||
}
|
||||
input SendVariableInstructionInput {
|
||||
"""
|
||||
Will be a json representation of a instruction defined in keypad & chrome extension.
|
||||
"""
|
||||
message: String!
|
||||
}
|
||||
### FIX: dealing with polymorphism here by having different optional fields because can't have a union in an input type
|
||||
input SendInstructionInput {
|
||||
openUrl: SendInstructionOpenUrlInput
|
||||
chatGptFollowUp: SendInstructionChatGptFollowUpInput
|
||||
chatGptToggleWebSearch: SendInstructionChatGptToggleWebSearchInput
|
||||
updateGoogleCalendarView: SendInstructionUpdateGoogleCalendarViewInput
|
||||
variable: SendVariableInstructionInput
|
||||
}
|
||||
|
||||
type Header {
|
||||
key: String!
|
||||
value: String!
|
||||
}
|
||||
|
||||
type DraftEchoOutput {
|
||||
draftEchoId: ID!
|
||||
"""
|
||||
The URL to upload the asset to. Must be done before committing the echo.
|
||||
"""
|
||||
assetUploadUrl: URL!
|
||||
"""
|
||||
Use these headers to upload the asset to the given URL.
|
||||
"""
|
||||
uploadHeaders: [Header!]!
|
||||
}
|
||||
|
||||
enum CompanyWorkspaceSuite {
|
||||
GSuite
|
||||
Office365
|
||||
}
|
||||
|
||||
type WaitlistEntry {
|
||||
email: String!
|
||||
firstName: String
|
||||
lastName: String
|
||||
companyWebsite: URL
|
||||
companyWorkspaceSuite: CompanyWorkspaceSuite
|
||||
isDecisionMaker: Boolean
|
||||
}
|
||||
|
||||
input JoinWaitlistInput {
|
||||
email: String!
|
||||
firstName: String
|
||||
lastName: String
|
||||
companyWebsite: URL
|
||||
companyWorkspaceSuite: CompanyWorkspaceSuite
|
||||
isDecisionMaker: Boolean
|
||||
}
|
||||
|
||||
input AddHumanInput {
|
||||
email: String!
|
||||
displayName: String!
|
||||
profilePicture: Upload
|
||||
}
|
||||
|
||||
input DraftEchoInput {
|
||||
contentLength: Int!
|
||||
contentType: String!
|
||||
|
||||
"""
|
||||
Must match the mime type of the asset. If `video/*`, then you can use `VIDEO` or `SCREEN`.
|
||||
"""
|
||||
echoType: EchoType!
|
||||
}
|
||||
|
||||
input CommitEchoInput {
|
||||
draftEchoId: ID!
|
||||
|
||||
"""
|
||||
Send to the given existing conversation.
|
||||
Authed human must be a member of the conversation.
|
||||
Must have this or `newConversation`.
|
||||
"""
|
||||
existingConversation: String
|
||||
|
||||
"""
|
||||
Send to a new conversation with the given human ids.
|
||||
Authed human becomes the admin of the conversation.
|
||||
Must have this or `existingConversation`.
|
||||
Do NOT include the echo creator in the list.
|
||||
"""
|
||||
newConversation: [ID!]
|
||||
}
|
||||
|
||||
input AddHumanToConversationInput {
|
||||
conversationId: ID!
|
||||
humanId: ID!
|
||||
}
|
||||
|
||||
input UpdateHumanProfileInput {
|
||||
"""
|
||||
The profile picture to update. Optional.
|
||||
If kept empty, will retain the former profile picture.
|
||||
"""
|
||||
profilePicture: Upload
|
||||
"""
|
||||
The display name to update. Optional.
|
||||
If kept empty, will retain the former display name.
|
||||
"""
|
||||
displayName: String
|
||||
}
|
||||
|
||||
"""
|
||||
Orders by all types DESC
|
||||
"""
|
||||
enum PaginationOrderBy {
|
||||
CREATED_AT
|
||||
UPDATED_AT
|
||||
}
|
||||
|
||||
type PageInfo {
|
||||
hasNextPage: Boolean!
|
||||
hasPreviousPage: Boolean!
|
||||
startCursor: String
|
||||
endCursor: String
|
||||
}
|
||||
|
||||
type Human {
|
||||
id: ID!
|
||||
email: String!
|
||||
displayName: String!
|
||||
profilePictureUrl: URL
|
||||
"""
|
||||
Two letters based on the display name.
|
||||
"""
|
||||
initials: String!
|
||||
isFlowyAdmin: Boolean!
|
||||
createdAt: Time!
|
||||
|
||||
"""
|
||||
Conversations that the human is involved.
|
||||
Only available if the viewer is this human or flowy-admin.
|
||||
"""
|
||||
conversations(
|
||||
"""
|
||||
Whether or not to show expired conversations.
|
||||
"""
|
||||
includeExpired: Boolean! = false
|
||||
): HumanConversationConnection!
|
||||
}
|
||||
|
||||
type HumanConversationConnection {
|
||||
edges: [HumanConversationEdge!]!
|
||||
nodes: [Conversation!]!
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
type ConversationPlaybackMarker {
|
||||
"""
|
||||
This is the id of the echo that the human last played within this conversation.
|
||||
Serves as a playback marker for the human to enable 'continue playing a youtube video'.
|
||||
"""
|
||||
echoId: String
|
||||
|
||||
"""
|
||||
This is how far we are on the current marker echo. Used for precision.
|
||||
If we are at the end, will start playing the next echo.
|
||||
Similar to [MDN audio currentTime](https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/currentTime)
|
||||
"""
|
||||
currentPositionSeconds: Int
|
||||
|
||||
# """
|
||||
# Whether or not the current marker is at the latest echo in the conversation.
|
||||
# """
|
||||
# FIXME: want data from echoes resolver to update this upstream resolver...how? consolidate resolvers?
|
||||
# isLatestEcho: Boolean!
|
||||
}
|
||||
|
||||
type HumanConversationEdge {
|
||||
cursor: String!
|
||||
node: Conversation!
|
||||
|
||||
"""
|
||||
A set of properties for seamless playback experience for a human in a conversation.
|
||||
"""
|
||||
playbackMarker: ConversationPlaybackMarker!
|
||||
}
|
||||
|
||||
type Conversation {
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
All members of a conversation *excluding* the viewer.
|
||||
"""
|
||||
members: ConversationMemberConnection!
|
||||
|
||||
"""
|
||||
Echoes for this conversation, sorted by createdAt ASC.
|
||||
"""
|
||||
echoes(
|
||||
"""
|
||||
Whether or not to show all echoes for this conversation.
|
||||
An echo is considered expired if it was created more than 48 hours ago.
|
||||
"""
|
||||
includeExpired: Boolean! = false
|
||||
): EchoConnection!
|
||||
|
||||
"""
|
||||
The last time that an echo, radio, or chat happened in this conversation.
|
||||
"""
|
||||
lastActivityAt: Time
|
||||
|
||||
"""
|
||||
A conversation is considered expired if the last activity was more than 48 hours ago.
|
||||
"""
|
||||
isExpired: Boolean!
|
||||
}
|
||||
|
||||
type ConversationMemberConnection {
|
||||
edges: [ConversationMemberEdge!]!
|
||||
# NOTE: be careful to not to trigger infinite fetch here.
|
||||
nodes: [Human!]!
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
type ConversationMemberEdge {
|
||||
cursor: String!
|
||||
node: Human!
|
||||
}
|
||||
|
||||
type EchoConnection {
|
||||
edges: [EchoEdge!]!
|
||||
nodes: [Echo!]!
|
||||
pageInfo: PageInfo!
|
||||
# lastEchoTranscript: String
|
||||
}
|
||||
|
||||
type EchoEdge {
|
||||
cursor: ID!
|
||||
node: Echo!
|
||||
}
|
||||
|
||||
enum EchoType {
|
||||
AUDIO_ONLY
|
||||
VIDEO
|
||||
SCREEN
|
||||
}
|
||||
|
||||
enum EchoState {
|
||||
DRAFT
|
||||
"""
|
||||
The creator has committed this to be sent to a conversation when complete.
|
||||
"""
|
||||
COMMITTED
|
||||
"""
|
||||
Transcribing, transcoding and other activities in progress.
|
||||
"""
|
||||
PREPARING
|
||||
"""
|
||||
Everything ready for playback experience, going to send soon.
|
||||
"""
|
||||
READY
|
||||
"""
|
||||
The echo is sent within a conversation.
|
||||
"""
|
||||
SENT
|
||||
"""
|
||||
The echo failed in some way.
|
||||
"""
|
||||
FAILURE
|
||||
}
|
||||
|
||||
type Echo {
|
||||
id: ID!
|
||||
createdBy: Human!
|
||||
createdByViewer: Boolean!
|
||||
createdAt: Time!
|
||||
echoType: EchoType!
|
||||
echoState: EchoState!
|
||||
|
||||
"""
|
||||
URL to download the asset. Will be a temporary pre-signed URL.
|
||||
"""
|
||||
assetUrl: URL!
|
||||
|
||||
"""
|
||||
HLS streal URL for asset. Only available if the echo is in 'SENT' state.
|
||||
"""
|
||||
streamUrl: URL
|
||||
|
||||
"""
|
||||
Thumbnail image for the asset. Only available if the echo is in 'SENT' state.
|
||||
"""
|
||||
thumbnailUrl: URL
|
||||
|
||||
"""
|
||||
Thumbnail gif for the asset. Only available if the echo is in 'SENT' state.
|
||||
"""
|
||||
thumbnailGifUrl: URL
|
||||
|
||||
"""
|
||||
Duration in seconds. Only available if the echo is in 'SENT' state.
|
||||
"""
|
||||
durationSeconds: Float
|
||||
|
||||
"""
|
||||
The conversation that this echo belongs to.
|
||||
Only available if the echo is past the 'DRAFT' state.
|
||||
"""
|
||||
conversation: Conversation
|
||||
|
||||
"""
|
||||
The transcript of the echo. Only available if the echo is in 'SENT' state.
|
||||
"""
|
||||
transcript: Transcript
|
||||
}
|
||||
|
||||
type TranscriptWord {
|
||||
word: String!
|
||||
start: Float!
|
||||
end: Float!
|
||||
}
|
||||
|
||||
type Transcript {
|
||||
fullText: String!
|
||||
words: [TranscriptWord!]!
|
||||
}
|
||||
|
||||
type IconName {
|
||||
value: String!
|
||||
}
|
||||
type IconUrl {
|
||||
value: URL!
|
||||
}
|
||||
union VariableIcon = IconName | IconUrl
|
||||
type KeyTypeKeypress {
|
||||
mainKey: String!
|
||||
shiftKey: Boolean!
|
||||
commandKey: Boolean!
|
||||
optionKey: Boolean!
|
||||
controlKey: Boolean!
|
||||
}
|
||||
type KeyTypeOpenUrl {
|
||||
url: URL!
|
||||
newWindow: Boolean!
|
||||
}
|
||||
type KeyTypeOpenApp {
|
||||
appName: String!
|
||||
}
|
||||
type KeyTypeTextSnippet {
|
||||
text: String!
|
||||
pasteInCurrentInput: Boolean!
|
||||
copyToClipboard: Boolean!
|
||||
}
|
||||
type KeyTypeTerminalCommand {
|
||||
command: String!
|
||||
directory: String!
|
||||
}
|
||||
type KeyTypeWriteForMe {
|
||||
prependedInstruction: String!
|
||||
"""
|
||||
e.g. casual, friendly, formal, concise (or any combination)
|
||||
"""
|
||||
writingStyle: String!
|
||||
"""
|
||||
Whether or not to format for the current app (e.g. Notion in markdown vs. email formatting differences)
|
||||
Default: true.
|
||||
"""
|
||||
formatForCurrentApp: Boolean!
|
||||
"""
|
||||
Optional. Provides more context of what I am doing and reading.
|
||||
"""
|
||||
attachScreenshot: Boolean!
|
||||
}
|
||||
type KeyTypeTypeForMe {
|
||||
"""
|
||||
Help with breaking sentences apart and small grammar rules.
|
||||
"""
|
||||
minimallyProcess: Boolean!
|
||||
"""
|
||||
Whether or not to format for the current app (e.g. Notion in markdown vs. email formatting differences)
|
||||
Default: true.
|
||||
"""
|
||||
formatForCurrentApp: Boolean!
|
||||
}
|
||||
type KeyTypeFlowyChat {
|
||||
prependedInstruction: String!
|
||||
}
|
||||
enum MacOsCommandType {
|
||||
INCREASE_BRIGHTNESS
|
||||
DECREASE_BRIGHTNESS
|
||||
MUTE_VOLUME
|
||||
INCREASE_VOLUME
|
||||
DECREASE_VOLUME
|
||||
PLAY_PAUSE
|
||||
NEXT_TRACK
|
||||
PREVIOUS_TRACK
|
||||
DO_NOT_DISTURB
|
||||
LOCK_SCREEN
|
||||
LOG_OUT
|
||||
SLEEP
|
||||
SHUT_DOWN
|
||||
RESTART
|
||||
MISSION_CONTROL
|
||||
APP_DRAWER
|
||||
SPOTLIGHT
|
||||
"""
|
||||
MacOS: ⌘ + SHIFT + 3
|
||||
"""
|
||||
SCREENSHOT_SCREEN
|
||||
"""
|
||||
MacOS: ⌘ + SHIFT + 4
|
||||
"""
|
||||
SCREENSHOT_AREA_SELECT
|
||||
"""
|
||||
MacOS: ⌘ + SHIFT + 5
|
||||
"""
|
||||
SCREENSHOT_FULL_OPTIONS
|
||||
}
|
||||
type KeyTypeMacOsCommand {
|
||||
commandType: MacOsCommandType!
|
||||
}
|
||||
union KeyConfiguration = KeyTypeKeypress | KeyTypeOpenUrl | KeyTypeOpenApp | KeyTypeTextSnippet | KeyTypeTerminalCommand | KeyTypeWriteForMe | KeyTypeTypeForMe | KeyTypeFlowyChat | KeyTypeMacOsCommand
|
||||
type Key {
|
||||
id: ID!
|
||||
title: String!
|
||||
position: Int!
|
||||
hexColor: String
|
||||
icon: VariableIcon
|
||||
createdAt: Time!
|
||||
keyConfiguration: KeyConfiguration!
|
||||
}
|
||||
type Space {
|
||||
id: ID!
|
||||
name: String!
|
||||
keys: [Key!]!
|
||||
createdAt: Time!
|
||||
icon: VariableIcon
|
||||
trigger: String
|
||||
}
|
||||
|
||||
type SpaceConnection {
|
||||
edges: [SpaceEdge!]!
|
||||
nodes: [Space!]!
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
type SpaceEdge {
|
||||
cursor: ID!
|
||||
node: Space!
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,88 @@
|
||||
/* Code generated by cmd/cgo; DO NOT EDIT. */
|
||||
|
||||
/* package command-line-arguments */
|
||||
|
||||
|
||||
#line 1 "cgo-builtin-export-prolog"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef GO_CGO_EXPORT_PROLOGUE_H
|
||||
#define GO_CGO_EXPORT_PROLOGUE_H
|
||||
|
||||
#ifndef GO_CGO_GOSTRING_TYPEDEF
|
||||
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Start of preamble from import "C" comments. */
|
||||
|
||||
|
||||
|
||||
|
||||
/* End of preamble from import "C" comments. */
|
||||
|
||||
|
||||
/* Start of boilerplate cgo prologue. */
|
||||
#line 1 "cgo-gcc-export-header-prolog"
|
||||
|
||||
#ifndef GO_CGO_PROLOGUE_H
|
||||
#define GO_CGO_PROLOGUE_H
|
||||
|
||||
typedef signed char GoInt8;
|
||||
typedef unsigned char GoUint8;
|
||||
typedef short GoInt16;
|
||||
typedef unsigned short GoUint16;
|
||||
typedef int GoInt32;
|
||||
typedef unsigned int GoUint32;
|
||||
typedef long long GoInt64;
|
||||
typedef unsigned long long GoUint64;
|
||||
typedef GoInt64 GoInt;
|
||||
typedef GoUint64 GoUint;
|
||||
typedef size_t GoUintptr;
|
||||
typedef float GoFloat32;
|
||||
typedef double GoFloat64;
|
||||
#ifdef _MSC_VER
|
||||
#include <complex.h>
|
||||
typedef _Fcomplex GoComplex64;
|
||||
typedef _Dcomplex GoComplex128;
|
||||
#else
|
||||
typedef float _Complex GoComplex64;
|
||||
typedef double _Complex GoComplex128;
|
||||
#endif
|
||||
|
||||
/*
|
||||
static assertion to make sure the file is being used on architecture
|
||||
at least with matching size of GoInt.
|
||||
*/
|
||||
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
|
||||
|
||||
#ifndef GO_CGO_GOSTRING_TYPEDEF
|
||||
typedef _GoString_ GoString;
|
||||
#endif
|
||||
typedef void *GoMap;
|
||||
typedef void *GoChan;
|
||||
typedef struct { void *t; void *v; } GoInterface;
|
||||
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
|
||||
|
||||
#endif
|
||||
|
||||
/* End of boilerplate cgo prologue. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern char* QueryGraphQL(char* query);
|
||||
|
||||
/* Return type for GetWaitlist */
|
||||
struct GetWaitlist_return {
|
||||
char** r0;
|
||||
long r1;
|
||||
};
|
||||
extern struct GetWaitlist_return GetWaitlist();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user