diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 769372e3a8..6371565672 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -22,7 +22,7 @@ jobs: cache: false - uses: actions/checkout@v4 - name: golangci-lint - uses: golangci/golangci-lint-action@v5 + uses: golangci/golangci-lint-action@v6 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version version: latest diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 5f79baf650..7105708068 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,15 +1,61 @@ import type { Preview } from '@storybook/react' import DefaultDecorator from '../web/src/app/storybook/decorators' import { initialize, mswLoader } from 'msw-storybook-addon' -import { - handleDefaultConfig, - handleExpFlags, -} from '../web/src/app/storybook/graphql' +import { defaultConfig } from '../web/src/app/storybook/graphql' +import { graphql, HttpResponse } from 'msw' initialize({ onUnhandledRequest: 'bypass', }) +export type GraphQLRequestHandler = (variables: unknown) => object +export type GraphQLParams = Record + +const componentConfig: Record = {} + +export const mswHandler = graphql.operation((params) => { + const url = new URL(params.request.url) + const gql = componentConfig[url.pathname] + const handler = gql[params.operationName] + if (!handler) { + return HttpResponse.json({ + errors: [ + { message: `No mock defined for operation '${params.operationName}'.` }, + ], + }) + } + + if (typeof handler === 'function') { + return HttpResponse.json(handler(params.variables)) + } + + return HttpResponse.json(handler) +}) + +interface LoaderArg { + id: string + parameters: { + graphql?: GraphQLParams + } +} + +/** + * graphqlLoader is a loader function that sets up the GraphQL mocks for the + * component. It stores them in a global object, componentConfig, which is used + * by the mswHandler to resolve the mocks. + * + * We need to do this because the browser will render all components at once, + * and so we need to handle all GraphQL mocks at once. + * + * The way this works is that each component get's a unique URL for GraphQL + * (see decorators.tsx). This URL is used to store the GraphQL mocks for that + * component in componentConfig. + */ +export function graphQLLoader(arg: LoaderArg): void { + const path = '/' + encodeURIComponent(arg.id) + '/api/graphql' + componentConfig[path] = arg.parameters.graphql || {} +} + const preview: Preview = { parameters: { controls: { @@ -18,12 +64,15 @@ const preview: Preview = { date: /Date$/i, }, }, - msw: { - handlers: [handleDefaultConfig, handleExpFlags()], + graphql: { + // default GraphQL handlers + RequireConfig: { data: defaultConfig }, + useExpFlag: { data: { experimentalFlags: [] } }, }, + msw: { handlers: [mswHandler] }, }, decorators: [DefaultDecorator], - loaders: [mswLoader], + loaders: [graphQLLoader, mswLoader], } export default preview diff --git a/.storybook/static/mockServiceWorker.js b/.storybook/static/mockServiceWorker.js index e369128ec0..bdfdb11d38 100644 --- a/.storybook/static/mockServiceWorker.js +++ b/.storybook/static/mockServiceWorker.js @@ -2,13 +2,14 @@ /* tslint:disable */ /** - * Mock Service Worker (2.0.11). + * Mock Service Worker. * @see https://github.com/mswjs/msw * - Please do NOT modify this file. * - Please do NOT serve this file on production. */ -const INTEGRITY_CHECKSUM = 'c5f7f8e188b673ea4e677df7ea3c5a39' +const PACKAGE_VERSION = '2.3.0' +const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423' const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') const activeClientIds = new Set() @@ -48,7 +49,10 @@ self.addEventListener('message', async function (event) { case 'INTEGRITY_CHECK_REQUEST': { sendToClient(client, { type: 'INTEGRITY_CHECK_RESPONSE', - payload: INTEGRITY_CHECKSUM, + payload: { + packageVersion: PACKAGE_VERSION, + checksum: INTEGRITY_CHECKSUM, + }, }) break } @@ -202,13 +206,6 @@ async function getResponse(event, client, requestId) { return passthrough() } - // Bypass requests with the explicit bypass header. - // Such requests can be issued by "ctx.fetch()". - const mswIntention = request.headers.get('x-msw-intention') - if (['bypass', 'passthrough'].includes(mswIntention)) { - return passthrough() - } - // Notify the client that a request has been intercepted. const requestBuffer = await request.arrayBuffer() const clientMessage = await sendToClient( @@ -240,7 +237,7 @@ async function getResponse(event, client, requestId) { return respondWithMock(clientMessage.data) } - case 'MOCK_NOT_FOUND': { + case 'PASSTHROUGH': { return passthrough() } } diff --git a/apikey/policy.go b/apikey/policy.go index 73f1d6f89a..3c9e9b1f24 100644 --- a/apikey/policy.go +++ b/apikey/policy.go @@ -3,6 +3,13 @@ package apikey import "github.com/target/goalert/permission" // GQLPolicy is a GraphQL API key policy. +// +// Any changes to existing fields MUST require the version to be incremented. +// +// If new fields are added, they MUST be set to `omitempty` +// to ensure existing keys don't break. +// +// It MUST be possible to unmarshal & re-marshal the policy without changing the data for existing keys. type GQLPolicy struct { Version int Query string diff --git a/apikey/policyinfo.go b/apikey/policyinfo.go index a47ec1026a..8a8de2e845 100644 --- a/apikey/policyinfo.go +++ b/apikey/policyinfo.go @@ -16,6 +16,25 @@ type policyInfo struct { Policy GQLPolicy } +func parsePolicyInfo(data []byte) (*policyInfo, error) { + var info policyInfo + err := json.Unmarshal(data, &info.Policy) + if err != nil { + return nil, err + } + + // re-encode policy to get a consistent hash + data, err = json.Marshal(info.Policy) + if err != nil { + return nil, err + } + + h := sha256.Sum256(data) + info.Hash = h[:] + + return &info, nil +} + // _fetchPolicyInfo will fetch the policyInfo for the given key. func (s *Store) _fetchPolicyInfo(ctx context.Context, id uuid.UUID) (*policyInfo, bool, error) { polData, err := gadb.New(s.db).APIKeyAuthPolicy(ctx, id) @@ -26,14 +45,10 @@ func (s *Store) _fetchPolicyInfo(ctx context.Context, id uuid.UUID) (*policyInfo return nil, false, err } - var info policyInfo - err = json.Unmarshal(polData, &info.Policy) + info, err := parsePolicyInfo(polData) if err != nil { return nil, false, err } - h := sha256.Sum256(polData) - info.Hash = h[:] - - return &info, true, nil + return info, true, nil } diff --git a/apikey/policyinfo_test.go b/apikey/policyinfo_test.go new file mode 100644 index 0000000000..55e6cddc4e --- /dev/null +++ b/apikey/policyinfo_test.go @@ -0,0 +1,38 @@ +package apikey + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestParsePolicyInfo(t *testing.T) { + expected := &policyInfo{ + // Never change this hash -- it is used to verify future changes wont break existing keys. + Hash: []byte{0x2d, 0x6d, 0xef, 0x3b, 0xfa, 0xd8, 0xef, 0x9d, 0x7e, 0x6c, 0xf4, 0xed, 0xd1, 0x81, 0x16, 0xf4, 0x23, 0xaa, 0x4a, 0xaf, 0x70, 0x1b, 0xfd, 0x1b, 0x26, 0x1d, 0xb3, 0x1, 0x4f, 0xdc, 0xa1, 0x61}, + Policy: GQLPolicy{ + Version: 1, + Query: "query", + Role: "admin", + }, + } + + info, err := parsePolicyInfo([]byte(`{"Version":1,"Query":"query","Role":"admin"}`)) + assert.NoError(t, err) + assert.Equal(t, expected, info) + + // add spaces and re-order keys + info, err = parsePolicyInfo([]byte(`{ "Role":"admin", "Query":"query","Version":1}`)) + assert.NoError(t, err) + assert.Equal(t, expected, info) + + // add extra field + info, err = parsePolicyInfo([]byte(`{"Version":1,"Query":"query","Role":"admin","Extra":true}`)) + assert.NoError(t, err) + assert.Equal(t, expected, info) + + // changed query + info, err = parsePolicyInfo([]byte(`{"Version":1,"Query":"query2","Role":"admin"}`)) + assert.NoError(t, err) + assert.NotEqual(t, expected.Hash, info.Hash) // NOT equal +} diff --git a/app/app.go b/app/app.go index a0a2f4d823..2dcad6abd3 100644 --- a/app/app.go +++ b/app/app.go @@ -25,6 +25,7 @@ import ( "github.com/target/goalert/graphql2/graphqlapp" "github.com/target/goalert/heartbeat" "github.com/target/goalert/integrationkey" + "github.com/target/goalert/integrationkey/uik" "github.com/target/goalert/keyring" "github.com/target/goalert/label" "github.com/target/goalert/limit" @@ -99,6 +100,7 @@ type App struct { ServiceStore *service.Store EscalationStore *escalation.Store IntegrationKeyStore *integrationkey.Store + UIKHandler *uik.Handler ScheduleRuleStore *rule.Store NotificationStore *notification.Store ScheduleStore *schedule.Store diff --git a/app/inithttp.go b/app/inithttp.go index 9d2d6b4bb5..d105eb8bfc 100644 --- a/app/inithttp.go +++ b/app/inithttp.go @@ -9,6 +9,7 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/target/goalert/config" + "github.com/target/goalert/expflag" "github.com/target/goalert/genericapi" "github.com/target/goalert/grafana" "github.com/target/goalert/mailgun" @@ -142,6 +143,9 @@ func (app *App) initHTTP(ctx context.Context) error { mux.HandleFunc("/api/v2/identity/providers/oidc", oidcAuth) mux.HandleFunc("/api/v2/identity/providers/oidc/callback", oidcAuth) + if expflag.ContextHas(ctx, expflag.UnivKeys) { + mux.HandleFunc("POST /api/v2/uik", app.UIKHandler.ServeHTTP) + } mux.HandleFunc("/api/v2/mailgun/incoming", mailgun.IngressWebhooks(app.AlertStore, app.IntegrationKeyStore)) mux.HandleFunc("/api/v2/grafana/incoming", grafana.GrafanaToEventsAPI(app.AlertStore, app.IntegrationKeyStore)) mux.HandleFunc("/api/v2/site24x7/incoming", site24x7.Site24x7ToEventsAPI(app.AlertStore, app.IntegrationKeyStore)) diff --git a/app/initstores.go b/app/initstores.go index 50e4dcfe9d..239db3fe8e 100644 --- a/app/initstores.go +++ b/app/initstores.go @@ -16,6 +16,7 @@ import ( "github.com/target/goalert/escalation" "github.com/target/goalert/heartbeat" "github.com/target/goalert/integrationkey" + "github.com/target/goalert/integrationkey/uik" "github.com/target/goalert/keyring" "github.com/target/goalert/label" "github.com/target/goalert/limit" @@ -217,7 +218,7 @@ func (app *App) initStores(ctx context.Context) error { } if app.IntegrationKeyStore == nil { - app.IntegrationKeyStore = integrationkey.NewStore(ctx, app.db) + app.IntegrationKeyStore = integrationkey.NewStore(ctx, app.db, app.APIKeyring) } if app.ScheduleRuleStore == nil { @@ -299,5 +300,7 @@ func (app *App) initStores(ctx context.Context) error { return errors.Wrap(err, "init API key store") } + app.UIKHandler = uik.NewHandler(app.db, app.IntegrationKeyStore, app.AlertStore) + return nil } diff --git a/auth/authtoken/encode.go b/auth/authtoken/encode.go index b4365e8a07..c60f91f452 100644 --- a/auth/authtoken/encode.go +++ b/auth/authtoken/encode.go @@ -34,6 +34,12 @@ func (t Token) Encode(signFn SignFunc) (string, error) { b[2] = byte(t.Type) copy(b[3:], t.ID[:]) binary.BigEndian.PutUint64(b[19:], uint64(t.CreatedAt.Unix())) + case 3: + b = make([]byte, 19) + b[0] = 'V' // versioned header format + b[1] = 3 + b[2] = byte(t.Type) + copy(b[3:], t.ID[:]) default: return "", validation.NewFieldError("Type", "unsupported version") } diff --git a/auth/authtoken/parse.go b/auth/authtoken/parse.go index 9f2066e7a4..0c349c127a 100644 --- a/auth/authtoken/parse.go +++ b/auth/authtoken/parse.go @@ -73,6 +73,20 @@ func Parse(s string, verifyFn VerifyFunc) (*Token, bool, error) { } switch data[1] { + case 3: + if len(data) < 19 { + return nil, false, validation.NewGenericError("invalid length") + } + t := &Token{ + Version: 3, + Type: Type(data[2]), + } + valid, isOldKey := verifyFn(t.Type, data[:19], data[19:]) + if !valid { + return nil, false, validation.NewGenericError("invalid signature") + } + copy(t.ID[:], data[3:]) + return t, isOldKey, nil case 2: if len(data) < 27 { return nil, false, validation.NewGenericError("invalid length") diff --git a/auth/authtoken/type.go b/auth/authtoken/type.go index 8ed8223335..2eaac4d6ca 100644 --- a/auth/authtoken/type.go +++ b/auth/authtoken/type.go @@ -8,4 +8,5 @@ const ( TypeUnknown Type = iota // always make the zero-value Unknown TypeSession TypeCalSub + TypeUIK ) diff --git a/auth/handler.go b/auth/handler.go index 888375d37c..a829f4362b 100644 --- a/auth/handler.go +++ b/auth/handler.go @@ -564,6 +564,15 @@ func (h *Handler) authWithToken(w http.ResponseWriter, req *http.Request, next h next.ServeHTTP(w, req.WithContext(ctx)) return true } + if req.URL.Path == "/api/v2/uik" && strings.HasPrefix(tokStr, "ey") { + ctx, err = h.cfg.IntKeyStore.AuthorizeUIK(ctx, tokStr) + if errutil.HTTPError(req.Context(), w, err) { + return true + } + + next.ServeHTTP(w, req.WithContext(ctx)) + return true + } tok, _, err := authtoken.Parse(tokStr, func(t authtoken.Type, p, sig []byte) (bool, bool) { if t == authtoken.TypeSession { diff --git a/cmd/goalert-slack-email-sync/main.go b/cmd/goalert-slack-email-sync/main.go index 0a3160dc9d..dd754f977a 100644 --- a/cmd/goalert-slack-email-sync/main.go +++ b/cmd/goalert-slack-email-sync/main.go @@ -39,7 +39,7 @@ func main() { creds = credentials.NewTLS(cfg) } - conn, err := grpc.Dial(*api, grpc.WithTransportCredentials(creds)) + conn, err := grpc.NewClient(*api, grpc.WithTransportCredentials(creds)) if err != nil { log.Fatal("connect to GoAlert:", err) } diff --git a/devtools/gqltsgen/run.go b/devtools/gqltsgen/run.go index b9d2379187..ae3fd3d581 100644 --- a/devtools/gqltsgen/run.go +++ b/devtools/gqltsgen/run.go @@ -144,6 +144,9 @@ func main() { if def.Name == "WeekdayFilter" { typeName = "[boolean, boolean, boolean, boolean, boolean, boolean, boolean]" } + if strings.HasSuffix(def.Name, "Map") { + typeName = "Record" + } fmt.Fprintf(w, "export type %s = %s\n\n", def.Name, typeName) case ast.Union: sort.Strings(def.Types) diff --git a/devtools/pgdump-lite/pgd/db.go b/devtools/pgdump-lite/pgd/db.go index 037305d722..73af1ff2c5 100644 --- a/devtools/pgdump-lite/pgd/db.go +++ b/devtools/pgdump-lite/pgd/db.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.26.0 package pgd diff --git a/devtools/pgdump-lite/pgd/models.go b/devtools/pgdump-lite/pgd/models.go index 7ee37c351a..145322b418 100644 --- a/devtools/pgdump-lite/pgd/models.go +++ b/devtools/pgdump-lite/pgd/models.go @@ -1,7 +1,5 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.26.0 package pgd - -import () diff --git a/devtools/pgdump-lite/pgd/queries.sql.go b/devtools/pgdump-lite/pgd/queries.sql.go index ba5c2a9851..9cb2b7cf2e 100644 --- a/devtools/pgdump-lite/pgd/queries.sql.go +++ b/devtools/pgdump-lite/pgd/queries.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.26.0 // source: queries.sql package pgd diff --git a/devtools/resetdb/main.go b/devtools/resetdb/main.go index 66bacc9fb7..8b256f300d 100644 --- a/devtools/resetdb/main.go +++ b/devtools/resetdb/main.go @@ -15,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/jackc/pgtype" "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" "github.com/jackc/pgx/v5/pgxpool" "github.com/pkg/errors" ) @@ -96,6 +97,10 @@ func fillDB(ctx context.Context, dataCfg *datagenConfig, url string) error { defer pool.Close() must := func(err error) { + var pgErr *pgconn.PgError + if errors.As(err, &pgErr) { + log.Printf("ERROR: %s\n%s\n%s\n", pgErr.Detail, pgErr.InternalQuery, pgErr.Where) + } if err != nil { log.Fatal(err) } diff --git a/engine/message/db.go b/engine/message/db.go index 90a564a093..e68fb74995 100644 --- a/engine/message/db.go +++ b/engine/message/db.go @@ -12,6 +12,7 @@ import ( "github.com/target/goalert/app/lifecycle" "github.com/target/goalert/config" "github.com/target/goalert/engine/processinglock" + "github.com/target/goalert/gadb" "github.com/target/goalert/lock" "github.com/target/goalert/notification" "github.com/target/goalert/permission" @@ -34,7 +35,6 @@ type DB struct { setSending *sql.Stmt lockStmt *sql.Stmt - messages *sql.Stmt currentTime *sql.Stmt retryReset *sql.Stmt retryClear *sql.Stmt @@ -299,32 +299,6 @@ func NewDB(ctx context.Context, db *sql.DB, a *alertlog.Store, pausable lifecycl where id = any($2::uuid[]) `), - messages: p.P(` - select - msg.id, - msg.message_type, - cm.type, - chan.type, - coalesce(msg.contact_method_id, msg.channel_id), - coalesce(cm.value, chan.value), - msg.alert_id, - msg.alert_log_id, - msg.user_verification_code_id, - cm.user_id, - msg.service_id, - msg.created_at, - msg.sent_at, - msg.status_alert_ids, - msg.schedule_id - from outgoing_messages msg - left join user_contact_methods cm on cm.id = msg.contact_method_id - left join notification_channels chan on chan.id = msg.channel_id - where - sent_at >= $1 or - last_status = 'pending' and - (msg.contact_method_id isnull or msg.message_type = 'verification_message' or not cm.disabled) - `), - deleteAny: p.P(`delete from outgoing_messages where id = any($1)`), }, p.Err } @@ -336,53 +310,44 @@ func (db *DB) currentQueue(ctx context.Context, tx *sql.Tx, now time.Time) (*que sentSince = cutoff } - rows, err := tx.StmtContext(ctx, db.messages).QueryContext(ctx, sentSince) + rows, err := gadb.New(tx).MessageMgrGetPending(ctx, sql.NullTime{Time: sentSince, Valid: true}) if err != nil { return nil, errors.Wrap(err, "fetch outgoing messages") } - defer rows.Close() - result := make([]Message, 0, len(db.sentMessages)) - for rows.Next() { + result := make([]Message, 0, len(rows)) + for _, row := range rows { var msg Message - var destID, destValue, verifyID, userID, serviceID, scheduleID sql.NullString - var dstType notification.ScannableDestType - var alertID, logID sql.NullInt64 - var statusAlertIDs sqlutil.IntArray - var createdAt, sentAt sql.NullTime - err = rows.Scan( - &msg.ID, - &msg.Type, - &dstType.CM, - &dstType.NC, - &destID, - &destValue, - &alertID, - &logID, - &verifyID, - &userID, - &serviceID, - &createdAt, - &sentAt, - &statusAlertIDs, - &scheduleID, - ) + msg.ID = row.ID.String() + err = msg.Type.FromDB(row.MessageType) if err != nil { - return nil, errors.Wrap(err, "scan row") + return nil, fmt.Errorf("message type: %w", err) + } + msg.AlertID = int(row.AlertID.Int64) + msg.AlertLogID = int(row.AlertLogID.Int64) + if row.UserVerificationCodeID.Valid { + msg.VerifyID = row.UserVerificationCodeID.UUID.String() + } + if row.UserID.Valid { + msg.UserID = row.UserID.UUID.String() + } + if row.ServiceID.Valid { + msg.ServiceID = row.ServiceID.UUID.String() + } + msg.CreatedAt = row.CreatedAt + msg.SentAt = row.SentAt.Time + msg.Dest = notification.SQLDest{ + CMID: row.CmID, + CMType: row.CmType, + CMValue: row.CmValue, + NCID: row.ChanID, + NCType: row.ChanType, + NCValue: row.ChanValue, + }.Dest() + msg.StatusAlertIDs = row.StatusAlertIds + if row.ScheduleID.Valid { + msg.ScheduleID = row.ScheduleID.UUID.String() } - msg.AlertID = int(alertID.Int64) - msg.AlertLogID = int(logID.Int64) - msg.VerifyID = verifyID.String - msg.UserID = userID.String - msg.ServiceID = serviceID.String - msg.CreatedAt = createdAt.Time - msg.SentAt = sentAt.Time - msg.Dest.ID = destID.String - msg.Dest.Value = destValue.String - msg.StatusAlertIDs = statusAlertIDs - msg.ScheduleID = scheduleID.String - - msg.Dest.Type = dstType.DestType() if msg.Dest.Type == notification.DestTypeUnknown { log.Debugf(ctx, "unknown message type for message %s", msg.ID) continue diff --git a/engine/message/message.go b/engine/message/message.go index 275147c336..e37930931a 100644 --- a/engine/message/message.go +++ b/engine/message/message.go @@ -21,5 +21,5 @@ type Message struct { CreatedAt time.Time SentAt time.Time - StatusAlertIDs []int + StatusAlertIDs []int64 } diff --git a/engine/message/queries.sql b/engine/message/queries.sql new file mode 100644 index 0000000000..7f98975db0 --- /dev/null +++ b/engine/message/queries.sql @@ -0,0 +1,30 @@ +-- name: MessageMgrGetPending :many +SELECT + msg.id, + msg.message_type, + cm.id AS cm_id, + cm.type AS cm_type, + cm.value AS cm_value, + chan.id AS chan_id, + chan.type AS chan_type, + chan.value AS chan_value, + msg.alert_id, + msg.alert_log_id, + msg.user_verification_code_id, + cm.user_id, + msg.service_id, + msg.created_at, + msg.sent_at, + msg.status_alert_ids, + msg.schedule_id +FROM + outgoing_messages msg + LEFT JOIN user_contact_methods cm ON cm.id = msg.contact_method_id + LEFT JOIN notification_channels chan ON chan.id = msg.channel_id +WHERE + sent_at >= $1 + OR last_status = 'pending' + AND (msg.contact_method_id ISNULL + OR msg.message_type = 'verification_message' + OR NOT cm.disabled); + diff --git a/expflag/flags.go b/expflag/flags.go index d965db426b..f553ae3f29 100644 --- a/expflag/flags.go +++ b/expflag/flags.go @@ -5,15 +5,13 @@ import "sort" type Flag string const ( - Example Flag = "example" - DestTypes Flag = "dest-types" - UnivKeys Flag = "univ-keys" + Example Flag = "example" + UnivKeys Flag = "univ-keys" ) var desc = map[Flag]string{ - Example: "An example experimental flag to demonstrate usage.", - DestTypes: "Generic destination type API.", - UnivKeys: "Universal integration key support.", + Example: "An example experimental flag to demonstrate usage.", + UnivKeys: "Universal integration key support.", } // AllFlags returns a slice of all experimental flags sorted by name. diff --git a/gadb/db.go b/gadb/db.go index 23b26283dd..6f41631580 100644 --- a/gadb/db.go +++ b/gadb/db.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.26.0 package gadb diff --git a/gadb/dest.go b/gadb/dest.go new file mode 100644 index 0000000000..c09f804283 --- /dev/null +++ b/gadb/dest.go @@ -0,0 +1,78 @@ +package gadb + +import ( + "encoding/json" + "fmt" +) + +type DestV1 struct { + Args map[string]string + Type string +} + +// Scan implements the Scanner interface. +func (ns *DestV1) Scan(value interface{}) error { + switch v := value.(type) { + case json.RawMessage: + err := json.Unmarshal(v, ns) + if err != nil { + return err + } + case []byte: + err := json.Unmarshal(v, ns) + if err != nil { + return err + } + case string: + err := json.Unmarshal([]byte(v), ns) + if err != nil { + return err + } + default: + return fmt.Errorf("unsupported scan for DestV1 type: %T", value) + } + + if ns.Args == nil { + ns.Args = map[string]string{} + } + + return nil +} + +// Value implements the driver Valuer interface. +func (ns DestV1) Value() (interface{}, error) { + if ns.Args == nil { + ns.Args = map[string]string{} + } + data, err := json.Marshal(ns) + if err != nil { + return nil, err + } + + return json.RawMessage(data), nil +} + +type NullDestV1 struct { + Valid bool + DestV1 DestV1 +} + +// Scan implements the Scanner interface. +func (ns *NullDestV1) Scan(value interface{}) error { + if value == nil { + ns.DestV1, ns.Valid = DestV1{}, false + return nil + } + + ns.Valid = true + return ns.DestV1.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullDestV1) Value() (interface{}, error) { + if !ns.Valid { + return nil, nil + } + + return ns.DestV1.Value() +} diff --git a/gadb/models.go b/gadb/models.go index a5a9526e15..ec5aad579b 100644 --- a/gadb/models.go +++ b/gadb/models.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.26.0 package gadb @@ -397,6 +397,7 @@ func (ns NullEnumLimitType) Value() (driver.Value, error) { type EnumNotifChannelType string const ( + EnumNotifChannelTypeDEST EnumNotifChannelType = "DEST" EnumNotifChannelTypeSLACK EnumNotifChannelType = "SLACK" EnumNotifChannelTypeSLACKUSERGROUP EnumNotifChannelType = "SLACK_USER_GROUP" EnumNotifChannelTypeWEBHOOK EnumNotifChannelType = "WEBHOOK" @@ -663,6 +664,7 @@ func (ns NullEnumThrottleType) Value() (driver.Value, error) { type EnumUserContactMethodType string const ( + EnumUserContactMethodTypeDEST EnumUserContactMethodType = "DEST" EnumUserContactMethodTypeEMAIL EnumUserContactMethodType = "EMAIL" EnumUserContactMethodTypePUSH EnumUserContactMethodType = "PUSH" EnumUserContactMethodTypeSLACKDM EnumUserContactMethodType = "SLACK_DM" @@ -972,6 +974,7 @@ type Label struct { type NotificationChannel struct { CreatedAt time.Time + Dest NullDestV1 ID uuid.UUID Meta json.RawMessage Name string @@ -1138,8 +1141,12 @@ type TwilioVoiceError struct { } type UikConfig struct { - Config json.RawMessage - ID uuid.UUID + Config json.RawMessage + ID uuid.UUID + PrimaryToken uuid.NullUUID + PrimaryTokenHint sql.NullString + SecondaryToken uuid.NullUUID + SecondaryTokenHint sql.NullString } type User struct { @@ -1165,6 +1172,7 @@ type UserCalendarSubscription struct { } type UserContactMethod struct { + Dest NullDestV1 Disabled bool EnableStatusUpdates bool ID uuid.UUID diff --git a/gadb/queries.sql.go b/gadb/queries.sql.go index 962e1d8093..77c7608d6f 100644 --- a/gadb/queries.sql.go +++ b/gadb/queries.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.26.0 // source: queries.sql package gadb @@ -1396,6 +1396,59 @@ func (q *Queries) FindOneCalSubForUpdate(ctx context.Context, id uuid.UUID) (Fin return i, err } +const gQLUserOnCallOverview = `-- name: GQLUserOnCallOverview :many +SELECT + svc.id AS service_id, + svc.name AS service_name, + ep.id AS policy_id, + ep.name AS policy_name, + step.step_number +FROM + ep_step_on_call_users oc + JOIN escalation_policy_steps step ON step.id = oc.ep_step_id + JOIN escalation_policies ep ON ep.id = step.escalation_policy_id + JOIN services svc ON svc.escalation_policy_id = ep.id +WHERE + oc.user_id = $1 +` + +type GQLUserOnCallOverviewRow struct { + ServiceID uuid.UUID + ServiceName string + PolicyID uuid.UUID + PolicyName string + StepNumber int32 +} + +func (q *Queries) GQLUserOnCallOverview(ctx context.Context, userID uuid.UUID) ([]GQLUserOnCallOverviewRow, error) { + rows, err := q.db.QueryContext(ctx, gQLUserOnCallOverview, userID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GQLUserOnCallOverviewRow + for rows.Next() { + var i GQLUserOnCallOverviewRow + if err := rows.Scan( + &i.ServiceID, + &i.ServiceName, + &i.PolicyID, + &i.PolicyName, + &i.StepNumber, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const intKeyCreate = `-- name: IntKeyCreate :exec INSERT INTO integration_keys(id, name, type, service_id, external_system_name) VALUES ($1, $2, $3, $4, $5) @@ -1440,6 +1493,21 @@ func (q *Queries) IntKeyDeleteConfig(ctx context.Context, id uuid.UUID) error { return err } +const intKeyDeleteSecondaryToken = `-- name: IntKeyDeleteSecondaryToken :exec +UPDATE + uik_config +SET + secondary_token = NULL, + secondary_token_hint = NULL +WHERE + id = $1 +` + +func (q *Queries) IntKeyDeleteSecondaryToken(ctx context.Context, id uuid.UUID) error { + _, err := q.db.ExecContext(ctx, intKeyDeleteSecondaryToken, id) + return err +} + const intKeyFindByService = `-- name: IntKeyFindByService :many SELECT id, @@ -1579,6 +1647,27 @@ func (q *Queries) IntKeyGetType(ctx context.Context, id uuid.UUID) (EnumIntegrat return type_, err } +const intKeyPromoteSecondary = `-- name: IntKeyPromoteSecondary :one +UPDATE + uik_config +SET + primary_token = secondary_token, + primary_token_hint = secondary_token_hint, + secondary_token = NULL, + secondary_token_hint = NULL +WHERE + id = $1 +RETURNING + primary_token_hint +` + +func (q *Queries) IntKeyPromoteSecondary(ctx context.Context, id uuid.UUID) (sql.NullString, error) { + row := q.db.QueryRowContext(ctx, intKeyPromoteSecondary, id) + var primary_token_hint sql.NullString + err := row.Scan(&primary_token_hint) + return primary_token_hint, err +} + const intKeySetConfig = `-- name: IntKeySetConfig :exec INSERT INTO uik_config(id, config) VALUES ($1, $2) @@ -1597,6 +1686,106 @@ func (q *Queries) IntKeySetConfig(ctx context.Context, arg IntKeySetConfigParams return err } +const intKeySetPrimaryToken = `-- name: IntKeySetPrimaryToken :one +UPDATE + uik_config +SET + primary_token = $2, + primary_token_hint = $3 +WHERE + id = $1 + AND primary_token IS NULL +RETURNING + id +` + +type IntKeySetPrimaryTokenParams struct { + ID uuid.UUID + PrimaryToken uuid.NullUUID + PrimaryTokenHint sql.NullString +} + +func (q *Queries) IntKeySetPrimaryToken(ctx context.Context, arg IntKeySetPrimaryTokenParams) (uuid.UUID, error) { + row := q.db.QueryRowContext(ctx, intKeySetPrimaryToken, arg.ID, arg.PrimaryToken, arg.PrimaryTokenHint) + var id uuid.UUID + err := row.Scan(&id) + return id, err +} + +const intKeySetSecondaryToken = `-- name: IntKeySetSecondaryToken :one +UPDATE + uik_config +SET + secondary_token = $2, + secondary_token_hint = $3 +WHERE + id = $1 + AND secondary_token IS NULL + AND primary_token IS NOT NULL +RETURNING + id +` + +type IntKeySetSecondaryTokenParams struct { + ID uuid.UUID + SecondaryToken uuid.NullUUID + SecondaryTokenHint sql.NullString +} + +func (q *Queries) IntKeySetSecondaryToken(ctx context.Context, arg IntKeySetSecondaryTokenParams) (uuid.UUID, error) { + row := q.db.QueryRowContext(ctx, intKeySetSecondaryToken, arg.ID, arg.SecondaryToken, arg.SecondaryTokenHint) + var id uuid.UUID + err := row.Scan(&id) + return id, err +} + +const intKeyTokenHints = `-- name: IntKeyTokenHints :one +SELECT + primary_token_hint, + secondary_token_hint +FROM + uik_config +WHERE + id = $1 +` + +type IntKeyTokenHintsRow struct { + PrimaryTokenHint sql.NullString + SecondaryTokenHint sql.NullString +} + +func (q *Queries) IntKeyTokenHints(ctx context.Context, id uuid.UUID) (IntKeyTokenHintsRow, error) { + row := q.db.QueryRowContext(ctx, intKeyTokenHints, id) + var i IntKeyTokenHintsRow + err := row.Scan(&i.PrimaryTokenHint, &i.SecondaryTokenHint) + return i, err +} + +const intKeyUIKValidateService = `-- name: IntKeyUIKValidateService :one +SELECT + k.service_id +FROM + uik_config c + JOIN integration_keys k ON k.id = c.id +WHERE + c.id = $1 + AND k.type = 'universal' + AND (c.primary_token = $2 + OR c.secondary_token = $2) +` + +type IntKeyUIKValidateServiceParams struct { + KeyID uuid.UUID + TokenID uuid.NullUUID +} + +func (q *Queries) IntKeyUIKValidateService(ctx context.Context, arg IntKeyUIKValidateServiceParams) (uuid.UUID, error) { + row := q.db.QueryRowContext(ctx, intKeyUIKValidateService, arg.KeyID, arg.TokenID) + var service_id uuid.UUID + err := row.Scan(&service_id) + return service_id, err +} + const labelDeleteKeyByTarget = `-- name: LabelDeleteKeyByTarget :exec DELETE FROM labels WHERE key = $1 @@ -1724,6 +1913,98 @@ func (q *Queries) LockOneAlertService(ctx context.Context, id int64) (LockOneAle return i, err } +const messageMgrGetPending = `-- name: MessageMgrGetPending :many +SELECT + msg.id, + msg.message_type, + cm.id AS cm_id, + cm.type AS cm_type, + cm.value AS cm_value, + chan.id AS chan_id, + chan.type AS chan_type, + chan.value AS chan_value, + msg.alert_id, + msg.alert_log_id, + msg.user_verification_code_id, + cm.user_id, + msg.service_id, + msg.created_at, + msg.sent_at, + msg.status_alert_ids, + msg.schedule_id +FROM + outgoing_messages msg + LEFT JOIN user_contact_methods cm ON cm.id = msg.contact_method_id + LEFT JOIN notification_channels chan ON chan.id = msg.channel_id +WHERE + sent_at >= $1 + OR last_status = 'pending' + AND (msg.contact_method_id ISNULL + OR msg.message_type = 'verification_message' + OR NOT cm.disabled) +` + +type MessageMgrGetPendingRow struct { + ID uuid.UUID + MessageType EnumOutgoingMessagesType + CmID uuid.NullUUID + CmType NullEnumUserContactMethodType + CmValue sql.NullString + ChanID uuid.NullUUID + ChanType NullEnumNotifChannelType + ChanValue sql.NullString + AlertID sql.NullInt64 + AlertLogID sql.NullInt64 + UserVerificationCodeID uuid.NullUUID + UserID uuid.NullUUID + ServiceID uuid.NullUUID + CreatedAt time.Time + SentAt sql.NullTime + StatusAlertIds []int64 + ScheduleID uuid.NullUUID +} + +func (q *Queries) MessageMgrGetPending(ctx context.Context, sentAt sql.NullTime) ([]MessageMgrGetPendingRow, error) { + rows, err := q.db.QueryContext(ctx, messageMgrGetPending, sentAt) + if err != nil { + return nil, err + } + defer rows.Close() + var items []MessageMgrGetPendingRow + for rows.Next() { + var i MessageMgrGetPendingRow + if err := rows.Scan( + &i.ID, + &i.MessageType, + &i.CmID, + &i.CmType, + &i.CmValue, + &i.ChanID, + &i.ChanType, + &i.ChanValue, + &i.AlertID, + &i.AlertLogID, + &i.UserVerificationCodeID, + &i.UserID, + &i.ServiceID, + &i.CreatedAt, + &i.SentAt, + pq.Array(&i.StatusAlertIds), + &i.ScheduleID, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const noticeUnackedAlertsByService = `-- name: NoticeUnackedAlertsByService :one SELECT count(*), @@ -1754,6 +2035,160 @@ func (q *Queries) NoticeUnackedAlertsByService(ctx context.Context, dollar_1 uui return i, err } +const notifChanCreate = `-- name: NotifChanCreate :exec +INSERT INTO notification_channels(id, name, type, value) + VALUES ($1, $2, $3, $4) +` + +type NotifChanCreateParams struct { + ID uuid.UUID + Name string + Type EnumNotifChannelType + Value string +} + +func (q *Queries) NotifChanCreate(ctx context.Context, arg NotifChanCreateParams) error { + _, err := q.db.ExecContext(ctx, notifChanCreate, + arg.ID, + arg.Name, + arg.Type, + arg.Value, + ) + return err +} + +const notifChanDeleteMany = `-- name: NotifChanDeleteMany :exec +DELETE FROM notification_channels +WHERE id = ANY ($1::uuid[]) +` + +func (q *Queries) NotifChanDeleteMany(ctx context.Context, dollar_1 []uuid.UUID) error { + _, err := q.db.ExecContext(ctx, notifChanDeleteMany, pq.Array(dollar_1)) + return err +} + +const notifChanFindByValue = `-- name: NotifChanFindByValue :one +SELECT + created_at, dest, id, meta, name, type, value +FROM + notification_channels +WHERE + type = $1 + AND value = $2 +` + +type NotifChanFindByValueParams struct { + Type EnumNotifChannelType + Value string +} + +func (q *Queries) NotifChanFindByValue(ctx context.Context, arg NotifChanFindByValueParams) (NotificationChannel, error) { + row := q.db.QueryRowContext(ctx, notifChanFindByValue, arg.Type, arg.Value) + var i NotificationChannel + err := row.Scan( + &i.CreatedAt, + &i.Dest, + &i.ID, + &i.Meta, + &i.Name, + &i.Type, + &i.Value, + ) + return i, err +} + +const notifChanFindMany = `-- name: NotifChanFindMany :many +SELECT + created_at, dest, id, meta, name, type, value +FROM + notification_channels +WHERE + id = ANY ($1::uuid[]) +` + +func (q *Queries) NotifChanFindMany(ctx context.Context, dollar_1 []uuid.UUID) ([]NotificationChannel, error) { + rows, err := q.db.QueryContext(ctx, notifChanFindMany, pq.Array(dollar_1)) + if err != nil { + return nil, err + } + defer rows.Close() + var items []NotificationChannel + for rows.Next() { + var i NotificationChannel + if err := rows.Scan( + &i.CreatedAt, + &i.Dest, + &i.ID, + &i.Meta, + &i.Name, + &i.Type, + &i.Value, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const notifChanFindOne = `-- name: NotifChanFindOne :one +SELECT + created_at, dest, id, meta, name, type, value +FROM + notification_channels +WHERE + id = $1 +` + +func (q *Queries) NotifChanFindOne(ctx context.Context, id uuid.UUID) (NotificationChannel, error) { + row := q.db.QueryRowContext(ctx, notifChanFindOne, id) + var i NotificationChannel + err := row.Scan( + &i.CreatedAt, + &i.Dest, + &i.ID, + &i.Meta, + &i.Name, + &i.Type, + &i.Value, + ) + return i, err +} + +const notifChanLock = `-- name: NotifChanLock :exec +LOCK notification_channels IN SHARE ROW EXCLUSIVE MODE +` + +func (q *Queries) NotifChanLock(ctx context.Context) error { + _, err := q.db.ExecContext(ctx, notifChanLock) + return err +} + +const notifChanUpdateName = `-- name: NotifChanUpdateName :exec +UPDATE + notification_channels +SET + name = $2 +WHERE + id = $1 +` + +type NotifChanUpdateNameParams struct { + ID uuid.UUID + Name string +} + +func (q *Queries) NotifChanUpdateName(ctx context.Context, arg NotifChanUpdateNameParams) error { + _, err := q.db.ExecContext(ctx, notifChanUpdateName, arg.ID, arg.Name) + return err +} + const now = `-- name: Now :one SELECT now()::timestamptz diff --git a/go.mod b/go.mod index e3a7e4dfe8..22cedab87d 100644 --- a/go.mod +++ b/go.mod @@ -3,16 +3,16 @@ module github.com/target/goalert go 1.22 require ( - github.com/99designs/gqlgen v0.17.45 + github.com/99designs/gqlgen v0.17.49 github.com/brianvoe/gofakeit/v6 v6.28.0 github.com/coreos/go-oidc/v3 v3.10.0 github.com/creack/pty/v2 v2.0.1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc - github.com/emersion/go-smtp v0.21.1 - github.com/expr-lang/expr v1.16.5 - github.com/fatih/color v1.16.0 + github.com/emersion/go-smtp v0.21.2 + github.com/expr-lang/expr v1.16.9 + github.com/fatih/color v1.17.0 github.com/felixge/httpsnoop v1.0.4 - github.com/fullstorydev/grpcui v1.3.3 + github.com/fullstorydev/grpcui v1.5.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da github.com/google/go-github/v56 v56.0.0 @@ -20,7 +20,7 @@ require ( github.com/gordonklaus/ineffassign v0.1.0 github.com/hashicorp/yamux v0.1.1 github.com/jackc/pgtype v1.14.3 - github.com/jackc/pgx/v5 v5.5.5 + github.com/jackc/pgx/v5 v5.6.0 github.com/jmespath/go-jmespath v0.4.0 github.com/joho/godotenv v1.5.1 github.com/kffl/speedbump v1.1.0 @@ -31,63 +31,63 @@ require ( github.com/mailhog/storage v1.0.1 github.com/matcornic/hermes/v2 v2.1.0 github.com/mnako/letters v0.2.2 - github.com/nyaruka/phonenumbers v1.3.4 - github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282 + github.com/nyaruka/phonenumbers v1.3.6 + github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25 github.com/pelletier/go-toml/v2 v2.2.2 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.19.0 + github.com/prometheus/client_golang v1.19.1 github.com/rubenv/sql-migrate v1.6.1 github.com/sirupsen/logrus v1.9.3 - github.com/slack-go/slack v0.12.5 - github.com/spf13/cobra v1.8.0 - github.com/spf13/viper v1.18.2 + github.com/slack-go/slack v0.13.0 + github.com/spf13/cobra v1.8.1 + github.com/spf13/viper v1.19.0 github.com/sqlc-dev/pqtype v0.3.0 github.com/stretchr/testify v1.9.0 - github.com/vektah/gqlparser/v2 v2.5.11 - golang.org/x/crypto v0.22.0 + github.com/vektah/gqlparser/v2 v2.5.16 + golang.org/x/crypto v0.24.0 golang.org/x/oauth2 v0.19.0 - golang.org/x/sys v0.20.0 - golang.org/x/term v0.19.0 - golang.org/x/tools v0.20.0 - google.golang.org/grpc v1.63.2 - google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 - google.golang.org/protobuf v1.33.0 + golang.org/x/sys v0.21.0 + golang.org/x/term v0.21.0 + golang.org/x/tools v0.22.0 + google.golang.org/grpc v1.64.0 + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.4.0 + google.golang.org/protobuf v1.34.2 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df honnef.co/go/tools v0.4.7 ) require ( - cloud.google.com/go/compute v1.24.0 // indirect + cloud.google.com/go/compute v1.25.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/BurntSushi/toml v1.3.2 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect - github.com/PuerkitoBio/goquery v1.9.1 // indirect + github.com/PuerkitoBio/goquery v1.9.2 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/andybalholm/cascadia v1.3.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect - github.com/bufbuild/protocompile v0.6.0 // indirect + github.com/bufbuild/protocompile v0.10.0 // indirect github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect github.com/envoyproxy/go-control-plane v0.12.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/fullstorydev/grpcurl v1.8.8 // indirect + github.com/fullstorydev/grpcurl v1.9.1 // indirect + github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect - github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-querystring v1.1.0 // indirect - github.com/gorilla/context v1.1.1 // indirect - github.com/gorilla/css v1.0.0 // indirect - github.com/gorilla/mux v1.8.0 // indirect - github.com/gorilla/pat v1.0.1 // indirect + github.com/gorilla/context v1.1.2 // indirect + github.com/gorilla/css v1.0.1 // indirect + github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/pat v1.0.2 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect @@ -104,7 +104,7 @@ require ( github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 // indirect - github.com/jhump/protoreflect v1.15.3 // indirect + github.com/jhump/protoreflect v1.16.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailhog/MailHog-UI v1.0.1 // indirect github.com/mailhog/http v1.0.1 // indirect @@ -129,7 +129,7 @@ require ( github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/smartystreets/goconvey v1.7.2 // indirect - github.com/sosodev/duration v1.2.0 // indirect + github.com/sosodev/duration v1.3.1 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect @@ -138,25 +138,23 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect github.com/t-k/fluent-logger-golang v1.0.0 // indirect github.com/tinylib/msgp v1.1.8 // indirect - github.com/urfave/cli/v2 v2.27.1 // indirect + github.com/urfave/cli/v2 v2.27.2 // indirect github.com/vanng822/css v1.0.1 // indirect - github.com/vanng822/go-premailer v1.20.2 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + github.com/vanng822/go-premailer v1.21.0 // indirect + github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect - golang.org/x/exp/typeparams v0.0.0-20230626212559-97b1e661b5df // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.24.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20240112132812-db7319d0e0e3 // indirect + golang.org/x/mod v0.18.0 // indirect + golang.org/x/net v0.26.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect + golang.org/x/text v0.16.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect - gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index f6d028c5be..bf3d00dc63 100644 --- a/go.sum +++ b/go.sum @@ -1,610 +1,12 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= -cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= -cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= -cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= -cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= -cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= -cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= -cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= -cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= -cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= -cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= -cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= -cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= -cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= -cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= -cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= -cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= -cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= -cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= -cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= -cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= -cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= -cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= -cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= -cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= -cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= -cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= -cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= -cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= -cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= -cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= -cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= -cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= -cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= -cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= -cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= -cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= -cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= -cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= -cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= -cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= -cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= -cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= -cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= -cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= -cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= -cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= -cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= -cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= -cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= -cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= -cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= -cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= -cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= -cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= -cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= -cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= -cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= -cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= -cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= -cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= -cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= -cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= -cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= -cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= -cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= -cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= -cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= -cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= -cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= -cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= -cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= -cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= -cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= -cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= -cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= -cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= -cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= -cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= -cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= -cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= -cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= -cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= -cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= -cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= -cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= -cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= -cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= -cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= -cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= -cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= -cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= -cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= -cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= -cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= -cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= -cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= -cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= -cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= -cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= -cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= -cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= -cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= -cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= -cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= -cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= -cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= -cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= -cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= -cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= -cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= -github.com/99designs/gqlgen v0.17.45 h1:bH0AH67vIJo8JKNKPJP+pOPpQhZeuVRQLf53dKIpDik= -github.com/99designs/gqlgen v0.17.45/go.mod h1:Bas0XQ+Jiu/Xm5E33jC8sES3G+iC2esHBMXcq0fUPs0= +github.com/99designs/gqlgen v0.17.49 h1:b3hNGexHd33fBSAd4NDT/c3NCcQzcAVkknhN9ym36YQ= +github.com/99designs/gqlgen v0.17.49/go.mod h1:tC8YFVZMed81x7UJ7ORUwXF4Kn6SXuucFqQBhN8+BU0= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= @@ -614,81 +16,46 @@ github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0 github.com/Masterminds/sprig v2.16.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= -github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= -github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI= github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY= +github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE= +github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk= github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= -github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= -github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= 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/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= -github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= -github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= -github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= -github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4= github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= -github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= -github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/bufbuild/protocompile v0.10.0 h1:+jW/wnLMLxaCEG8AX9lD0bQ5v9h1RUiMKOBOT5ll9dM= +github.com/bufbuild/protocompile v0.10.0/go.mod h1:G9qQIQo0xZ6Uyj6CMNz0saGmx2so+KONo8/KrELABiY= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50 h1:DBmgJDC9dTfkVyGgipamEh2BpGYxScCH1TOF1LL1cXc= +github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU= github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty/v2 v2.0.1 h1:RDY1VY5b+7m2mfPsugucOYPIxMp+xal5ZheSyVzUA+k= github.com/creack/pty/v2 v2.0.1/go.mod h1:2dSssKp3b86qYEMwA/FPwc3ff+kYpDdQI8osU8J7gxQ= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -697,207 +64,79 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY= github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= -github.com/emersion/go-smtp v0.21.1 h1:VQeZSZAKk8ueYii1yR5Zalmy7jI287eWDUqSaJ68vRM= -github.com/emersion/go-smtp v0.21.1/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= +github.com/emersion/go-smtp v0.21.2 h1:OLDgvZKuofk4em9fT5tFG5j4jE1/hXnX75UMvcrL4AA= +github.com/emersion/go-smtp v0.21.2/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= -github.com/expr-lang/expr v1.16.5 h1:m2hvtguFeVaVNTHj8L7BoAyt7O0PAIBaSVbjdHgRXMs= -github.com/expr-lang/expr v1.16.5/go.mod h1:uCkhfG+x7fcZ5A5sXHKuQ07jGZRl6J0FCAaf2k4PtVQ= +github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI= +github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/fullstorydev/grpcui v1.3.3 h1:Vl1icw1wm9smDbwLU6pJ2+4S+U4Zd4zJJ3JQvRVRAjg= -github.com/fullstorydev/grpcui v1.3.3/go.mod h1:3ims68AvrNhCXBKwY73nqef81kcoKVMgwAN6p3M2F0c= -github.com/fullstorydev/grpcurl v1.8.8 h1:74MrTXbTlsNEAAhbwc4r2F5P4Qu7Rkyn9BflEer8vss= -github.com/fullstorydev/grpcurl v1.8.8/go.mod h1:TRM21TqPbPzHkA9DqSh94oI2g1pD2AFRhLhmGrSht+Q= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/fullstorydev/grpcui v1.5.0 h1:jOoKLMIbAFwZLlOWzfEXGpwNi4IKbWIlpxllvcWBrm0= +github.com/fullstorydev/grpcui v1.5.0/go.mod h1:zsf22AMRaRqVCAxo3sVrbh7ZexlO70JGACwGenuBsgA= +github.com/fullstorydev/grpcurl v1.9.1 h1:YxX1aCcCc4SDBQfj9uoWcTLe8t4NWrZe1y+mk83BQgo= +github.com/fullstorydev/grpcurl v1.9.1/go.mod h1:i8gKLIC6s93WdU3LSmkE5vtsCxyRmihUj5FK1cNW5EM= github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df/go.mod h1:GJr+FCSXshIwgHBtLglIg9M2l2kQSi6QjVAngtzI08Y= +github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= +github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= -github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v56 v56.0.0 h1:TysL7dMa/r7wsQi44BjqlwaHvwlFlqkK8CtBWCX3gb4= github.com/google/go-github/v56 v56.0.0/go.mod h1:D8cdcX98YWJvi7TLo7zM4/h8ZTx6u6fwGEkCdisopo0= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= -github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o= +github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/pat v1.0.1 h1:OeSoj6sffw4/majibAY2BAUsXjNP7fEE+w30KickaL4= -github.com/gorilla/pat v1.0.1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY= +github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= +github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/pat v1.0.2 h1:TDh/RulbnPxMQACcwbgMF5Bf00jaGoeYBNu+XUFuwtE= +github.com/gorilla/pat v1.0.2/go.mod h1:ioQ7dFQ2KXmOmWLJs6vZAfRikcm2D2JyuLrL9b5wVCg= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -915,9 +154,6 @@ github.com/ian-kent/goose v0.0.0-20141221090059-c3541ea826ad h1:5UZIY1lPvsBrRQRg github.com/ian-kent/goose v0.0.0-20141221090059-c3541ea826ad/go.mod h1:VHyJj0/IJFmpYvVqWFIN2HgjCatXujj7XaLLyOMC23M= github.com/ian-kent/linkio v0.0.0-20170807205755-97566b872887 h1:LPaZmcRJS13h+igi07S26uKy0qxCa76u1+pArD+JGrY= github.com/ian-kent/linkio v0.0.0-20170807205755-97566b872887/go.mod h1:aE63iKqF9rMrshaEiYZroUYFZLaYoTuA7pBMsg3lJoY= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= @@ -970,8 +206,8 @@ github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQ github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= github.com/jackc/pgx/v4 v4.18.2 h1:xVpYkNR5pk5bMCZGfClbO962UIqVABcAGt7ha1s/FeU= github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= -github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= -github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= +github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= @@ -981,38 +217,22 @@ github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFr github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA= github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= -github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= -github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= -github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= -github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= -github.com/jhump/protoreflect v1.15.2/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= -github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= -github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= +github.com/jhump/protoreflect v1.16.0 h1:54fZg+49widqXYQ0b+usAFHbMkBGR4PpXrsHc8+TBDg= +github.com/jhump/protoreflect v1.16.0/go.mod h1:oYPd7nPvcBw/5wlDfm/AVmU9zH9BgqGCI469pGxfj/8= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kffl/speedbump v1.1.0 h1:mTLW9ZzWP/1FQCmkZgHhKbphhqJmzzajKKuGXvjibHE= github.com/kffl/speedbump v1.1.0/go.mod h1:6nNWIwc8zM0l41fIArBiVdvcomulEd8v5RX9YBjJoQ4= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -1026,9 +246,6 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailhog/MailHog v1.0.1 h1:NDExFIj+JGzXT3kmG31r7Okrn78Sk/5p9lP/TV8OE4E= @@ -1066,9 +283,6 @@ github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -1077,10 +291,10 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mnako/letters v0.2.2 h1:koVahnzazHIq3aQnjVZE5SBJ7ZG/mXK6uSM4Jh70Naw= github.com/mnako/letters v0.2.2/go.mod h1:8DKs/xAQ9A7TP8zrLiZPvlrX5synZnvRyTT5Ja+QUK4= -github.com/nyaruka/phonenumbers v1.3.4 h1:bF1Wdh++fxw09s3surhVeBhXEcUKG07pHeP8HQXqjn8= -github.com/nyaruka/phonenumbers v1.3.4/go.mod h1:Ut+eFwikULbmCenH6InMKL9csUNLyxHuBLyfkpum11s= -github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282 h1:TQMyrpijtkFyXpNI3rY5hsZQZw+paiH+BfAlsb81HBY= -github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282/go.mod h1:rW25Kyd08Wdn3UVn0YBsDTSvReu0jqpmJKzxITPSjks= +github.com/nyaruka/phonenumbers v1.3.6 h1:33owXWp4d1U+Tyaj9fpci6PbvaQZcXBUO2FybeKeLwQ= +github.com/nyaruka/phonenumbers v1.3.6/go.mod h1:Ut+eFwikULbmCenH6InMKL9csUNLyxHuBLyfkpum11s= +github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25 h1:9bCMuD3TcnjeqjPT2gSlha4asp8NvgcFRYExCaikCxk= +github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25/go.mod h1:eDjgYHYDJbPLBLsyZ6qRaugP0mX8vePOhZ5id1fdzJw= github.com/ogier/pflag v0.0.1 h1:RW6JSWSu/RkSatfcLtogGfFgpim5p7ARQ10ECk5O750= github.com/ogier/pflag v0.0.1/go.mod h1:zkFki7tvTa0tafRvTBIZTvzYyAu6kQhPZFnshFFPE+g= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= @@ -1090,40 +304,26 @@ github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6 github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= -github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -1134,8 +334,6 @@ github.com/rubenv/sql-migrate v1.6.1/go.mod h1:tPzespupJS0jacLfhbwto/UjSX+8h2FdW github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -1150,30 +348,26 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/slack-go/slack v0.12.5 h1:ddZ6uz6XVaB+3MTDhoW04gG+Vc/M/X1ctC+wssy2cqs= -github.com/slack-go/slack v0.12.5/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= +github.com/slack-go/slack v0.13.0 h1:7my/pR2ubZJ9912p9FtvALYpbt0cQPAqkRy2jaSI1PQ= +github.com/slack-go/slack v0.13.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= -github.com/sosodev/duration v1.2.0 h1:pqK/FLSjsAADWY74SyWDCjOcd5l7H8GSnnOGEB9A1Us= -github.com/sosodev/duration v1.2.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= +github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4= +github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/sqlc-dev/pqtype v0.3.0 h1:b09TewZ3cSnO5+M1Kqq05y0+OjqIptxELaSayg7bmqk= github.com/sqlc-dev/pqtype v0.3.0/go.mod h1:oyUjp5981ctiL9UYvj1bVvCKi8OXkCa0u645hce7CAs= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo= @@ -1194,7 +388,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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= @@ -1205,40 +398,22 @@ github.com/t-k/fluent-logger-golang v1.0.0/go.mod h1:6vC3Vzp9Kva0l5J9+YDY5/ROePw github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/unrolled/render v1.0.3/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= -github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= -github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI= +github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM= github.com/vanng822/css v0.0.0-20190504095207-a21e860bcd04/go.mod h1:tcnB1voG49QhCrwq1W0w5hhGasvOg+VQp9i9H1rCM1w= github.com/vanng822/css v1.0.1 h1:10yiXc4e8NI8ldU6mSrWmSWMuyWgPr9DZ63RSlsgDw8= github.com/vanng822/css v1.0.1/go.mod h1:tcnB1voG49QhCrwq1W0w5hhGasvOg+VQp9i9H1rCM1w= github.com/vanng822/go-premailer v0.0.0-20191214114701-be27abe028fe/go.mod h1:JTFJA/t820uFDoyPpErFQ3rb3amdZoPtxcKervG0OE4= -github.com/vanng822/go-premailer v1.20.2 h1:vKs4VdtfXDqL7IXC2pkiBObc1bXM9bYH3Wa+wYw2DnI= -github.com/vanng822/go-premailer v1.20.2/go.mod h1:RAxbRFp6M/B171gsKu8dsyq+Y5NGsUUvYfg+WQWusbE= +github.com/vanng822/go-premailer v1.21.0 h1:qIwX4urphNPO3xa60MGqowmyjzzMtFacJPKNrt1UWFU= +github.com/vanng822/go-premailer v1.21.0/go.mod h1:6Y3H2NzNmK3sFBNgR1ENdfV9hzG8hMzrA1nL/XBbbP4= github.com/vanng822/r2router v0.0.0-20150523112421-1023140a4f30/go.mod h1:1BVq8p2jVr55Ost2PkZWDrG86PiJ/0lxqcXoAcGxvWU= -github.com/vektah/gqlparser/v2 v2.5.11 h1:JJxLtXIoN7+3x6MBdtIP59TP1RANnY7pXOaDnADQSf8= -github.com/vektah/gqlparser/v2 v2.5.11/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/vektah/gqlparser/v2 v2.5.16 h1:1gcmLTvs3JLKXckwCwlUagVn/IlV2bwqle0vJ0vy5p8= +github.com/vektah/gqlparser/v2 v2.5.16/go.mod h1:1lz1OeCqgQbQepsGxPVywrjdBHW2T08PUS3pJqepRww= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -1258,697 +433,150 @@ golang.org/x/crypto v0.0.0-20181029175232-7e6ffbd03851/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4= golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= -golang.org/x/exp/typeparams v0.0.0-20230626212559-97b1e661b5df h1:jfUqBujZx2dktJVEmZpCkyngz7MWrVv1y9kLOqFNsqw= -golang.org/x/exp/typeparams v0.0.0-20230626212559-97b1e661b5df/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/exp/typeparams v0.0.0-20240112132812-db7319d0e0e3 h1:cW4lNfFicb4kAracdjGpt2Vkbnqy07T/gvwWKBeXt74= +golang.org/x/exp/typeparams v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/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.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190225065934-cc5685c2db12/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 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/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= -golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= -gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= -gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= -google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= -google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= -google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.4.0 h1:9SxA29VM43MF5Z9dQu694wmY5t8E/Gxr7s+RSxiIDmc= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.4.0/go.mod h1:yZOK5zhQMiALmuweVdIVoQPa6eIJyXn2B9g5dJDhqX4= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -1959,62 +587,14 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw= gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 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= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= honnef.co/go/tools v0.4.7 h1:9MDAWxMoSnB6QoSqiVr7P5mtkT9pOc1kSxchzPCnqJs= honnef.co/go/tools v0.4.7/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= -lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= -modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= -modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= -modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= -modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= -modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= -modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= -modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/graphql2/compatdestinput.go b/graphql2/compatdestinput.go deleted file mode 100644 index 1370fd8581..0000000000 --- a/graphql2/compatdestinput.go +++ /dev/null @@ -1,19 +0,0 @@ -package graphql2 - -func (d DestinationInput) FieldValue(id string) string { - for _, f := range d.Values { - if f.FieldID == id { - return f.Value - } - } - return "" -} - -func (d Destination) FieldValuePair(id string) FieldValuePair { - for _, f := range d.Values { - if f.FieldID == id { - return f - } - } - return FieldValuePair{} -} diff --git a/graphql2/exprscalar.go b/graphql2/exprscalar.go index e59f34f6e7..960093a258 100644 --- a/graphql2/exprscalar.go +++ b/graphql2/exprscalar.go @@ -143,3 +143,24 @@ func UnmarshalExprOperator(v interface{}) (string, error) { return bin.Operator, nil } + +func UnmarshalExprStringMap(v interface{}) (map[string]string, error) { + m, ok := v.(map[string]any) + if !ok { + return nil, validation.NewGenericError("must be a map") + } + res := make(map[string]string, len(m)) + for k, v := range m { + str, err := UnmarshalExprStringExpression(v) + if err != nil { + return nil, MapValueError{Key: k, Err: err} + } + res[k] = str + } + + return res, nil +} + +func MarshalExprStringMap(v map[string]string) graphql.Marshaler { + return graphql.MarshalAny(v) +} diff --git a/graphql2/generated.go b/graphql2/generated.go index c9c722c6dd..0975487f83 100644 --- a/graphql2/generated.go +++ b/graphql2/generated.go @@ -74,6 +74,7 @@ type ResolverRoot interface { GQLAPIKey() GQLAPIKeyResolver HeartbeatMonitor() HeartbeatMonitorResolver IntegrationKey() IntegrationKeyResolver + KeyConfig() KeyConfigResolver MessageLogConnectionStats() MessageLogConnectionStatsResolver Mutation() MutationResolver OnCallNotificationRule() OnCallNotificationRuleResolver @@ -91,6 +92,7 @@ type ResolverRoot interface { UserNotificationRule() UserNotificationRuleResolver UserOverride() UserOverrideResolver CreateEscalationPolicyStepInput() CreateEscalationPolicyStepInputResolver + DestinationInput() DestinationInputResolver OnCallNotificationRuleInput() OnCallNotificationRuleInputResolver UpdateEscalationPolicyStepInput() UpdateEscalationPolicyStepInputResolver } @@ -244,6 +246,7 @@ type ComplexityRoot struct { } Destination struct { + Args func(childComplexity int) int DisplayInfo func(childComplexity int) int Type func(childComplexity int) int Values func(childComplexity int) int @@ -273,10 +276,12 @@ type ComplexityRoot struct { } DestinationTypeInfo struct { + DynamicParams func(childComplexity int) int Enabled func(childComplexity int) int IconAltText func(childComplexity int) int IconURL func(childComplexity int) int IsContactMethod func(childComplexity int) int + IsDynamicAction func(childComplexity int) int IsEPTarget func(childComplexity int) int IsSchedOnCallNotify func(childComplexity int) int Name func(childComplexity int) int @@ -287,8 +292,10 @@ type ComplexityRoot struct { UserDisclaimer func(childComplexity int) int } - DynamicParam struct { - Expr func(childComplexity int) int + DynamicParamConfig struct { + Hint func(childComplexity int) int + HintURL func(childComplexity int) int + Label func(childComplexity int) int ParamID func(childComplexity int) int } @@ -377,6 +384,7 @@ type ComplexityRoot struct { ID func(childComplexity int) int Name func(childComplexity int) int ServiceID func(childComplexity int) int + TokenInfo func(childComplexity int) int Type func(childComplexity int) int } @@ -393,17 +401,18 @@ type ComplexityRoot struct { } KeyConfig struct { - DefaultActions func(childComplexity int) int - Rules func(childComplexity int) int - StopAtFirstRule func(childComplexity int) int + DefaultActions func(childComplexity int) int + OneRule func(childComplexity int, id string) int + Rules func(childComplexity int) int } KeyRule struct { - Actions func(childComplexity int) int - ConditionExpr func(childComplexity int) int - Description func(childComplexity int) int - ID func(childComplexity int) int - Name func(childComplexity int) int + Actions func(childComplexity int) int + ConditionExpr func(childComplexity int) int + ContinueAfterMatch func(childComplexity int) int + Description func(childComplexity int) int + ID func(childComplexity int) int + Name func(childComplexity int) int } Label struct { @@ -456,9 +465,12 @@ type ComplexityRoot struct { DeleteAll func(childComplexity int, input []assignment.RawTarget) int DeleteAuthSubject func(childComplexity int, input user.AuthSubject) int DeleteGQLAPIKey func(childComplexity int, id string) int + DeleteSecondaryToken func(childComplexity int, id string) int EndAllAuthSessionsByCurrentUser func(childComplexity int) int EscalateAlerts func(childComplexity int, input []int) int + GenerateKeyToken func(childComplexity int, id string) int LinkAccount func(childComplexity int, token string) int + PromoteSecondaryToken func(childComplexity int, id string) int SendContactMethodVerification func(childComplexity int, input SendContactMethodVerificationInput) int SetAlertNoiseReason func(childComplexity int, input SetAlertNoiseReasonInput) int SetConfig func(childComplexity int, input []ConfigValueInput) int @@ -508,6 +520,19 @@ type ComplexityRoot struct { WeekdayFilter func(childComplexity int) int } + OnCallOverview struct { + ServiceAssignments func(childComplexity int) int + ServiceCount func(childComplexity int) int + } + + OnCallServiceAssignment struct { + EscalationPolicyID func(childComplexity int) int + EscalationPolicyName func(childComplexity int) int + ServiceID func(childComplexity int) int + ServiceName func(childComplexity int) int + StepNumber func(childComplexity int) int + } + OnCallShift struct { End func(childComplexity int) int Start func(childComplexity int) int @@ -531,6 +556,7 @@ type ComplexityRoot struct { } Query struct { + ActionInputValidate func(childComplexity int, input ActionInput) int Alert func(childComplexity int, id int) int Alerts func(childComplexity int, input *AlertSearchOptions) int AuthSubjectsForProvider func(childComplexity int, first *int, after *string, providerID string) int @@ -543,7 +569,7 @@ type ComplexityRoot struct { DestinationFieldSearch func(childComplexity int, input DestinationFieldSearchInput) int DestinationFieldValidate func(childComplexity int, input DestinationFieldValidateInput) int DestinationFieldValueName func(childComplexity int, input DestinationFieldValidateInput) int - DestinationTypes func(childComplexity int) int + DestinationTypes func(childComplexity int, isDynamicAction *bool) int EscalationPolicies func(childComplexity int, input *EscalationPolicySearchOptions) int EscalationPolicy func(childComplexity int, id string) int ExperimentalFlags func(childComplexity int) int @@ -747,6 +773,11 @@ type ComplexityRoot struct { PageInfo func(childComplexity int) int } + TokenInfo struct { + PrimaryHint func(childComplexity int) int + SecondaryHint func(childComplexity int) int + } + User struct { AlertStatusCMID func(childComplexity int) int AssignedSchedules func(childComplexity int) int @@ -758,6 +789,7 @@ type ComplexityRoot struct { IsFavorite func(childComplexity int) int Name func(childComplexity int) int NotificationRules func(childComplexity int) int + OnCallOverview func(childComplexity int) int OnCallSteps func(childComplexity int) int Role func(childComplexity int) int Sessions func(childComplexity int) int @@ -850,6 +882,8 @@ type AlertMetricResolver interface { TimeToClose(ctx context.Context, obj *alertmetrics.Metric) (*timeutil.ISODuration, error) } type DestinationResolver interface { + Values(ctx context.Context, obj *Destination) ([]FieldValuePair, error) + Args(ctx context.Context, obj *Destination) (map[string]string, error) DisplayInfo(ctx context.Context, obj *Destination) (InlineDisplayInfo, error) } type EscalationPolicyResolver interface { @@ -883,6 +917,10 @@ type IntegrationKeyResolver interface { Href(ctx context.Context, obj *integrationkey.IntegrationKey) (string, error) Config(ctx context.Context, obj *integrationkey.IntegrationKey) (*KeyConfig, error) + TokenInfo(ctx context.Context, obj *integrationkey.IntegrationKey) (*TokenInfo, error) +} +type KeyConfigResolver interface { + OneRule(ctx context.Context, obj *KeyConfig, id string) (*KeyRule, error) } type MessageLogConnectionStatsResolver interface { TimeSeries(ctx context.Context, obj *notification.SearchOptions, input TimeSeriesOptions) ([]TimeSeriesBucket, error) @@ -941,6 +979,9 @@ type MutationResolver interface { UpdateGQLAPIKey(ctx context.Context, input UpdateGQLAPIKeyInput) (bool, error) DeleteGQLAPIKey(ctx context.Context, id string) (bool, error) UpdateKeyConfig(ctx context.Context, input UpdateKeyConfigInput) (bool, error) + PromoteSecondaryToken(ctx context.Context, id string) (bool, error) + DeleteSecondaryToken(ctx context.Context, id string) (bool, error) + GenerateKeyToken(ctx context.Context, id string) (string, error) } type OnCallNotificationRuleResolver interface { Target(ctx context.Context, obj *schedule.OnCallNotificationRule) (*assignment.RawTarget, error) @@ -991,13 +1032,14 @@ type QueryResolver interface { GenerateSlackAppManifest(ctx context.Context) (string, error) LinkAccountInfo(ctx context.Context, token string) (*LinkAccountInfo, error) SwoStatus(ctx context.Context) (*SWOStatus, error) - DestinationTypes(ctx context.Context) ([]DestinationTypeInfo, error) + DestinationTypes(ctx context.Context, isDynamicAction *bool) ([]DestinationTypeInfo, error) DestinationFieldValidate(ctx context.Context, input DestinationFieldValidateInput) (bool, error) DestinationFieldSearch(ctx context.Context, input DestinationFieldSearchInput) (*FieldSearchConnection, error) DestinationFieldValueName(ctx context.Context, input DestinationFieldValidateInput) (string, error) DestinationDisplayInfo(ctx context.Context, input DestinationInput) (*DestinationDisplayInfo, error) Expr(ctx context.Context) (*Expr, error) GqlAPIKeys(ctx context.Context) ([]GQLAPIKey, error) + ActionInputValidate(ctx context.Context, input ActionInput) (bool, error) } type RotationResolver interface { IsFavorite(ctx context.Context, obj *rotation.Rotation) (bool, error) @@ -1048,6 +1090,7 @@ type UserResolver interface { AuthSubjects(ctx context.Context, obj *user.User) ([]user.AuthSubject, error) Sessions(ctx context.Context, obj *user.User) ([]UserSession, error) OnCallSteps(ctx context.Context, obj *user.User) ([]escalation.Step, error) + OnCallOverview(ctx context.Context, obj *user.User) (*OnCallOverview, error) IsFavorite(ctx context.Context, obj *user.User) (bool, error) AssignedSchedules(ctx context.Context, obj *user.User) ([]schedule.Schedule, error) } @@ -1081,6 +1124,10 @@ type UserOverrideResolver interface { type CreateEscalationPolicyStepInputResolver interface { Actions(ctx context.Context, obj *CreateEscalationPolicyStepInput, data []DestinationInput) error } +type DestinationInputResolver interface { + Values(ctx context.Context, obj *DestinationInput, data []FieldValueInput) error + Args(ctx context.Context, obj *DestinationInput, data map[string]string) error +} type OnCallNotificationRuleInputResolver interface { Dest(ctx context.Context, obj *OnCallNotificationRuleInput, data *DestinationInput) error } @@ -1677,6 +1724,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DebugSendSMSInfo.ProviderURL(childComplexity), true + case "Destination.args": + if e.complexity.Destination.Args == nil { + break + } + + return e.complexity.Destination.Args(childComplexity), true + case "Destination.displayInfo": if e.complexity.Destination.DisplayInfo == nil { break @@ -1796,6 +1850,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DestinationFieldConfig.SupportsValidation(childComplexity), true + case "DestinationTypeInfo.dynamicParams": + if e.complexity.DestinationTypeInfo.DynamicParams == nil { + break + } + + return e.complexity.DestinationTypeInfo.DynamicParams(childComplexity), true + case "DestinationTypeInfo.enabled": if e.complexity.DestinationTypeInfo.Enabled == nil { break @@ -1824,6 +1885,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DestinationTypeInfo.IsContactMethod(childComplexity), true + case "DestinationTypeInfo.isDynamicAction": + if e.complexity.DestinationTypeInfo.IsDynamicAction == nil { + break + } + + return e.complexity.DestinationTypeInfo.IsDynamicAction(childComplexity), true + case "DestinationTypeInfo.isEPTarget": if e.complexity.DestinationTypeInfo.IsEPTarget == nil { break @@ -1880,19 +1948,33 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DestinationTypeInfo.UserDisclaimer(childComplexity), true - case "DynamicParam.expr": - if e.complexity.DynamicParam.Expr == nil { + case "DynamicParamConfig.hint": + if e.complexity.DynamicParamConfig.Hint == nil { + break + } + + return e.complexity.DynamicParamConfig.Hint(childComplexity), true + + case "DynamicParamConfig.hintURL": + if e.complexity.DynamicParamConfig.HintURL == nil { break } - return e.complexity.DynamicParam.Expr(childComplexity), true + return e.complexity.DynamicParamConfig.HintURL(childComplexity), true - case "DynamicParam.paramID": - if e.complexity.DynamicParam.ParamID == nil { + case "DynamicParamConfig.label": + if e.complexity.DynamicParamConfig.Label == nil { break } - return e.complexity.DynamicParam.ParamID(childComplexity), true + return e.complexity.DynamicParamConfig.Label(childComplexity), true + + case "DynamicParamConfig.paramID": + if e.complexity.DynamicParamConfig.ParamID == nil { + break + } + + return e.complexity.DynamicParamConfig.ParamID(childComplexity), true case "EscalationPolicy.assignedTo": if e.complexity.EscalationPolicy.AssignedTo == nil { @@ -2282,6 +2364,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.IntegrationKey.ServiceID(childComplexity), true + case "IntegrationKey.tokenInfo": + if e.complexity.IntegrationKey.TokenInfo == nil { + break + } + + return e.complexity.IntegrationKey.TokenInfo(childComplexity), true + case "IntegrationKey.type": if e.complexity.IntegrationKey.Type == nil { break @@ -2338,19 +2427,24 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.KeyConfig.DefaultActions(childComplexity), true - case "KeyConfig.rules": - if e.complexity.KeyConfig.Rules == nil { + case "KeyConfig.oneRule": + if e.complexity.KeyConfig.OneRule == nil { break } - return e.complexity.KeyConfig.Rules(childComplexity), true + args, err := ec.field_KeyConfig_oneRule_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.KeyConfig.OneRule(childComplexity, args["id"].(string)), true - case "KeyConfig.stopAtFirstRule": - if e.complexity.KeyConfig.StopAtFirstRule == nil { + case "KeyConfig.rules": + if e.complexity.KeyConfig.Rules == nil { break } - return e.complexity.KeyConfig.StopAtFirstRule(childComplexity), true + return e.complexity.KeyConfig.Rules(childComplexity), true case "KeyRule.actions": if e.complexity.KeyRule.Actions == nil { @@ -2366,6 +2460,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.KeyRule.ConditionExpr(childComplexity), true + case "KeyRule.continueAfterMatch": + if e.complexity.KeyRule.ContinueAfterMatch == nil { + break + } + + return e.complexity.KeyRule.ContinueAfterMatch(childComplexity), true + case "KeyRule.description": if e.complexity.KeyRule.Description == nil { break @@ -2745,6 +2846,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.DeleteGQLAPIKey(childComplexity, args["id"].(string)), true + case "Mutation.deleteSecondaryToken": + if e.complexity.Mutation.DeleteSecondaryToken == nil { + break + } + + args, err := ec.field_Mutation_deleteSecondaryToken_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.DeleteSecondaryToken(childComplexity, args["id"].(string)), true + case "Mutation.endAllAuthSessionsByCurrentUser": if e.complexity.Mutation.EndAllAuthSessionsByCurrentUser == nil { break @@ -2764,6 +2877,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.EscalateAlerts(childComplexity, args["input"].([]int)), true + case "Mutation.generateKeyToken": + if e.complexity.Mutation.GenerateKeyToken == nil { + break + } + + args, err := ec.field_Mutation_generateKeyToken_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.GenerateKeyToken(childComplexity, args["id"].(string)), true + case "Mutation.linkAccount": if e.complexity.Mutation.LinkAccount == nil { break @@ -2776,6 +2901,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.LinkAccount(childComplexity, args["token"].(string)), true + case "Mutation.promoteSecondaryToken": + if e.complexity.Mutation.PromoteSecondaryToken == nil { + break + } + + args, err := ec.field_Mutation_promoteSecondaryToken_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.PromoteSecondaryToken(childComplexity, args["id"].(string)), true + case "Mutation.sendContactMethodVerification": if e.complexity.Mutation.SendContactMethodVerification == nil { break @@ -3177,6 +3314,55 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.OnCallNotificationRule.WeekdayFilter(childComplexity), true + case "OnCallOverview.serviceAssignments": + if e.complexity.OnCallOverview.ServiceAssignments == nil { + break + } + + return e.complexity.OnCallOverview.ServiceAssignments(childComplexity), true + + case "OnCallOverview.serviceCount": + if e.complexity.OnCallOverview.ServiceCount == nil { + break + } + + return e.complexity.OnCallOverview.ServiceCount(childComplexity), true + + case "OnCallServiceAssignment.escalationPolicyID": + if e.complexity.OnCallServiceAssignment.EscalationPolicyID == nil { + break + } + + return e.complexity.OnCallServiceAssignment.EscalationPolicyID(childComplexity), true + + case "OnCallServiceAssignment.escalationPolicyName": + if e.complexity.OnCallServiceAssignment.EscalationPolicyName == nil { + break + } + + return e.complexity.OnCallServiceAssignment.EscalationPolicyName(childComplexity), true + + case "OnCallServiceAssignment.serviceID": + if e.complexity.OnCallServiceAssignment.ServiceID == nil { + break + } + + return e.complexity.OnCallServiceAssignment.ServiceID(childComplexity), true + + case "OnCallServiceAssignment.serviceName": + if e.complexity.OnCallServiceAssignment.ServiceName == nil { + break + } + + return e.complexity.OnCallServiceAssignment.ServiceName(childComplexity), true + + case "OnCallServiceAssignment.stepNumber": + if e.complexity.OnCallServiceAssignment.StepNumber == nil { + break + } + + return e.complexity.OnCallServiceAssignment.StepNumber(childComplexity), true + case "OnCallShift.end": if e.complexity.OnCallShift.End == nil { break @@ -3268,6 +3454,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PhoneNumberInfo.Valid(childComplexity), true + case "Query.actionInputValidate": + if e.complexity.Query.ActionInputValidate == nil { + break + } + + args, err := ec.field_Query_actionInputValidate_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.ActionInputValidate(childComplexity, args["input"].(ActionInput)), true + case "Query.alert": if e.complexity.Query.Alert == nil { break @@ -3412,7 +3610,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in break } - return e.complexity.Query.DestinationTypes(childComplexity), true + args, err := ec.field_Query_destinationTypes_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.DestinationTypes(childComplexity, args["isDynamicAction"].(*bool)), true case "Query.escalationPolicies": if e.complexity.Query.EscalationPolicies == nil { @@ -4493,6 +4696,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.TimeZoneConnection.PageInfo(childComplexity), true + case "TokenInfo.primaryHint": + if e.complexity.TokenInfo.PrimaryHint == nil { + break + } + + return e.complexity.TokenInfo.PrimaryHint(childComplexity), true + + case "TokenInfo.secondaryHint": + if e.complexity.TokenInfo.SecondaryHint == nil { + break + } + + return e.complexity.TokenInfo.SecondaryHint(childComplexity), true + case "User.statusUpdateContactMethodID": if e.complexity.User.AlertStatusCMID == nil { break @@ -4563,6 +4780,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.User.NotificationRules(childComplexity), true + case "User.onCallOverview": + if e.complexity.User.OnCallOverview == nil { + break + } + + return e.complexity.User.OnCallOverview(childComplexity), true + case "User.onCallSteps": if e.complexity.User.OnCallSteps == nil { break @@ -4921,7 +5145,6 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputDestinationFieldSearchInput, ec.unmarshalInputDestinationFieldValidateInput, ec.unmarshalInputDestinationInput, - ec.unmarshalInputDynamicParamInput, ec.unmarshalInputEscalationPolicySearchOptions, ec.unmarshalInputExprToConditionInput, ec.unmarshalInputFieldValueInput, @@ -5168,6 +5391,21 @@ func (ec *executionContext) field_Expr_exprToCondition_args(ctx context.Context, return args, nil } +func (ec *executionContext) field_KeyConfig_oneRule_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + func (ec *executionContext) field_MessageLogConnectionStats_timeSeries_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -5528,6 +5766,21 @@ func (ec *executionContext) field_Mutation_deleteGQLAPIKey_args(ctx context.Cont return args, nil } +func (ec *executionContext) field_Mutation_deleteSecondaryToken_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_escalateAlerts_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -5543,6 +5796,21 @@ func (ec *executionContext) field_Mutation_escalateAlerts_args(ctx context.Conte return args, nil } +func (ec *executionContext) field_Mutation_generateKeyToken_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_linkAccount_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -5558,6 +5826,21 @@ func (ec *executionContext) field_Mutation_linkAccount_args(ctx context.Context, return args, nil } +func (ec *executionContext) field_Mutation_promoteSecondaryToken_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_sendContactMethodVerification_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -5978,6 +6261,21 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs return args, nil } +func (ec *executionContext) field_Query_actionInputValidate_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 ActionInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNActionInput2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐActionInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_alert_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -6161,6 +6459,21 @@ func (ec *executionContext) field_Query_destinationFieldValueName_args(ctx conte return args, nil } +func (ec *executionContext) field_Query_destinationTypes_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *bool + if tmp, ok := rawArgs["isDynamicAction"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("isDynamicAction")) + arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["isDynamicAction"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_escalationPolicies_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -6740,7 +7053,7 @@ func (ec *executionContext) _Action_dest(ctx context.Context, field graphql.Coll return ec.marshalNDestination2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDestination(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Action_dest(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Action_dest(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Action", Field: field, @@ -6752,6 +7065,8 @@ func (ec *executionContext) fieldContext_Action_dest(ctx context.Context, field return ec.fieldContext_Destination_type(ctx, field) case "values": return ec.fieldContext_Destination_values(ctx, field) + case "args": + return ec.fieldContext_Destination_args(ctx, field) case "displayInfo": return ec.fieldContext_Destination_displayInfo(ctx, field) } @@ -6787,25 +7102,19 @@ func (ec *executionContext) _Action_params(ctx context.Context, field graphql.Co } return graphql.Null } - res := resTmp.([]DynamicParam) + res := resTmp.(map[string]string) fc.Result = res - return ec.marshalNDynamicParam2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParamᚄ(ctx, field.Selections, res) + return ec.marshalNExprStringMap2map(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Action_params(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Action_params(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Action", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "paramID": - return ec.fieldContext_DynamicParam_paramID(ctx, field) - case "expr": - return ec.fieldContext_DynamicParam_expr(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type DynamicParam", field.Name) + return nil, errors.New("field of type ExprStringMap does not have child fields") }, } return fc, nil @@ -6842,7 +7151,7 @@ func (ec *executionContext) _Alert_id(ctx context.Context, field graphql.Collect return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -6886,7 +7195,7 @@ func (ec *executionContext) _Alert_alertID(ctx context.Context, field graphql.Co return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_alertID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_alertID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -6930,7 +7239,7 @@ func (ec *executionContext) _Alert_status(ctx context.Context, field graphql.Col return ec.marshalNAlertStatus2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐAlertStatus(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_status(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_status(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -6974,7 +7283,7 @@ func (ec *executionContext) _Alert_summary(ctx context.Context, field graphql.Co return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_summary(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_summary(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -7018,7 +7327,7 @@ func (ec *executionContext) _Alert_details(ctx context.Context, field graphql.Co return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_details(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_details(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -7062,7 +7371,7 @@ func (ec *executionContext) _Alert_createdAt(ctx context.Context, field graphql. return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_createdAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -7106,7 +7415,7 @@ func (ec *executionContext) _Alert_serviceID(ctx context.Context, field graphql. return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_serviceID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_serviceID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -7147,7 +7456,7 @@ func (ec *executionContext) _Alert_service(ctx context.Context, field graphql.Co return ec.marshalOService2ᚖgithubᚗcomᚋtargetᚋgoalertᚋserviceᚐService(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_service(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_service(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -7214,7 +7523,7 @@ func (ec *executionContext) _Alert_state(ctx context.Context, field graphql.Coll return ec.marshalOAlertState2ᚖgithubᚗcomᚋtargetᚋgoalertᚋalertᚐState(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_state(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -7327,7 +7636,7 @@ func (ec *executionContext) _Alert_pendingNotifications(ctx context.Context, fie return ec.marshalNAlertPendingNotification2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐAlertPendingNotificationᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_pendingNotifications(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_pendingNotifications(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -7372,7 +7681,7 @@ func (ec *executionContext) _Alert_metrics(ctx context.Context, field graphql.Co return ec.marshalOAlertMetric2ᚖgithubᚗcomᚋtargetᚋgoalertᚋalertᚋalertmetricsᚐMetric(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_metrics(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_metrics(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -7423,7 +7732,7 @@ func (ec *executionContext) _Alert_noiseReason(ctx context.Context, field graphq return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_noiseReason(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_noiseReason(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -7464,7 +7773,7 @@ func (ec *executionContext) _Alert_meta(ctx context.Context, field graphql.Colle return ec.marshalOAlertMetadata2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐAlertMetadataᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Alert_meta(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Alert_meta(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Alert", Field: field, @@ -7569,7 +7878,7 @@ func (ec *executionContext) _AlertConnection_nodes(ctx context.Context, field gr return ec.marshalNAlert2ᚕgithubᚗcomᚋtargetᚋgoalertᚋalertᚐAlertᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertConnection", Field: field, @@ -7645,7 +7954,7 @@ func (ec *executionContext) _AlertConnection_pageInfo(ctx context.Context, field return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertConnection", Field: field, @@ -7695,7 +8004,7 @@ func (ec *executionContext) _AlertDataPoint_timestamp(ctx context.Context, field return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertDataPoint_timestamp(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertDataPoint_timestamp(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertDataPoint", Field: field, @@ -7739,7 +8048,7 @@ func (ec *executionContext) _AlertDataPoint_alertCount(ctx context.Context, fiel return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertDataPoint_alertCount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertDataPoint_alertCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertDataPoint", Field: field, @@ -7783,7 +8092,7 @@ func (ec *executionContext) _AlertLogEntry_id(ctx context.Context, field graphql return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertLogEntry_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertLogEntry_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertLogEntry", Field: field, @@ -7827,7 +8136,7 @@ func (ec *executionContext) _AlertLogEntry_timestamp(ctx context.Context, field return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertLogEntry_timestamp(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertLogEntry_timestamp(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertLogEntry", Field: field, @@ -7871,7 +8180,7 @@ func (ec *executionContext) _AlertLogEntry_message(ctx context.Context, field gr return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertLogEntry_message(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertLogEntry_message(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertLogEntry", Field: field, @@ -7912,7 +8221,7 @@ func (ec *executionContext) _AlertLogEntry_state(ctx context.Context, field grap return ec.marshalONotificationState2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐNotificationState(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertLogEntry_state(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertLogEntry_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertLogEntry", Field: field, @@ -7964,7 +8273,7 @@ func (ec *executionContext) _AlertLogEntryConnection_nodes(ctx context.Context, return ec.marshalNAlertLogEntry2ᚕgithubᚗcomᚋtargetᚋgoalertᚋalertᚋalertlogᚐEntryᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertLogEntryConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertLogEntryConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertLogEntryConnection", Field: field, @@ -8018,7 +8327,7 @@ func (ec *executionContext) _AlertLogEntryConnection_pageInfo(ctx context.Contex return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertLogEntryConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertLogEntryConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertLogEntryConnection", Field: field, @@ -8068,7 +8377,7 @@ func (ec *executionContext) _AlertMetadata_key(ctx context.Context, field graphq return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertMetadata_key(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertMetadata_key(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertMetadata", Field: field, @@ -8112,7 +8421,7 @@ func (ec *executionContext) _AlertMetadata_value(ctx context.Context, field grap return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertMetadata_value(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertMetadata_value(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertMetadata", Field: field, @@ -8156,7 +8465,7 @@ func (ec *executionContext) _AlertMetric_escalated(ctx context.Context, field gr return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertMetric_escalated(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertMetric_escalated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertMetric", Field: field, @@ -8200,7 +8509,7 @@ func (ec *executionContext) _AlertMetric_closedAt(ctx context.Context, field gra return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertMetric_closedAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertMetric_closedAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertMetric", Field: field, @@ -8244,7 +8553,7 @@ func (ec *executionContext) _AlertMetric_timeToAck(ctx context.Context, field gr return ec.marshalNISODuration2ᚖgithubᚗcomᚋtargetᚋgoalertᚋutilᚋtimeutilᚐISODuration(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertMetric_timeToAck(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertMetric_timeToAck(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertMetric", Field: field, @@ -8288,7 +8597,7 @@ func (ec *executionContext) _AlertMetric_timeToClose(ctx context.Context, field return ec.marshalNISODuration2ᚖgithubᚗcomᚋtargetᚋgoalertᚋutilᚋtimeutilᚐISODuration(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertMetric_timeToClose(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertMetric_timeToClose(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertMetric", Field: field, @@ -8332,7 +8641,7 @@ func (ec *executionContext) _AlertPendingNotification_destination(ctx context.Co return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertPendingNotification_destination(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertPendingNotification_destination(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertPendingNotification", Field: field, @@ -8376,7 +8685,7 @@ func (ec *executionContext) _AlertState_lastEscalation(ctx context.Context, fiel return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertState_lastEscalation(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertState_lastEscalation(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertState", Field: field, @@ -8420,7 +8729,7 @@ func (ec *executionContext) _AlertState_stepNumber(ctx context.Context, field gr return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertState_stepNumber(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertState_stepNumber(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertState", Field: field, @@ -8464,7 +8773,7 @@ func (ec *executionContext) _AlertState_repeatCount(ctx context.Context, field g return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AlertState_repeatCount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AlertState_repeatCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AlertState", Field: field, @@ -8508,7 +8817,7 @@ func (ec *executionContext) _AuthSubject_providerID(ctx context.Context, field g return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AuthSubject_providerID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AuthSubject_providerID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AuthSubject", Field: field, @@ -8552,7 +8861,7 @@ func (ec *executionContext) _AuthSubject_subjectID(ctx context.Context, field gr return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AuthSubject_subjectID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AuthSubject_subjectID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AuthSubject", Field: field, @@ -8596,7 +8905,7 @@ func (ec *executionContext) _AuthSubject_userID(ctx context.Context, field graph return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AuthSubject_userID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AuthSubject_userID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AuthSubject", Field: field, @@ -8640,7 +8949,7 @@ func (ec *executionContext) _AuthSubjectConnection_nodes(ctx context.Context, fi return ec.marshalNAuthSubject2ᚕgithubᚗcomᚋtargetᚋgoalertᚋuserᚐAuthSubjectᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AuthSubjectConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AuthSubjectConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AuthSubjectConnection", Field: field, @@ -8692,7 +9001,7 @@ func (ec *executionContext) _AuthSubjectConnection_pageInfo(ctx context.Context, return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_AuthSubjectConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_AuthSubjectConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "AuthSubjectConnection", Field: field, @@ -8742,7 +9051,7 @@ func (ec *executionContext) _Clause_field(ctx context.Context, field graphql.Col return ec.marshalNExprIdentifier2githubᚗcomᚋexprᚑlangᚋexprᚋastᚐNode(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Clause_field(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Clause_field(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Clause", Field: field, @@ -8786,7 +9095,7 @@ func (ec *executionContext) _Clause_operator(ctx context.Context, field graphql. return ec.marshalNExprOperator2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Clause_operator(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Clause_operator(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Clause", Field: field, @@ -8830,7 +9139,7 @@ func (ec *executionContext) _Clause_value(ctx context.Context, field graphql.Col return ec.marshalNExprValue2githubᚗcomᚋexprᚑlangᚋexprᚋastᚐNode(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Clause_value(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Clause_value(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Clause", Field: field, @@ -8874,7 +9183,7 @@ func (ec *executionContext) _Clause_negate(ctx context.Context, field graphql.Co return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Clause_negate(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Clause_negate(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Clause", Field: field, @@ -8918,7 +9227,7 @@ func (ec *executionContext) _Condition_clauses(ctx context.Context, field graphq return ec.marshalNClause2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐClauseᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Condition_clauses(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Condition_clauses(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Condition", Field: field, @@ -8972,7 +9281,7 @@ func (ec *executionContext) _ConfigHint_id(ctx context.Context, field graphql.Co return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ConfigHint_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ConfigHint_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ConfigHint", Field: field, @@ -9016,7 +9325,7 @@ func (ec *executionContext) _ConfigHint_value(ctx context.Context, field graphql return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ConfigHint_value(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ConfigHint_value(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ConfigHint", Field: field, @@ -9060,7 +9369,7 @@ func (ec *executionContext) _ConfigValue_id(ctx context.Context, field graphql.C return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ConfigValue_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ConfigValue_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ConfigValue", Field: field, @@ -9104,7 +9413,7 @@ func (ec *executionContext) _ConfigValue_description(ctx context.Context, field return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ConfigValue_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ConfigValue_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ConfigValue", Field: field, @@ -9148,7 +9457,7 @@ func (ec *executionContext) _ConfigValue_value(ctx context.Context, field graphq return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ConfigValue_value(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ConfigValue_value(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ConfigValue", Field: field, @@ -9192,7 +9501,7 @@ func (ec *executionContext) _ConfigValue_type(ctx context.Context, field graphql return ec.marshalNConfigType2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐConfigType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ConfigValue_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ConfigValue_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ConfigValue", Field: field, @@ -9236,7 +9545,7 @@ func (ec *executionContext) _ConfigValue_password(ctx context.Context, field gra return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ConfigValue_password(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ConfigValue_password(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ConfigValue", Field: field, @@ -9280,7 +9589,7 @@ func (ec *executionContext) _ConfigValue_deprecated(ctx context.Context, field g return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ConfigValue_deprecated(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ConfigValue_deprecated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ConfigValue", Field: field, @@ -9324,7 +9633,7 @@ func (ec *executionContext) _CreatedGQLAPIKey_id(ctx context.Context, field grap return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_CreatedGQLAPIKey_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_CreatedGQLAPIKey_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "CreatedGQLAPIKey", Field: field, @@ -9368,7 +9677,7 @@ func (ec *executionContext) _CreatedGQLAPIKey_token(ctx context.Context, field g return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_CreatedGQLAPIKey_token(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_CreatedGQLAPIKey_token(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "CreatedGQLAPIKey", Field: field, @@ -9412,7 +9721,7 @@ func (ec *executionContext) _DebugCarrierInfo_name(ctx context.Context, field gr return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugCarrierInfo_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugCarrierInfo_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugCarrierInfo", Field: field, @@ -9456,7 +9765,7 @@ func (ec *executionContext) _DebugCarrierInfo_type(ctx context.Context, field gr return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugCarrierInfo_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugCarrierInfo_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugCarrierInfo", Field: field, @@ -9500,7 +9809,7 @@ func (ec *executionContext) _DebugCarrierInfo_mobileNetworkCode(ctx context.Cont return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugCarrierInfo_mobileNetworkCode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugCarrierInfo_mobileNetworkCode(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugCarrierInfo", Field: field, @@ -9544,7 +9853,7 @@ func (ec *executionContext) _DebugCarrierInfo_mobileCountryCode(ctx context.Cont return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugCarrierInfo_mobileCountryCode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugCarrierInfo_mobileCountryCode(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugCarrierInfo", Field: field, @@ -9588,7 +9897,7 @@ func (ec *executionContext) _DebugMessage_id(ctx context.Context, field graphql. return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -9632,7 +9941,7 @@ func (ec *executionContext) _DebugMessage_createdAt(ctx context.Context, field g return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_createdAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -9676,7 +9985,7 @@ func (ec *executionContext) _DebugMessage_updatedAt(ctx context.Context, field g return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_updatedAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_updatedAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -9720,7 +10029,7 @@ func (ec *executionContext) _DebugMessage_type(ctx context.Context, field graphq return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -9764,7 +10073,7 @@ func (ec *executionContext) _DebugMessage_status(ctx context.Context, field grap return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_status(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_status(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -9805,7 +10114,7 @@ func (ec *executionContext) _DebugMessage_userID(ctx context.Context, field grap return ec.marshalOID2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_userID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_userID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -9846,7 +10155,7 @@ func (ec *executionContext) _DebugMessage_userName(ctx context.Context, field gr return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_userName(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_userName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -9887,7 +10196,7 @@ func (ec *executionContext) _DebugMessage_source(ctx context.Context, field grap return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_source(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_source(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -9931,7 +10240,7 @@ func (ec *executionContext) _DebugMessage_destination(ctx context.Context, field return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_destination(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_destination(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -9972,7 +10281,7 @@ func (ec *executionContext) _DebugMessage_serviceID(ctx context.Context, field g return ec.marshalOID2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_serviceID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_serviceID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -10013,7 +10322,7 @@ func (ec *executionContext) _DebugMessage_serviceName(ctx context.Context, field return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_serviceName(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_serviceName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -10054,7 +10363,7 @@ func (ec *executionContext) _DebugMessage_alertID(ctx context.Context, field gra return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_alertID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_alertID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -10095,7 +10404,7 @@ func (ec *executionContext) _DebugMessage_providerID(ctx context.Context, field return ec.marshalOID2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_providerID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_providerID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -10136,7 +10445,7 @@ func (ec *executionContext) _DebugMessage_sentAt(ctx context.Context, field grap return ec.marshalOISOTimestamp2ᚖtimeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_sentAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_sentAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -10180,7 +10489,7 @@ func (ec *executionContext) _DebugMessage_retryCount(ctx context.Context, field return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessage_retryCount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessage_retryCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessage", Field: field, @@ -10224,7 +10533,7 @@ func (ec *executionContext) _DebugMessageStatusInfo_state(ctx context.Context, f return ec.marshalNNotificationState2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐNotificationState(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugMessageStatusInfo_state(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugMessageStatusInfo_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugMessageStatusInfo", Field: field, @@ -10276,7 +10585,7 @@ func (ec *executionContext) _DebugSendSMSInfo_id(ctx context.Context, field grap return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugSendSMSInfo_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugSendSMSInfo_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugSendSMSInfo", Field: field, @@ -10320,7 +10629,7 @@ func (ec *executionContext) _DebugSendSMSInfo_providerURL(ctx context.Context, f return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugSendSMSInfo_providerURL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugSendSMSInfo_providerURL(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugSendSMSInfo", Field: field, @@ -10364,7 +10673,7 @@ func (ec *executionContext) _DebugSendSMSInfo_fromNumber(ctx context.Context, fi return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DebugSendSMSInfo_fromNumber(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DebugSendSMSInfo_fromNumber(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DebugSendSMSInfo", Field: field, @@ -10408,7 +10717,7 @@ func (ec *executionContext) _Destination_type(ctx context.Context, field graphql return ec.marshalNDestinationType2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Destination_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Destination_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Destination", Field: field, @@ -10435,7 +10744,7 @@ func (ec *executionContext) _Destination_values(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Values, nil + return ec.resolvers.Destination().Values(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -10452,12 +10761,12 @@ func (ec *executionContext) _Destination_values(ctx context.Context, field graph return ec.marshalNFieldValuePair2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐFieldValuePairᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Destination_values(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Destination_values(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Destination", Field: field, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "fieldID": @@ -10471,8 +10780,8 @@ func (ec *executionContext) fieldContext_Destination_values(ctx context.Context, return fc, nil } -func (ec *executionContext) _Destination_displayInfo(ctx context.Context, field graphql.CollectedField, obj *Destination) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Destination_displayInfo(ctx, field) +func (ec *executionContext) _Destination_args(ctx context.Context, field graphql.CollectedField, obj *Destination) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Destination_args(ctx, field) if err != nil { return graphql.Null } @@ -10485,7 +10794,7 @@ func (ec *executionContext) _Destination_displayInfo(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Destination().DisplayInfo(rctx, obj) + return ec.resolvers.Destination().Args(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -10497,26 +10806,26 @@ func (ec *executionContext) _Destination_displayInfo(ctx context.Context, field } return graphql.Null } - res := resTmp.(InlineDisplayInfo) + res := resTmp.(map[string]string) fc.Result = res - return ec.marshalNInlineDisplayInfo2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐInlineDisplayInfo(ctx, field.Selections, res) + return ec.marshalNStringMap2map(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Destination_displayInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Destination_args(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Destination", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type InlineDisplayInfo does not have child fields") + return nil, errors.New("field of type StringMap does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DestinationDisplayInfo_text(ctx context.Context, field graphql.CollectedField, obj *DestinationDisplayInfo) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DestinationDisplayInfo_text(ctx, field) +func (ec *executionContext) _Destination_displayInfo(ctx context.Context, field graphql.CollectedField, obj *Destination) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Destination_displayInfo(ctx, field) if err != nil { return graphql.Null } @@ -10529,7 +10838,7 @@ func (ec *executionContext) _DestinationDisplayInfo_text(ctx context.Context, fi }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Text, nil + return ec.resolvers.Destination().DisplayInfo(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -10541,26 +10850,26 @@ func (ec *executionContext) _DestinationDisplayInfo_text(ctx context.Context, fi } return graphql.Null } - res := resTmp.(string) + res := resTmp.(InlineDisplayInfo) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNInlineDisplayInfo2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐInlineDisplayInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationDisplayInfo_text(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Destination_displayInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DestinationDisplayInfo", + Object: "Destination", Field: field, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type InlineDisplayInfo does not have child fields") }, } return fc, nil } -func (ec *executionContext) _DestinationDisplayInfo_iconURL(ctx context.Context, field graphql.CollectedField, obj *DestinationDisplayInfo) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DestinationDisplayInfo_iconURL(ctx, field) +func (ec *executionContext) _DestinationDisplayInfo_text(ctx context.Context, field graphql.CollectedField, obj *DestinationDisplayInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DestinationDisplayInfo_text(ctx, field) if err != nil { return graphql.Null } @@ -10573,7 +10882,7 @@ func (ec *executionContext) _DestinationDisplayInfo_iconURL(ctx context.Context, }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.IconURL, nil + return obj.Text, nil }) if err != nil { ec.Error(ctx, err) @@ -10590,7 +10899,7 @@ func (ec *executionContext) _DestinationDisplayInfo_iconURL(ctx context.Context, return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationDisplayInfo_iconURL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationDisplayInfo_text(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationDisplayInfo", Field: field, @@ -10603,8 +10912,8 @@ func (ec *executionContext) fieldContext_DestinationDisplayInfo_iconURL(ctx cont return fc, nil } -func (ec *executionContext) _DestinationDisplayInfo_iconAltText(ctx context.Context, field graphql.CollectedField, obj *DestinationDisplayInfo) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DestinationDisplayInfo_iconAltText(ctx, field) +func (ec *executionContext) _DestinationDisplayInfo_iconURL(ctx context.Context, field graphql.CollectedField, obj *DestinationDisplayInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DestinationDisplayInfo_iconURL(ctx, field) if err != nil { return graphql.Null } @@ -10617,7 +10926,7 @@ func (ec *executionContext) _DestinationDisplayInfo_iconAltText(ctx context.Cont }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.IconAltText, nil + return obj.IconURL, nil }) if err != nil { ec.Error(ctx, err) @@ -10634,7 +10943,7 @@ func (ec *executionContext) _DestinationDisplayInfo_iconAltText(ctx context.Cont return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationDisplayInfo_iconAltText(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationDisplayInfo_iconURL(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationDisplayInfo", Field: field, @@ -10647,8 +10956,8 @@ func (ec *executionContext) fieldContext_DestinationDisplayInfo_iconAltText(ctx return fc, nil } -func (ec *executionContext) _DestinationDisplayInfo_linkURL(ctx context.Context, field graphql.CollectedField, obj *DestinationDisplayInfo) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DestinationDisplayInfo_linkURL(ctx, field) +func (ec *executionContext) _DestinationDisplayInfo_iconAltText(ctx context.Context, field graphql.CollectedField, obj *DestinationDisplayInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DestinationDisplayInfo_iconAltText(ctx, field) if err != nil { return graphql.Null } @@ -10661,7 +10970,7 @@ func (ec *executionContext) _DestinationDisplayInfo_linkURL(ctx context.Context, }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.LinkURL, nil + return obj.IconAltText, nil }) if err != nil { ec.Error(ctx, err) @@ -10678,7 +10987,51 @@ func (ec *executionContext) _DestinationDisplayInfo_linkURL(ctx context.Context, return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationDisplayInfo_linkURL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationDisplayInfo_iconAltText(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DestinationDisplayInfo", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DestinationDisplayInfo_linkURL(ctx context.Context, field graphql.CollectedField, obj *DestinationDisplayInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DestinationDisplayInfo_linkURL(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.LinkURL, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DestinationDisplayInfo_linkURL(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationDisplayInfo", Field: field, @@ -10722,7 +11075,7 @@ func (ec *executionContext) _DestinationDisplayInfoError_error(ctx context.Conte return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationDisplayInfoError_error(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationDisplayInfoError_error(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationDisplayInfoError", Field: field, @@ -10766,7 +11119,7 @@ func (ec *executionContext) _DestinationFieldConfig_fieldID(ctx context.Context, return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationFieldConfig_fieldID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationFieldConfig_fieldID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationFieldConfig", Field: field, @@ -10810,7 +11163,7 @@ func (ec *executionContext) _DestinationFieldConfig_label(ctx context.Context, f return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationFieldConfig_label(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationFieldConfig_label(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationFieldConfig", Field: field, @@ -10854,7 +11207,7 @@ func (ec *executionContext) _DestinationFieldConfig_hint(ctx context.Context, fi return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationFieldConfig_hint(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationFieldConfig_hint(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationFieldConfig", Field: field, @@ -10898,7 +11251,7 @@ func (ec *executionContext) _DestinationFieldConfig_hintURL(ctx context.Context, return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationFieldConfig_hintURL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationFieldConfig_hintURL(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationFieldConfig", Field: field, @@ -10942,7 +11295,7 @@ func (ec *executionContext) _DestinationFieldConfig_placeholderText(ctx context. return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationFieldConfig_placeholderText(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationFieldConfig_placeholderText(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationFieldConfig", Field: field, @@ -10986,7 +11339,7 @@ func (ec *executionContext) _DestinationFieldConfig_prefix(ctx context.Context, return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationFieldConfig_prefix(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationFieldConfig_prefix(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationFieldConfig", Field: field, @@ -11030,7 +11383,7 @@ func (ec *executionContext) _DestinationFieldConfig_inputType(ctx context.Contex return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationFieldConfig_inputType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationFieldConfig_inputType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationFieldConfig", Field: field, @@ -11074,7 +11427,7 @@ func (ec *executionContext) _DestinationFieldConfig_supportsSearch(ctx context.C return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationFieldConfig_supportsSearch(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationFieldConfig_supportsSearch(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationFieldConfig", Field: field, @@ -11118,7 +11471,7 @@ func (ec *executionContext) _DestinationFieldConfig_supportsValidation(ctx conte return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationFieldConfig_supportsValidation(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationFieldConfig_supportsValidation(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationFieldConfig", Field: field, @@ -11162,7 +11515,7 @@ func (ec *executionContext) _DestinationTypeInfo_type(ctx context.Context, field return ec.marshalNDestinationType2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11206,7 +11559,7 @@ func (ec *executionContext) _DestinationTypeInfo_name(ctx context.Context, field return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11250,7 +11603,7 @@ func (ec *executionContext) _DestinationTypeInfo_iconURL(ctx context.Context, fi return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_iconURL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_iconURL(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11294,7 +11647,7 @@ func (ec *executionContext) _DestinationTypeInfo_iconAltText(ctx context.Context return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_iconAltText(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_iconAltText(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11338,7 +11691,7 @@ func (ec *executionContext) _DestinationTypeInfo_enabled(ctx context.Context, fi return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_enabled(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_enabled(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11382,7 +11735,7 @@ func (ec *executionContext) _DestinationTypeInfo_requiredFields(ctx context.Cont return ec.marshalNDestinationFieldConfig2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDestinationFieldConfigᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_requiredFields(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_requiredFields(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11415,6 +11768,60 @@ func (ec *executionContext) fieldContext_DestinationTypeInfo_requiredFields(ctx return fc, nil } +func (ec *executionContext) _DestinationTypeInfo_dynamicParams(ctx context.Context, field graphql.CollectedField, obj *DestinationTypeInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DestinationTypeInfo_dynamicParams(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DynamicParams, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]DynamicParamConfig) + fc.Result = res + return ec.marshalNDynamicParamConfig2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParamConfigᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DestinationTypeInfo_dynamicParams(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DestinationTypeInfo", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "paramID": + return ec.fieldContext_DynamicParamConfig_paramID(ctx, field) + case "label": + return ec.fieldContext_DynamicParamConfig_label(ctx, field) + case "hint": + return ec.fieldContext_DynamicParamConfig_hint(ctx, field) + case "hintURL": + return ec.fieldContext_DynamicParamConfig_hintURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DynamicParamConfig", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _DestinationTypeInfo_userDisclaimer(ctx context.Context, field graphql.CollectedField, obj *DestinationTypeInfo) (ret graphql.Marshaler) { fc, err := ec.fieldContext_DestinationTypeInfo_userDisclaimer(ctx, field) if err != nil { @@ -11446,7 +11853,7 @@ func (ec *executionContext) _DestinationTypeInfo_userDisclaimer(ctx context.Cont return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_userDisclaimer(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_userDisclaimer(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11490,7 +11897,7 @@ func (ec *executionContext) _DestinationTypeInfo_isContactMethod(ctx context.Con return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_isContactMethod(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_isContactMethod(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11534,7 +11941,7 @@ func (ec *executionContext) _DestinationTypeInfo_isEPTarget(ctx context.Context, return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_isEPTarget(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_isEPTarget(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11578,7 +11985,51 @@ func (ec *executionContext) _DestinationTypeInfo_isSchedOnCallNotify(ctx context return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_isSchedOnCallNotify(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_isSchedOnCallNotify(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DestinationTypeInfo", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DestinationTypeInfo_isDynamicAction(ctx context.Context, field graphql.CollectedField, obj *DestinationTypeInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DestinationTypeInfo_isDynamicAction(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsDynamicAction, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DestinationTypeInfo_isDynamicAction(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11622,7 +12073,7 @@ func (ec *executionContext) _DestinationTypeInfo_supportsStatusUpdates(ctx conte return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_supportsStatusUpdates(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_supportsStatusUpdates(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11666,7 +12117,7 @@ func (ec *executionContext) _DestinationTypeInfo_statusUpdatesRequired(ctx conte return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DestinationTypeInfo_statusUpdatesRequired(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DestinationTypeInfo_statusUpdatesRequired(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "DestinationTypeInfo", Field: field, @@ -11679,8 +12130,8 @@ func (ec *executionContext) fieldContext_DestinationTypeInfo_statusUpdatesRequir return fc, nil } -func (ec *executionContext) _DynamicParam_paramID(ctx context.Context, field graphql.CollectedField, obj *DynamicParam) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DynamicParam_paramID(ctx, field) +func (ec *executionContext) _DynamicParamConfig_paramID(ctx context.Context, field graphql.CollectedField, obj *DynamicParamConfig) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DynamicParamConfig_paramID(ctx, field) if err != nil { return graphql.Null } @@ -11710,9 +12161,9 @@ func (ec *executionContext) _DynamicParam_paramID(ctx context.Context, field gra return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DynamicParam_paramID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DynamicParamConfig_paramID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DynamicParam", + Object: "DynamicParamConfig", Field: field, IsMethod: false, IsResolver: false, @@ -11723,8 +12174,8 @@ func (ec *executionContext) fieldContext_DynamicParam_paramID(ctx context.Contex return fc, nil } -func (ec *executionContext) _DynamicParam_expr(ctx context.Context, field graphql.CollectedField, obj *DynamicParam) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_DynamicParam_expr(ctx, field) +func (ec *executionContext) _DynamicParamConfig_label(ctx context.Context, field graphql.CollectedField, obj *DynamicParamConfig) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DynamicParamConfig_label(ctx, field) if err != nil { return graphql.Null } @@ -11737,7 +12188,7 @@ func (ec *executionContext) _DynamicParam_expr(ctx context.Context, field graphq }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Expr, nil + return obj.Label, nil }) if err != nil { ec.Error(ctx, err) @@ -11751,17 +12202,105 @@ func (ec *executionContext) _DynamicParam_expr(ctx context.Context, field graphq } res := resTmp.(string) fc.Result = res - return ec.marshalNExprStringExpression2string(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_DynamicParam_expr(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_DynamicParamConfig_label(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "DynamicParam", + Object: "DynamicParamConfig", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type ExprStringExpression does not have child fields") + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DynamicParamConfig_hint(ctx context.Context, field graphql.CollectedField, obj *DynamicParamConfig) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DynamicParamConfig_hint(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Hint, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DynamicParamConfig_hint(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DynamicParamConfig", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _DynamicParamConfig_hintURL(ctx context.Context, field graphql.CollectedField, obj *DynamicParamConfig) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_DynamicParamConfig_hintURL(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.HintURL, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_DynamicParamConfig_hintURL(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "DynamicParamConfig", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil @@ -11798,7 +12337,7 @@ func (ec *executionContext) _EscalationPolicy_id(ctx context.Context, field grap return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicy_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicy_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicy", Field: field, @@ -11842,7 +12381,7 @@ func (ec *executionContext) _EscalationPolicy_name(ctx context.Context, field gr return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicy_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicy_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicy", Field: field, @@ -11886,7 +12425,7 @@ func (ec *executionContext) _EscalationPolicy_description(ctx context.Context, f return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicy_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicy_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicy", Field: field, @@ -11930,7 +12469,7 @@ func (ec *executionContext) _EscalationPolicy_repeat(ctx context.Context, field return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicy_repeat(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicy_repeat(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicy", Field: field, @@ -11974,7 +12513,7 @@ func (ec *executionContext) _EscalationPolicy_isFavorite(ctx context.Context, fi return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicy_isFavorite(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicy_isFavorite(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicy", Field: field, @@ -12018,7 +12557,7 @@ func (ec *executionContext) _EscalationPolicy_assignedTo(ctx context.Context, fi return ec.marshalNTarget2ᚕgithubᚗcomᚋtargetᚋgoalertᚋassignmentᚐRawTargetᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicy_assignedTo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicy_assignedTo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicy", Field: field, @@ -12070,7 +12609,7 @@ func (ec *executionContext) _EscalationPolicy_steps(ctx context.Context, field g return ec.marshalNEscalationPolicyStep2ᚕgithubᚗcomᚋtargetᚋgoalertᚋescalationᚐStepᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicy_steps(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicy_steps(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicy", Field: field, @@ -12128,7 +12667,7 @@ func (ec *executionContext) _EscalationPolicy_notices(ctx context.Context, field return ec.marshalNNotice2ᚕgithubᚗcomᚋtargetᚋgoalertᚋnoticeᚐNoticeᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicy_notices(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicy_notices(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicy", Field: field, @@ -12180,7 +12719,7 @@ func (ec *executionContext) _EscalationPolicyConnection_nodes(ctx context.Contex return ec.marshalNEscalationPolicy2ᚕgithubᚗcomᚋtargetᚋgoalertᚋescalationᚐPolicyᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicyConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicyConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicyConnection", Field: field, @@ -12242,7 +12781,7 @@ func (ec *executionContext) _EscalationPolicyConnection_pageInfo(ctx context.Con return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicyConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicyConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicyConnection", Field: field, @@ -12292,7 +12831,7 @@ func (ec *executionContext) _EscalationPolicyStep_id(ctx context.Context, field return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicyStep_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicyStep_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicyStep", Field: field, @@ -12336,7 +12875,7 @@ func (ec *executionContext) _EscalationPolicyStep_stepNumber(ctx context.Context return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicyStep_stepNumber(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicyStep_stepNumber(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicyStep", Field: field, @@ -12380,7 +12919,7 @@ func (ec *executionContext) _EscalationPolicyStep_delayMinutes(ctx context.Conte return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicyStep_delayMinutes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicyStep_delayMinutes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicyStep", Field: field, @@ -12424,7 +12963,7 @@ func (ec *executionContext) _EscalationPolicyStep_targets(ctx context.Context, f return ec.marshalNTarget2ᚕgithubᚗcomᚋtargetᚋgoalertᚋassignmentᚐRawTargetᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicyStep_targets(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicyStep_targets(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicyStep", Field: field, @@ -12473,7 +13012,7 @@ func (ec *executionContext) _EscalationPolicyStep_escalationPolicy(ctx context.C return ec.marshalOEscalationPolicy2ᚖgithubᚗcomᚋtargetᚋgoalertᚋescalationᚐPolicy(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicyStep_escalationPolicy(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicyStep_escalationPolicy(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicyStep", Field: field, @@ -12535,7 +13074,7 @@ func (ec *executionContext) _EscalationPolicyStep_actions(ctx context.Context, f return ec.marshalNDestination2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDestinationᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_EscalationPolicyStep_actions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EscalationPolicyStep_actions(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "EscalationPolicyStep", Field: field, @@ -12547,6 +13086,8 @@ func (ec *executionContext) fieldContext_EscalationPolicyStep_actions(ctx contex return ec.fieldContext_Destination_type(ctx, field) case "values": return ec.fieldContext_Destination_values(ctx, field) + case "args": + return ec.fieldContext_Destination_args(ctx, field) case "displayInfo": return ec.fieldContext_Destination_displayInfo(ctx, field) } @@ -12701,7 +13242,7 @@ func (ec *executionContext) _FieldSearchConnection_nodes(ctx context.Context, fi return ec.marshalNFieldSearchResult2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐFieldSearchResultᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_FieldSearchConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_FieldSearchConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "FieldSearchConnection", Field: field, @@ -12755,7 +13296,7 @@ func (ec *executionContext) _FieldSearchConnection_pageInfo(ctx context.Context, return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_FieldSearchConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_FieldSearchConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "FieldSearchConnection", Field: field, @@ -12805,7 +13346,7 @@ func (ec *executionContext) _FieldSearchResult_fieldID(ctx context.Context, fiel return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_FieldSearchResult_fieldID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_FieldSearchResult_fieldID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "FieldSearchResult", Field: field, @@ -12849,7 +13390,7 @@ func (ec *executionContext) _FieldSearchResult_value(ctx context.Context, field return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_FieldSearchResult_value(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_FieldSearchResult_value(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "FieldSearchResult", Field: field, @@ -12893,7 +13434,7 @@ func (ec *executionContext) _FieldSearchResult_label(ctx context.Context, field return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_FieldSearchResult_label(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_FieldSearchResult_label(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "FieldSearchResult", Field: field, @@ -12937,7 +13478,7 @@ func (ec *executionContext) _FieldSearchResult_isFavorite(ctx context.Context, f return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_FieldSearchResult_isFavorite(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_FieldSearchResult_isFavorite(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "FieldSearchResult", Field: field, @@ -12981,7 +13522,7 @@ func (ec *executionContext) _FieldValuePair_fieldID(ctx context.Context, field g return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_FieldValuePair_fieldID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_FieldValuePair_fieldID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "FieldValuePair", Field: field, @@ -13025,7 +13566,7 @@ func (ec *executionContext) _FieldValuePair_value(ctx context.Context, field gra return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_FieldValuePair_value(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_FieldValuePair_value(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "FieldValuePair", Field: field, @@ -13069,7 +13610,7 @@ func (ec *executionContext) _GQLAPIKey_id(ctx context.Context, field graphql.Col return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKey_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKey_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKey", Field: field, @@ -13113,7 +13654,7 @@ func (ec *executionContext) _GQLAPIKey_name(ctx context.Context, field graphql.C return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKey_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKey_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKey", Field: field, @@ -13157,7 +13698,7 @@ func (ec *executionContext) _GQLAPIKey_description(ctx context.Context, field gr return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKey_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKey_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKey", Field: field, @@ -13201,7 +13742,7 @@ func (ec *executionContext) _GQLAPIKey_createdAt(ctx context.Context, field grap return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKey_createdAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKey_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKey", Field: field, @@ -13242,7 +13783,7 @@ func (ec *executionContext) _GQLAPIKey_createdBy(ctx context.Context, field grap return ec.marshalOUser2ᚖgithubᚗcomᚋtargetᚋgoalertᚋuserᚐUser(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKey_createdBy(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKey_createdBy(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKey", Field: field, @@ -13272,6 +13813,8 @@ func (ec *executionContext) fieldContext_GQLAPIKey_createdBy(ctx context.Context return ec.fieldContext_User_sessions(ctx, field) case "onCallSteps": return ec.fieldContext_User_onCallSteps(ctx, field) + case "onCallOverview": + return ec.fieldContext_User_onCallOverview(ctx, field) case "isFavorite": return ec.fieldContext_User_isFavorite(ctx, field) case "assignedSchedules": @@ -13314,7 +13857,7 @@ func (ec *executionContext) _GQLAPIKey_updatedAt(ctx context.Context, field grap return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKey_updatedAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKey_updatedAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKey", Field: field, @@ -13355,7 +13898,7 @@ func (ec *executionContext) _GQLAPIKey_updatedBy(ctx context.Context, field grap return ec.marshalOUser2ᚖgithubᚗcomᚋtargetᚋgoalertᚋuserᚐUser(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKey_updatedBy(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKey_updatedBy(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKey", Field: field, @@ -13385,6 +13928,8 @@ func (ec *executionContext) fieldContext_GQLAPIKey_updatedBy(ctx context.Context return ec.fieldContext_User_sessions(ctx, field) case "onCallSteps": return ec.fieldContext_User_onCallSteps(ctx, field) + case "onCallOverview": + return ec.fieldContext_User_onCallOverview(ctx, field) case "isFavorite": return ec.fieldContext_User_isFavorite(ctx, field) case "assignedSchedules": @@ -13424,7 +13969,7 @@ func (ec *executionContext) _GQLAPIKey_lastUsed(ctx context.Context, field graph return ec.marshalOGQLAPIKeyUsage2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐGQLAPIKeyUsage(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKey_lastUsed(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKey_lastUsed(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKey", Field: field, @@ -13476,7 +14021,7 @@ func (ec *executionContext) _GQLAPIKey_expiresAt(ctx context.Context, field grap return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKey_expiresAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKey_expiresAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKey", Field: field, @@ -13520,7 +14065,7 @@ func (ec *executionContext) _GQLAPIKey_query(ctx context.Context, field graphql. return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKey_query(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKey_query(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKey", Field: field, @@ -13564,7 +14109,7 @@ func (ec *executionContext) _GQLAPIKey_role(ctx context.Context, field graphql.C return ec.marshalNUserRole2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐUserRole(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKey_role(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKey_role(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKey", Field: field, @@ -13608,7 +14153,7 @@ func (ec *executionContext) _GQLAPIKeyUsage_time(ctx context.Context, field grap return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKeyUsage_time(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKeyUsage_time(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKeyUsage", Field: field, @@ -13652,7 +14197,7 @@ func (ec *executionContext) _GQLAPIKeyUsage_ua(ctx context.Context, field graphq return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKeyUsage_ua(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKeyUsage_ua(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKeyUsage", Field: field, @@ -13696,7 +14241,7 @@ func (ec *executionContext) _GQLAPIKeyUsage_ip(ctx context.Context, field graphq return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GQLAPIKeyUsage_ip(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_GQLAPIKeyUsage_ip(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "GQLAPIKeyUsage", Field: field, @@ -13740,7 +14285,7 @@ func (ec *executionContext) _HeartbeatMonitor_id(ctx context.Context, field grap return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_HeartbeatMonitor_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_HeartbeatMonitor_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "HeartbeatMonitor", Field: field, @@ -13784,7 +14329,7 @@ func (ec *executionContext) _HeartbeatMonitor_serviceID(ctx context.Context, fie return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_HeartbeatMonitor_serviceID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_HeartbeatMonitor_serviceID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "HeartbeatMonitor", Field: field, @@ -13828,7 +14373,7 @@ func (ec *executionContext) _HeartbeatMonitor_name(ctx context.Context, field gr return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_HeartbeatMonitor_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_HeartbeatMonitor_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "HeartbeatMonitor", Field: field, @@ -13872,7 +14417,7 @@ func (ec *executionContext) _HeartbeatMonitor_timeoutMinutes(ctx context.Context return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_HeartbeatMonitor_timeoutMinutes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_HeartbeatMonitor_timeoutMinutes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "HeartbeatMonitor", Field: field, @@ -13916,7 +14461,7 @@ func (ec *executionContext) _HeartbeatMonitor_lastState(ctx context.Context, fie return ec.marshalNHeartbeatMonitorState2githubᚗcomᚋtargetᚋgoalertᚋheartbeatᚐState(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_HeartbeatMonitor_lastState(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_HeartbeatMonitor_lastState(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "HeartbeatMonitor", Field: field, @@ -13957,7 +14502,7 @@ func (ec *executionContext) _HeartbeatMonitor_lastHeartbeat(ctx context.Context, return ec.marshalOISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_HeartbeatMonitor_lastHeartbeat(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_HeartbeatMonitor_lastHeartbeat(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "HeartbeatMonitor", Field: field, @@ -14001,7 +14546,7 @@ func (ec *executionContext) _HeartbeatMonitor_href(ctx context.Context, field gr return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_HeartbeatMonitor_href(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_HeartbeatMonitor_href(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "HeartbeatMonitor", Field: field, @@ -14045,7 +14590,7 @@ func (ec *executionContext) _HeartbeatMonitor_additionalDetails(ctx context.Cont return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_HeartbeatMonitor_additionalDetails(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_HeartbeatMonitor_additionalDetails(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "HeartbeatMonitor", Field: field, @@ -14089,7 +14634,7 @@ func (ec *executionContext) _IntegrationKey_id(ctx context.Context, field graphq return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKey_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKey_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKey", Field: field, @@ -14133,7 +14678,7 @@ func (ec *executionContext) _IntegrationKey_serviceID(ctx context.Context, field return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKey_serviceID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKey_serviceID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKey", Field: field, @@ -14177,7 +14722,7 @@ func (ec *executionContext) _IntegrationKey_type(ctx context.Context, field grap return ec.marshalNIntegrationKeyType2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐIntegrationKeyType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKey_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKey_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKey", Field: field, @@ -14221,7 +14766,7 @@ func (ec *executionContext) _IntegrationKey_name(ctx context.Context, field grap return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKey_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKey_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKey", Field: field, @@ -14265,7 +14810,7 @@ func (ec *executionContext) _IntegrationKey_href(ctx context.Context, field grap return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKey_href(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKey_href(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKey", Field: field, @@ -14306,7 +14851,7 @@ func (ec *executionContext) _IntegrationKey_externalSystemName(ctx context.Conte return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKey_externalSystemName(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKey_externalSystemName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKey", Field: field, @@ -14374,7 +14919,7 @@ func (ec *executionContext) _IntegrationKey_config(ctx context.Context, field gr return ec.marshalNKeyConfig2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐKeyConfig(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKey_config(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKey_config(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKey", Field: field, @@ -14382,10 +14927,10 @@ func (ec *executionContext) fieldContext_IntegrationKey_config(ctx context.Conte IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "stopAtFirstRule": - return ec.fieldContext_KeyConfig_stopAtFirstRule(ctx, field) case "rules": return ec.fieldContext_KeyConfig_rules(ctx, field) + case "oneRule": + return ec.fieldContext_KeyConfig_oneRule(ctx, field) case "defaultActions": return ec.fieldContext_KeyConfig_defaultActions(ctx, field) } @@ -14395,6 +14940,80 @@ func (ec *executionContext) fieldContext_IntegrationKey_config(ctx context.Conte return fc, nil } +func (ec *executionContext) _IntegrationKey_tokenInfo(ctx context.Context, field graphql.CollectedField, obj *integrationkey.IntegrationKey) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_IntegrationKey_tokenInfo(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.IntegrationKey().TokenInfo(rctx, obj) + } + directive1 := func(ctx context.Context) (interface{}, error) { + flagName, err := ec.unmarshalNString2string(ctx, "univ-keys") + if err != nil { + return nil, err + } + if ec.directives.Experimental == nil { + return nil, errors.New("directive experimental is not implemented") + } + return ec.directives.Experimental(ctx, obj, directive0, flagName) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*TokenInfo); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *github.com/target/goalert/graphql2.TokenInfo`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*TokenInfo) + fc.Result = res + return ec.marshalNTokenInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐTokenInfo(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_IntegrationKey_tokenInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "IntegrationKey", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "primaryHint": + return ec.fieldContext_TokenInfo_primaryHint(ctx, field) + case "secondaryHint": + return ec.fieldContext_TokenInfo_secondaryHint(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type TokenInfo", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _IntegrationKeyConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *IntegrationKeyConnection) (ret graphql.Marshaler) { fc, err := ec.fieldContext_IntegrationKeyConnection_nodes(ctx, field) if err != nil { @@ -14426,7 +15045,7 @@ func (ec *executionContext) _IntegrationKeyConnection_nodes(ctx context.Context, return ec.marshalNIntegrationKey2ᚕgithubᚗcomᚋtargetᚋgoalertᚋintegrationkeyᚐIntegrationKeyᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKeyConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKeyConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKeyConnection", Field: field, @@ -14448,6 +15067,8 @@ func (ec *executionContext) fieldContext_IntegrationKeyConnection_nodes(ctx cont return ec.fieldContext_IntegrationKey_externalSystemName(ctx, field) case "config": return ec.fieldContext_IntegrationKey_config(ctx, field) + case "tokenInfo": + return ec.fieldContext_IntegrationKey_tokenInfo(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type IntegrationKey", field.Name) }, @@ -14486,7 +15107,7 @@ func (ec *executionContext) _IntegrationKeyConnection_pageInfo(ctx context.Conte return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKeyConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKeyConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKeyConnection", Field: field, @@ -14536,7 +15157,7 @@ func (ec *executionContext) _IntegrationKeyTypeInfo_id(ctx context.Context, fiel return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKeyTypeInfo_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKeyTypeInfo_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKeyTypeInfo", Field: field, @@ -14580,7 +15201,7 @@ func (ec *executionContext) _IntegrationKeyTypeInfo_name(ctx context.Context, fi return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKeyTypeInfo_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKeyTypeInfo_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKeyTypeInfo", Field: field, @@ -14624,7 +15245,7 @@ func (ec *executionContext) _IntegrationKeyTypeInfo_label(ctx context.Context, f return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKeyTypeInfo_label(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKeyTypeInfo_label(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKeyTypeInfo", Field: field, @@ -14668,7 +15289,7 @@ func (ec *executionContext) _IntegrationKeyTypeInfo_enabled(ctx context.Context, return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_IntegrationKeyTypeInfo_enabled(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_IntegrationKeyTypeInfo_enabled(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "IntegrationKeyTypeInfo", Field: field, @@ -14681,8 +15302,8 @@ func (ec *executionContext) fieldContext_IntegrationKeyTypeInfo_enabled(ctx cont return fc, nil } -func (ec *executionContext) _KeyConfig_stopAtFirstRule(ctx context.Context, field graphql.CollectedField, obj *KeyConfig) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_KeyConfig_stopAtFirstRule(ctx, field) +func (ec *executionContext) _KeyConfig_rules(ctx context.Context, field graphql.CollectedField, obj *KeyConfig) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_KeyConfig_rules(ctx, field) if err != nil { return graphql.Null } @@ -14695,7 +15316,7 @@ func (ec *executionContext) _KeyConfig_stopAtFirstRule(ctx context.Context, fiel }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.StopAtFirstRule, nil + return obj.Rules, nil }) if err != nil { ec.Error(ctx, err) @@ -14707,26 +15328,40 @@ func (ec *executionContext) _KeyConfig_stopAtFirstRule(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(bool) + res := resTmp.([]KeyRule) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNKeyRule2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐKeyRuleᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_KeyConfig_stopAtFirstRule(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_KeyConfig_rules(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "KeyConfig", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") + switch field.Name { + case "id": + return ec.fieldContext_KeyRule_id(ctx, field) + case "name": + return ec.fieldContext_KeyRule_name(ctx, field) + case "description": + return ec.fieldContext_KeyRule_description(ctx, field) + case "conditionExpr": + return ec.fieldContext_KeyRule_conditionExpr(ctx, field) + case "actions": + return ec.fieldContext_KeyRule_actions(ctx, field) + case "continueAfterMatch": + return ec.fieldContext_KeyRule_continueAfterMatch(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type KeyRule", field.Name) }, } return fc, nil } -func (ec *executionContext) _KeyConfig_rules(ctx context.Context, field graphql.CollectedField, obj *KeyConfig) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_KeyConfig_rules(ctx, field) +func (ec *executionContext) _KeyConfig_oneRule(ctx context.Context, field graphql.CollectedField, obj *KeyConfig) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_KeyConfig_oneRule(ctx, field) if err != nil { return graphql.Null } @@ -14739,29 +15374,26 @@ func (ec *executionContext) _KeyConfig_rules(ctx context.Context, field graphql. }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Rules, nil + return ec.resolvers.KeyConfig().OneRule(rctx, obj, fc.Args["id"].(string)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]KeyRule) + res := resTmp.(*KeyRule) fc.Result = res - return ec.marshalNKeyRule2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐKeyRuleᚄ(ctx, field.Selections, res) + return ec.marshalOKeyRule2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐKeyRule(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_KeyConfig_rules(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_KeyConfig_oneRule(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "KeyConfig", Field: field, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "id": @@ -14774,10 +15406,23 @@ func (ec *executionContext) fieldContext_KeyConfig_rules(ctx context.Context, fi return ec.fieldContext_KeyRule_conditionExpr(ctx, field) case "actions": return ec.fieldContext_KeyRule_actions(ctx, field) + case "continueAfterMatch": + return ec.fieldContext_KeyRule_continueAfterMatch(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type KeyRule", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_KeyConfig_oneRule_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } @@ -14812,7 +15457,7 @@ func (ec *executionContext) _KeyConfig_defaultActions(ctx context.Context, field return ec.marshalNAction2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐActionᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_KeyConfig_defaultActions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_KeyConfig_defaultActions(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "KeyConfig", Field: field, @@ -14862,7 +15507,7 @@ func (ec *executionContext) _KeyRule_id(ctx context.Context, field graphql.Colle return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_KeyRule_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_KeyRule_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "KeyRule", Field: field, @@ -14906,7 +15551,7 @@ func (ec *executionContext) _KeyRule_name(ctx context.Context, field graphql.Col return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_KeyRule_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_KeyRule_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "KeyRule", Field: field, @@ -14950,7 +15595,7 @@ func (ec *executionContext) _KeyRule_description(ctx context.Context, field grap return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_KeyRule_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_KeyRule_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "KeyRule", Field: field, @@ -14994,7 +15639,7 @@ func (ec *executionContext) _KeyRule_conditionExpr(ctx context.Context, field gr return ec.marshalNExprBooleanExpression2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_KeyRule_conditionExpr(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_KeyRule_conditionExpr(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "KeyRule", Field: field, @@ -15038,7 +15683,7 @@ func (ec *executionContext) _KeyRule_actions(ctx context.Context, field graphql. return ec.marshalNAction2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐActionᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_KeyRule_actions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_KeyRule_actions(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "KeyRule", Field: field, @@ -15057,6 +15702,50 @@ func (ec *executionContext) fieldContext_KeyRule_actions(ctx context.Context, fi return fc, nil } +func (ec *executionContext) _KeyRule_continueAfterMatch(ctx context.Context, field graphql.CollectedField, obj *KeyRule) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_KeyRule_continueAfterMatch(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ContinueAfterMatch, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_KeyRule_continueAfterMatch(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "KeyRule", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _Label_key(ctx context.Context, field graphql.CollectedField, obj *label.Label) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Label_key(ctx, field) if err != nil { @@ -15088,7 +15777,7 @@ func (ec *executionContext) _Label_key(ctx context.Context, field graphql.Collec return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Label_key(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Label_key(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Label", Field: field, @@ -15132,7 +15821,7 @@ func (ec *executionContext) _Label_value(ctx context.Context, field graphql.Coll return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Label_value(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Label_value(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Label", Field: field, @@ -15176,7 +15865,7 @@ func (ec *executionContext) _LabelConnection_nodes(ctx context.Context, field gr return ec.marshalNLabel2ᚕgithubᚗcomᚋtargetᚋgoalertᚋlabelᚐLabelᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_LabelConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_LabelConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "LabelConnection", Field: field, @@ -15226,7 +15915,7 @@ func (ec *executionContext) _LabelConnection_pageInfo(ctx context.Context, field return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_LabelConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_LabelConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "LabelConnection", Field: field, @@ -15276,7 +15965,7 @@ func (ec *executionContext) _LinkAccountInfo_userDetails(ctx context.Context, fi return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_LinkAccountInfo_userDetails(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_LinkAccountInfo_userDetails(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "LinkAccountInfo", Field: field, @@ -15317,7 +16006,7 @@ func (ec *executionContext) _LinkAccountInfo_alertID(ctx context.Context, field return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_LinkAccountInfo_alertID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_LinkAccountInfo_alertID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "LinkAccountInfo", Field: field, @@ -15358,7 +16047,7 @@ func (ec *executionContext) _LinkAccountInfo_alertNewStatus(ctx context.Context, return ec.marshalOAlertStatus2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐAlertStatus(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_LinkAccountInfo_alertNewStatus(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_LinkAccountInfo_alertNewStatus(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "LinkAccountInfo", Field: field, @@ -15402,7 +16091,7 @@ func (ec *executionContext) _MessageLogConnection_nodes(ctx context.Context, fie return ec.marshalNDebugMessage2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDebugMessageᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_MessageLogConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_MessageLogConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "MessageLogConnection", Field: field, @@ -15478,7 +16167,7 @@ func (ec *executionContext) _MessageLogConnection_pageInfo(ctx context.Context, return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_MessageLogConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_MessageLogConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "MessageLogConnection", Field: field, @@ -15528,7 +16217,7 @@ func (ec *executionContext) _MessageLogConnection_stats(ctx context.Context, fie return ec.marshalNMessageLogConnectionStats2ᚖgithubᚗcomᚋtargetᚋgoalertᚋnotificationᚐSearchOptions(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_MessageLogConnection_stats(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_MessageLogConnection_stats(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "MessageLogConnection", Field: field, @@ -16149,7 +16838,7 @@ func (ec *executionContext) _Mutation_endAllAuthSessionsByCurrentUser(ctx contex return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Mutation_endAllAuthSessionsByCurrentUser(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Mutation_endAllAuthSessionsByCurrentUser(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Mutation", Field: field, @@ -17306,6 +17995,8 @@ func (ec *executionContext) fieldContext_Mutation_createIntegrationKey(ctx conte return ec.fieldContext_IntegrationKey_externalSystemName(ctx, field) case "config": return ec.fieldContext_IntegrationKey_config(ctx, field) + case "tokenInfo": + return ec.fieldContext_IntegrationKey_tokenInfo(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type IntegrationKey", field.Name) }, @@ -17583,6 +18274,8 @@ func (ec *executionContext) fieldContext_Mutation_createUser(ctx context.Context return ec.fieldContext_User_sessions(ctx, field) case "onCallSteps": return ec.fieldContext_User_onCallSteps(ctx, field) + case "onCallOverview": + return ec.fieldContext_User_onCallOverview(ctx, field) case "isFavorite": return ec.fieldContext_User_isFavorite(ctx, field) case "assignedSchedules": @@ -18855,6 +19548,243 @@ func (ec *executionContext) fieldContext_Mutation_updateKeyConfig(ctx context.Co return fc, nil } +func (ec *executionContext) _Mutation_promoteSecondaryToken(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_promoteSecondaryToken(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().PromoteSecondaryToken(rctx, fc.Args["id"].(string)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + flagName, err := ec.unmarshalNString2string(ctx, "univ-keys") + if err != nil { + return nil, err + } + if ec.directives.Experimental == nil { + return nil, errors.New("directive experimental is not implemented") + } + return ec.directives.Experimental(ctx, nil, directive0, flagName) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(bool); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be bool`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_promoteSecondaryToken(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_promoteSecondaryToken_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_deleteSecondaryToken(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_deleteSecondaryToken(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().DeleteSecondaryToken(rctx, fc.Args["id"].(string)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + flagName, err := ec.unmarshalNString2string(ctx, "univ-keys") + if err != nil { + return nil, err + } + if ec.directives.Experimental == nil { + return nil, errors.New("directive experimental is not implemented") + } + return ec.directives.Experimental(ctx, nil, directive0, flagName) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(bool); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be bool`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_deleteSecondaryToken(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_deleteSecondaryToken_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_generateKeyToken(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_generateKeyToken(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().GenerateKeyToken(rctx, fc.Args["id"].(string)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + flagName, err := ec.unmarshalNString2string(ctx, "univ-keys") + if err != nil { + return nil, err + } + if ec.directives.Experimental == nil { + return nil, errors.New("directive experimental is not implemented") + } + return ec.directives.Experimental(ctx, nil, directive0, flagName) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_generateKeyToken(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_generateKeyToken_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Notice_type(ctx context.Context, field graphql.CollectedField, obj *notice.Notice) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Notice_type(ctx, field) if err != nil { @@ -18886,7 +19816,7 @@ func (ec *executionContext) _Notice_type(ctx context.Context, field graphql.Coll return ec.marshalNNoticeType2githubᚗcomᚋtargetᚋgoalertᚋnoticeᚐType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Notice_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Notice_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Notice", Field: field, @@ -18930,7 +19860,7 @@ func (ec *executionContext) _Notice_message(ctx context.Context, field graphql.C return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Notice_message(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Notice_message(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Notice", Field: field, @@ -18974,7 +19904,7 @@ func (ec *executionContext) _Notice_details(ctx context.Context, field graphql.C return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Notice_details(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Notice_details(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Notice", Field: field, @@ -19018,7 +19948,7 @@ func (ec *executionContext) _NotificationState_details(ctx context.Context, fiel return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_NotificationState_details(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_NotificationState_details(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "NotificationState", Field: field, @@ -19059,7 +19989,7 @@ func (ec *executionContext) _NotificationState_status(ctx context.Context, field return ec.marshalONotificationStatus2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐNotificationStatus(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_NotificationState_status(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_NotificationState_status(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "NotificationState", Field: field, @@ -19103,7 +20033,7 @@ func (ec *executionContext) _NotificationState_formattedSrcValue(ctx context.Con return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_NotificationState_formattedSrcValue(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_NotificationState_formattedSrcValue(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "NotificationState", Field: field, @@ -19147,7 +20077,7 @@ func (ec *executionContext) _OnCallNotificationRule_id(ctx context.Context, fiel return ec.marshalNID2githubᚗcomᚋtargetᚋgoalertᚋscheduleᚐRuleID(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_OnCallNotificationRule_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_OnCallNotificationRule_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "OnCallNotificationRule", Field: field, @@ -19191,7 +20121,7 @@ func (ec *executionContext) _OnCallNotificationRule_target(ctx context.Context, return ec.marshalNTarget2ᚖgithubᚗcomᚋtargetᚋgoalertᚋassignmentᚐRawTarget(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_OnCallNotificationRule_target(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_OnCallNotificationRule_target(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "OnCallNotificationRule", Field: field, @@ -19243,7 +20173,7 @@ func (ec *executionContext) _OnCallNotificationRule_dest(ctx context.Context, fi return ec.marshalNDestination2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDestination(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_OnCallNotificationRule_dest(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_OnCallNotificationRule_dest(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "OnCallNotificationRule", Field: field, @@ -19255,6 +20185,8 @@ func (ec *executionContext) fieldContext_OnCallNotificationRule_dest(ctx context return ec.fieldContext_Destination_type(ctx, field) case "values": return ec.fieldContext_Destination_values(ctx, field) + case "args": + return ec.fieldContext_Destination_args(ctx, field) case "displayInfo": return ec.fieldContext_Destination_displayInfo(ctx, field) } @@ -19292,7 +20224,7 @@ func (ec *executionContext) _OnCallNotificationRule_time(ctx context.Context, fi return ec.marshalOClockTime2ᚖgithubᚗcomᚋtargetᚋgoalertᚋutilᚋtimeutilᚐClock(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_OnCallNotificationRule_time(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_OnCallNotificationRule_time(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "OnCallNotificationRule", Field: field, @@ -19333,7 +20265,7 @@ func (ec *executionContext) _OnCallNotificationRule_weekdayFilter(ctx context.Co return ec.marshalOWeekdayFilter2ᚖgithubᚗcomᚋtargetᚋgoalertᚋutilᚋtimeutilᚐWeekdayFilter(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_OnCallNotificationRule_weekdayFilter(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_OnCallNotificationRule_weekdayFilter(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "OnCallNotificationRule", Field: field, @@ -19346,6 +20278,326 @@ func (ec *executionContext) fieldContext_OnCallNotificationRule_weekdayFilter(ct return fc, nil } +func (ec *executionContext) _OnCallOverview_serviceCount(ctx context.Context, field graphql.CollectedField, obj *OnCallOverview) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_OnCallOverview_serviceCount(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ServiceCount, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_OnCallOverview_serviceCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "OnCallOverview", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _OnCallOverview_serviceAssignments(ctx context.Context, field graphql.CollectedField, obj *OnCallOverview) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_OnCallOverview_serviceAssignments(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ServiceAssignments, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]OnCallServiceAssignment) + fc.Result = res + return ec.marshalNOnCallServiceAssignment2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐOnCallServiceAssignmentᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_OnCallOverview_serviceAssignments(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "OnCallOverview", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "stepNumber": + return ec.fieldContext_OnCallServiceAssignment_stepNumber(ctx, field) + case "escalationPolicyID": + return ec.fieldContext_OnCallServiceAssignment_escalationPolicyID(ctx, field) + case "escalationPolicyName": + return ec.fieldContext_OnCallServiceAssignment_escalationPolicyName(ctx, field) + case "serviceID": + return ec.fieldContext_OnCallServiceAssignment_serviceID(ctx, field) + case "serviceName": + return ec.fieldContext_OnCallServiceAssignment_serviceName(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type OnCallServiceAssignment", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _OnCallServiceAssignment_stepNumber(ctx context.Context, field graphql.CollectedField, obj *OnCallServiceAssignment) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_OnCallServiceAssignment_stepNumber(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.StepNumber, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_OnCallServiceAssignment_stepNumber(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "OnCallServiceAssignment", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _OnCallServiceAssignment_escalationPolicyID(ctx context.Context, field graphql.CollectedField, obj *OnCallServiceAssignment) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_OnCallServiceAssignment_escalationPolicyID(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.EscalationPolicyID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_OnCallServiceAssignment_escalationPolicyID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "OnCallServiceAssignment", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _OnCallServiceAssignment_escalationPolicyName(ctx context.Context, field graphql.CollectedField, obj *OnCallServiceAssignment) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_OnCallServiceAssignment_escalationPolicyName(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.EscalationPolicyName, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_OnCallServiceAssignment_escalationPolicyName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "OnCallServiceAssignment", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _OnCallServiceAssignment_serviceID(ctx context.Context, field graphql.CollectedField, obj *OnCallServiceAssignment) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_OnCallServiceAssignment_serviceID(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ServiceID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_OnCallServiceAssignment_serviceID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "OnCallServiceAssignment", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _OnCallServiceAssignment_serviceName(ctx context.Context, field graphql.CollectedField, obj *OnCallServiceAssignment) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_OnCallServiceAssignment_serviceName(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ServiceName, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_OnCallServiceAssignment_serviceName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "OnCallServiceAssignment", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _OnCallShift_userID(ctx context.Context, field graphql.CollectedField, obj *oncall.Shift) (ret graphql.Marshaler) { fc, err := ec.fieldContext_OnCallShift_userID(ctx, field) if err != nil { @@ -19377,7 +20629,7 @@ func (ec *executionContext) _OnCallShift_userID(ctx context.Context, field graph return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_OnCallShift_userID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_OnCallShift_userID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "OnCallShift", Field: field, @@ -19418,7 +20670,7 @@ func (ec *executionContext) _OnCallShift_user(ctx context.Context, field graphql return ec.marshalOUser2ᚖgithubᚗcomᚋtargetᚋgoalertᚋuserᚐUser(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_OnCallShift_user(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_OnCallShift_user(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "OnCallShift", Field: field, @@ -19448,6 +20700,8 @@ func (ec *executionContext) fieldContext_OnCallShift_user(ctx context.Context, f return ec.fieldContext_User_sessions(ctx, field) case "onCallSteps": return ec.fieldContext_User_onCallSteps(ctx, field) + case "onCallOverview": + return ec.fieldContext_User_onCallOverview(ctx, field) case "isFavorite": return ec.fieldContext_User_isFavorite(ctx, field) case "assignedSchedules": @@ -19490,7 +20744,7 @@ func (ec *executionContext) _OnCallShift_start(ctx context.Context, field graphq return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_OnCallShift_start(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_OnCallShift_start(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "OnCallShift", Field: field, @@ -19534,7 +20788,7 @@ func (ec *executionContext) _OnCallShift_end(ctx context.Context, field graphql. return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_OnCallShift_end(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_OnCallShift_end(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "OnCallShift", Field: field, @@ -19578,7 +20832,7 @@ func (ec *executionContext) _OnCallShift_truncated(ctx context.Context, field gr return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_OnCallShift_truncated(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_OnCallShift_truncated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "OnCallShift", Field: field, @@ -19619,7 +20873,7 @@ func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graph return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PageInfo_endCursor(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PageInfo_endCursor(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PageInfo", Field: field, @@ -19663,7 +20917,7 @@ func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field gra return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PageInfo_hasNextPage(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PageInfo_hasNextPage(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PageInfo", Field: field, @@ -19707,7 +20961,7 @@ func (ec *executionContext) _PhoneNumberInfo_id(ctx context.Context, field graph return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PhoneNumberInfo_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PhoneNumberInfo_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PhoneNumberInfo", Field: field, @@ -19751,7 +21005,7 @@ func (ec *executionContext) _PhoneNumberInfo_countryCode(ctx context.Context, fi return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PhoneNumberInfo_countryCode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PhoneNumberInfo_countryCode(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PhoneNumberInfo", Field: field, @@ -19795,7 +21049,7 @@ func (ec *executionContext) _PhoneNumberInfo_regionCode(ctx context.Context, fie return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PhoneNumberInfo_regionCode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PhoneNumberInfo_regionCode(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PhoneNumberInfo", Field: field, @@ -19839,7 +21093,7 @@ func (ec *executionContext) _PhoneNumberInfo_formatted(ctx context.Context, fiel return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PhoneNumberInfo_formatted(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PhoneNumberInfo_formatted(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PhoneNumberInfo", Field: field, @@ -19883,7 +21137,7 @@ func (ec *executionContext) _PhoneNumberInfo_valid(ctx context.Context, field gr return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PhoneNumberInfo_valid(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PhoneNumberInfo_valid(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PhoneNumberInfo", Field: field, @@ -19927,7 +21181,7 @@ func (ec *executionContext) _PhoneNumberInfo_error(ctx context.Context, field gr return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PhoneNumberInfo_error(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PhoneNumberInfo_error(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PhoneNumberInfo", Field: field, @@ -20037,7 +21291,7 @@ func (ec *executionContext) _Query_experimentalFlags(ctx context.Context, field return ec.marshalNID2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_experimentalFlags(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_experimentalFlags(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -20258,6 +21512,8 @@ func (ec *executionContext) fieldContext_Query_user(ctx context.Context, field g return ec.fieldContext_User_sessions(ctx, field) case "onCallSteps": return ec.fieldContext_User_onCallSteps(ctx, field) + case "onCallOverview": + return ec.fieldContext_User_onCallOverview(ctx, field) case "isFavorite": return ec.fieldContext_User_isFavorite(ctx, field) case "assignedSchedules": @@ -20614,6 +21870,8 @@ func (ec *executionContext) fieldContext_Query_integrationKey(ctx context.Contex return ec.fieldContext_IntegrationKey_externalSystemName(ctx, field) case "config": return ec.fieldContext_IntegrationKey_config(ctx, field) + case "tokenInfo": + return ec.fieldContext_IntegrationKey_tokenInfo(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type IntegrationKey", field.Name) }, @@ -21894,7 +23152,7 @@ func (ec *executionContext) _Query_configHints(ctx context.Context, field graphq return ec.marshalNConfigHint2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐConfigHintᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_configHints(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_configHints(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -21944,7 +23202,7 @@ func (ec *executionContext) _Query_integrationKeyTypes(ctx context.Context, fiel return ec.marshalNIntegrationKeyTypeInfo2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐIntegrationKeyTypeInfoᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_integrationKeyTypes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_integrationKeyTypes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -21998,7 +23256,7 @@ func (ec *executionContext) _Query_systemLimits(ctx context.Context, field graph return ec.marshalNSystemLimit2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐSystemLimitᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_systemLimits(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_systemLimits(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -22429,7 +23687,7 @@ func (ec *executionContext) _Query_generateSlackAppManifest(ctx context.Context, return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_generateSlackAppManifest(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_generateSlackAppManifest(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -22533,7 +23791,7 @@ func (ec *executionContext) _Query_swoStatus(ctx context.Context, field graphql. return ec.marshalNSWOStatus2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐSWOStatus(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_swoStatus(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_swoStatus(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -22574,7 +23832,7 @@ func (ec *executionContext) _Query_destinationTypes(ctx context.Context, field g }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().DestinationTypes(rctx) + return ec.resolvers.Query().DestinationTypes(rctx, fc.Args["isDynamicAction"].(*bool)) }) if err != nil { ec.Error(ctx, err) @@ -22611,6 +23869,8 @@ func (ec *executionContext) fieldContext_Query_destinationTypes(ctx context.Cont return ec.fieldContext_DestinationTypeInfo_enabled(ctx, field) case "requiredFields": return ec.fieldContext_DestinationTypeInfo_requiredFields(ctx, field) + case "dynamicParams": + return ec.fieldContext_DestinationTypeInfo_dynamicParams(ctx, field) case "userDisclaimer": return ec.fieldContext_DestinationTypeInfo_userDisclaimer(ctx, field) case "isContactMethod": @@ -22619,6 +23879,8 @@ func (ec *executionContext) fieldContext_Query_destinationTypes(ctx context.Cont return ec.fieldContext_DestinationTypeInfo_isEPTarget(ctx, field) case "isSchedOnCallNotify": return ec.fieldContext_DestinationTypeInfo_isSchedOnCallNotify(ctx, field) + case "isDynamicAction": + return ec.fieldContext_DestinationTypeInfo_isDynamicAction(ctx, field) case "supportsStatusUpdates": return ec.fieldContext_DestinationTypeInfo_supportsStatusUpdates(ctx, field) case "statusUpdatesRequired": @@ -22627,6 +23889,17 @@ func (ec *executionContext) fieldContext_Query_destinationTypes(ctx context.Cont return nil, fmt.Errorf("no field named %q was found under type DestinationTypeInfo", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_destinationTypes_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } @@ -22921,7 +24194,7 @@ func (ec *executionContext) _Query_expr(ctx context.Context, field graphql.Colle return ec.marshalNExpr2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐExpr(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_expr(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_expr(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -22971,7 +24244,7 @@ func (ec *executionContext) _Query_gqlAPIKeys(ctx context.Context, field graphql return ec.marshalNGQLAPIKey2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐGQLAPIKeyᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_gqlAPIKeys(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_gqlAPIKeys(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -23008,6 +24281,85 @@ func (ec *executionContext) fieldContext_Query_gqlAPIKeys(ctx context.Context, f return fc, nil } +func (ec *executionContext) _Query_actionInputValidate(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_actionInputValidate(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().ActionInputValidate(rctx, fc.Args["input"].(ActionInput)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + flagName, err := ec.unmarshalNString2string(ctx, "univ-keys") + if err != nil { + return nil, err + } + if ec.directives.Experimental == nil { + return nil, errors.New("directive experimental is not implemented") + } + return ec.directives.Experimental(ctx, nil, directive0, flagName) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(bool); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be bool`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_actionInputValidate(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_actionInputValidate_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query___type(ctx, field) if err != nil { @@ -23110,7 +24462,7 @@ func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.C return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query___schema(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query___schema(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -23168,7 +24520,7 @@ func (ec *executionContext) _Rotation_id(ctx context.Context, field graphql.Coll return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Rotation_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Rotation_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Rotation", Field: field, @@ -23212,7 +24564,7 @@ func (ec *executionContext) _Rotation_name(ctx context.Context, field graphql.Co return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Rotation_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Rotation_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Rotation", Field: field, @@ -23256,7 +24608,7 @@ func (ec *executionContext) _Rotation_description(ctx context.Context, field gra return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Rotation_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Rotation_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Rotation", Field: field, @@ -23300,7 +24652,7 @@ func (ec *executionContext) _Rotation_isFavorite(ctx context.Context, field grap return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Rotation_isFavorite(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Rotation_isFavorite(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Rotation", Field: field, @@ -23344,7 +24696,7 @@ func (ec *executionContext) _Rotation_start(ctx context.Context, field graphql.C return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Rotation_start(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Rotation_start(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Rotation", Field: field, @@ -23388,7 +24740,7 @@ func (ec *executionContext) _Rotation_timeZone(ctx context.Context, field graphq return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Rotation_timeZone(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Rotation_timeZone(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Rotation", Field: field, @@ -23432,7 +24784,7 @@ func (ec *executionContext) _Rotation_type(ctx context.Context, field graphql.Co return ec.marshalNRotationType2githubᚗcomᚋtargetᚋgoalertᚋscheduleᚋrotationᚐType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Rotation_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Rotation_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Rotation", Field: field, @@ -23476,7 +24828,7 @@ func (ec *executionContext) _Rotation_shiftLength(ctx context.Context, field gra return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Rotation_shiftLength(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Rotation_shiftLength(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Rotation", Field: field, @@ -23520,7 +24872,7 @@ func (ec *executionContext) _Rotation_activeUserIndex(ctx context.Context, field return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Rotation_activeUserIndex(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Rotation_activeUserIndex(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Rotation", Field: field, @@ -23564,7 +24916,7 @@ func (ec *executionContext) _Rotation_userIDs(ctx context.Context, field graphql return ec.marshalNID2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Rotation_userIDs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Rotation_userIDs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Rotation", Field: field, @@ -23608,7 +24960,7 @@ func (ec *executionContext) _Rotation_users(ctx context.Context, field graphql.C return ec.marshalNUser2ᚕgithubᚗcomᚋtargetᚋgoalertᚋuserᚐUserᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Rotation_users(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Rotation_users(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Rotation", Field: field, @@ -23638,6 +24990,8 @@ func (ec *executionContext) fieldContext_Rotation_users(ctx context.Context, fie return ec.fieldContext_User_sessions(ctx, field) case "onCallSteps": return ec.fieldContext_User_onCallSteps(ctx, field) + case "onCallOverview": + return ec.fieldContext_User_onCallOverview(ctx, field) case "isFavorite": return ec.fieldContext_User_isFavorite(ctx, field) case "assignedSchedules": @@ -23735,7 +25089,7 @@ func (ec *executionContext) _RotationConnection_nodes(ctx context.Context, field return ec.marshalNRotation2ᚕgithubᚗcomᚋtargetᚋgoalertᚋscheduleᚋrotationᚐRotationᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_RotationConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_RotationConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "RotationConnection", Field: field, @@ -23805,7 +25159,7 @@ func (ec *executionContext) _RotationConnection_pageInfo(ctx context.Context, fi return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_RotationConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_RotationConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "RotationConnection", Field: field, @@ -23855,7 +25209,7 @@ func (ec *executionContext) _SWOConnection_name(ctx context.Context, field graph return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWOConnection_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWOConnection_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWOConnection", Field: field, @@ -23899,7 +25253,7 @@ func (ec *executionContext) _SWOConnection_version(ctx context.Context, field gr return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWOConnection_version(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWOConnection_version(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWOConnection", Field: field, @@ -23943,7 +25297,7 @@ func (ec *executionContext) _SWOConnection_type(ctx context.Context, field graph return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWOConnection_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWOConnection_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWOConnection", Field: field, @@ -23987,7 +25341,7 @@ func (ec *executionContext) _SWOConnection_isNext(ctx context.Context, field gra return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWOConnection_isNext(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWOConnection_isNext(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWOConnection", Field: field, @@ -24031,7 +25385,7 @@ func (ec *executionContext) _SWOConnection_count(ctx context.Context, field grap return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWOConnection_count(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWOConnection_count(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWOConnection", Field: field, @@ -24075,7 +25429,7 @@ func (ec *executionContext) _SWONode_id(ctx context.Context, field graphql.Colle return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWONode_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWONode_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWONode", Field: field, @@ -24119,7 +25473,7 @@ func (ec *executionContext) _SWONode_canExec(ctx context.Context, field graphql. return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWONode_canExec(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWONode_canExec(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWONode", Field: field, @@ -24163,7 +25517,7 @@ func (ec *executionContext) _SWONode_isLeader(ctx context.Context, field graphql return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWONode_isLeader(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWONode_isLeader(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWONode", Field: field, @@ -24207,7 +25561,7 @@ func (ec *executionContext) _SWONode_uptime(ctx context.Context, field graphql.C return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWONode_uptime(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWONode_uptime(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWONode", Field: field, @@ -24251,7 +25605,7 @@ func (ec *executionContext) _SWONode_configError(ctx context.Context, field grap return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWONode_configError(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWONode_configError(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWONode", Field: field, @@ -24292,7 +25646,7 @@ func (ec *executionContext) _SWONode_connections(ctx context.Context, field grap return ec.marshalOSWOConnection2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐSWOConnectionᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWONode_connections(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWONode_connections(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWONode", Field: field, @@ -24348,7 +25702,7 @@ func (ec *executionContext) _SWOStatus_state(ctx context.Context, field graphql. return ec.marshalNSWOState2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐSWOState(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWOStatus_state(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWOStatus_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWOStatus", Field: field, @@ -24392,7 +25746,7 @@ func (ec *executionContext) _SWOStatus_lastStatus(ctx context.Context, field gra return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWOStatus_lastStatus(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWOStatus_lastStatus(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWOStatus", Field: field, @@ -24436,7 +25790,7 @@ func (ec *executionContext) _SWOStatus_lastError(ctx context.Context, field grap return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWOStatus_lastError(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWOStatus_lastError(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWOStatus", Field: field, @@ -24480,7 +25834,7 @@ func (ec *executionContext) _SWOStatus_nodes(ctx context.Context, field graphql. return ec.marshalNSWONode2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐSWONodeᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWOStatus_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWOStatus_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWOStatus", Field: field, @@ -24538,7 +25892,7 @@ func (ec *executionContext) _SWOStatus_mainDBVersion(ctx context.Context, field return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWOStatus_mainDBVersion(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWOStatus_mainDBVersion(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWOStatus", Field: field, @@ -24582,7 +25936,7 @@ func (ec *executionContext) _SWOStatus_nextDBVersion(ctx context.Context, field return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SWOStatus_nextDBVersion(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SWOStatus_nextDBVersion(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SWOStatus", Field: field, @@ -24626,7 +25980,7 @@ func (ec *executionContext) _Schedule_id(ctx context.Context, field graphql.Coll return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Schedule_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Schedule_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Schedule", Field: field, @@ -24670,7 +26024,7 @@ func (ec *executionContext) _Schedule_name(ctx context.Context, field graphql.Co return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Schedule_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Schedule_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Schedule", Field: field, @@ -24714,7 +26068,7 @@ func (ec *executionContext) _Schedule_description(ctx context.Context, field gra return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Schedule_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Schedule_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Schedule", Field: field, @@ -24758,7 +26112,7 @@ func (ec *executionContext) _Schedule_timeZone(ctx context.Context, field graphq return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Schedule_timeZone(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Schedule_timeZone(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Schedule", Field: field, @@ -24802,7 +26156,7 @@ func (ec *executionContext) _Schedule_assignedTo(ctx context.Context, field grap return ec.marshalNTarget2ᚕgithubᚗcomᚋtargetᚋgoalertᚋassignmentᚐRawTargetᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Schedule_assignedTo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Schedule_assignedTo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Schedule", Field: field, @@ -24921,7 +26275,7 @@ func (ec *executionContext) _Schedule_targets(ctx context.Context, field graphql return ec.marshalNScheduleTarget2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐScheduleTargetᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Schedule_targets(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Schedule_targets(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Schedule", Field: field, @@ -25033,7 +26387,7 @@ func (ec *executionContext) _Schedule_isFavorite(ctx context.Context, field grap return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Schedule_isFavorite(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Schedule_isFavorite(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Schedule", Field: field, @@ -25077,7 +26431,7 @@ func (ec *executionContext) _Schedule_temporarySchedules(ctx context.Context, fi return ec.marshalNTemporarySchedule2ᚕgithubᚗcomᚋtargetᚋgoalertᚋscheduleᚐTemporaryScheduleᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Schedule_temporarySchedules(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Schedule_temporarySchedules(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Schedule", Field: field, @@ -25129,7 +26483,7 @@ func (ec *executionContext) _Schedule_onCallNotificationRules(ctx context.Contex return ec.marshalNOnCallNotificationRule2ᚕgithubᚗcomᚋtargetᚋgoalertᚋscheduleᚐOnCallNotificationRuleᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Schedule_onCallNotificationRules(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Schedule_onCallNotificationRules(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Schedule", Field: field, @@ -25185,7 +26539,7 @@ func (ec *executionContext) _ScheduleConnection_nodes(ctx context.Context, field return ec.marshalNSchedule2ᚕgithubᚗcomᚋtargetᚋgoalertᚋscheduleᚐScheduleᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ScheduleConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ScheduleConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ScheduleConnection", Field: field, @@ -25253,7 +26607,7 @@ func (ec *executionContext) _ScheduleConnection_pageInfo(ctx context.Context, fi return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ScheduleConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ScheduleConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ScheduleConnection", Field: field, @@ -25303,7 +26657,7 @@ func (ec *executionContext) _ScheduleRule_id(ctx context.Context, field graphql. return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ScheduleRule_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ScheduleRule_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ScheduleRule", Field: field, @@ -25347,7 +26701,7 @@ func (ec *executionContext) _ScheduleRule_scheduleID(ctx context.Context, field return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ScheduleRule_scheduleID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ScheduleRule_scheduleID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ScheduleRule", Field: field, @@ -25391,7 +26745,7 @@ func (ec *executionContext) _ScheduleRule_start(ctx context.Context, field graph return ec.marshalNClockTime2githubᚗcomᚋtargetᚋgoalertᚋutilᚋtimeutilᚐClock(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ScheduleRule_start(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ScheduleRule_start(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ScheduleRule", Field: field, @@ -25435,7 +26789,7 @@ func (ec *executionContext) _ScheduleRule_end(ctx context.Context, field graphql return ec.marshalNClockTime2githubᚗcomᚋtargetᚋgoalertᚋutilᚋtimeutilᚐClock(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ScheduleRule_end(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ScheduleRule_end(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ScheduleRule", Field: field, @@ -25479,7 +26833,7 @@ func (ec *executionContext) _ScheduleRule_weekdayFilter(ctx context.Context, fie return ec.marshalNWeekdayFilter2githubᚗcomᚋtargetᚋgoalertᚋutilᚋtimeutilᚐWeekdayFilter(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ScheduleRule_weekdayFilter(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ScheduleRule_weekdayFilter(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ScheduleRule", Field: field, @@ -25523,7 +26877,7 @@ func (ec *executionContext) _ScheduleRule_target(ctx context.Context, field grap return ec.marshalNTarget2ᚖgithubᚗcomᚋtargetᚋgoalertᚋassignmentᚐRawTarget(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ScheduleRule_target(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ScheduleRule_target(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ScheduleRule", Field: field, @@ -25575,7 +26929,7 @@ func (ec *executionContext) _ScheduleTarget_scheduleID(ctx context.Context, fiel return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ScheduleTarget_scheduleID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ScheduleTarget_scheduleID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ScheduleTarget", Field: field, @@ -25619,7 +26973,7 @@ func (ec *executionContext) _ScheduleTarget_target(ctx context.Context, field gr return ec.marshalNTarget2ᚖgithubᚗcomᚋtargetᚋgoalertᚋassignmentᚐRawTarget(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ScheduleTarget_target(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ScheduleTarget_target(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ScheduleTarget", Field: field, @@ -25671,7 +27025,7 @@ func (ec *executionContext) _ScheduleTarget_rules(ctx context.Context, field gra return ec.marshalNScheduleRule2ᚕgithubᚗcomᚋtargetᚋgoalertᚋscheduleᚋruleᚐRuleᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ScheduleTarget_rules(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ScheduleTarget_rules(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ScheduleTarget", Field: field, @@ -25729,7 +27083,7 @@ func (ec *executionContext) _Service_id(ctx context.Context, field graphql.Colle return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -25773,7 +27127,7 @@ func (ec *executionContext) _Service_name(ctx context.Context, field graphql.Col return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -25817,7 +27171,7 @@ func (ec *executionContext) _Service_description(ctx context.Context, field grap return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -25861,7 +27215,7 @@ func (ec *executionContext) _Service_escalationPolicyID(ctx context.Context, fie return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_escalationPolicyID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_escalationPolicyID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -25902,7 +27256,7 @@ func (ec *executionContext) _Service_escalationPolicy(ctx context.Context, field return ec.marshalOEscalationPolicy2ᚖgithubᚗcomᚋtargetᚋgoalertᚋescalationᚐPolicy(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_escalationPolicy(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_escalationPolicy(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -25964,7 +27318,7 @@ func (ec *executionContext) _Service_isFavorite(ctx context.Context, field graph return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_isFavorite(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_isFavorite(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -26005,7 +27359,7 @@ func (ec *executionContext) _Service_maintenanceExpiresAt(ctx context.Context, f return ec.marshalOISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_maintenanceExpiresAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_maintenanceExpiresAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -26049,7 +27403,7 @@ func (ec *executionContext) _Service_onCallUsers(ctx context.Context, field grap return ec.marshalNServiceOnCallUser2ᚕgithubᚗcomᚋtargetᚋgoalertᚋoncallᚐServiceOnCallUserᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_onCallUsers(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_onCallUsers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -26101,7 +27455,7 @@ func (ec *executionContext) _Service_integrationKeys(ctx context.Context, field return ec.marshalNIntegrationKey2ᚕgithubᚗcomᚋtargetᚋgoalertᚋintegrationkeyᚐIntegrationKeyᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_integrationKeys(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_integrationKeys(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -26123,6 +27477,8 @@ func (ec *executionContext) fieldContext_Service_integrationKeys(ctx context.Con return ec.fieldContext_IntegrationKey_externalSystemName(ctx, field) case "config": return ec.fieldContext_IntegrationKey_config(ctx, field) + case "tokenInfo": + return ec.fieldContext_IntegrationKey_tokenInfo(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type IntegrationKey", field.Name) }, @@ -26161,7 +27517,7 @@ func (ec *executionContext) _Service_labels(ctx context.Context, field graphql.C return ec.marshalNLabel2ᚕgithubᚗcomᚋtargetᚋgoalertᚋlabelᚐLabelᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_labels(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_labels(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -26211,7 +27567,7 @@ func (ec *executionContext) _Service_heartbeatMonitors(ctx context.Context, fiel return ec.marshalNHeartbeatMonitor2ᚕgithubᚗcomᚋtargetᚋgoalertᚋheartbeatᚐMonitorᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_heartbeatMonitors(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_heartbeatMonitors(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -26273,7 +27629,7 @@ func (ec *executionContext) _Service_notices(ctx context.Context, field graphql. return ec.marshalNNotice2ᚕgithubᚗcomᚋtargetᚋgoalertᚋnoticeᚐNoticeᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Service_notices(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Service_notices(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Service", Field: field, @@ -26325,7 +27681,7 @@ func (ec *executionContext) _ServiceConnection_nodes(ctx context.Context, field return ec.marshalNService2ᚕgithubᚗcomᚋtargetᚋgoalertᚋserviceᚐServiceᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ServiceConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ServiceConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ServiceConnection", Field: field, @@ -26395,7 +27751,7 @@ func (ec *executionContext) _ServiceConnection_pageInfo(ctx context.Context, fie return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ServiceConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ServiceConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ServiceConnection", Field: field, @@ -26445,7 +27801,7 @@ func (ec *executionContext) _ServiceOnCallUser_userID(ctx context.Context, field return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ServiceOnCallUser_userID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ServiceOnCallUser_userID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ServiceOnCallUser", Field: field, @@ -26489,7 +27845,7 @@ func (ec *executionContext) _ServiceOnCallUser_userName(ctx context.Context, fie return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ServiceOnCallUser_userName(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ServiceOnCallUser_userName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ServiceOnCallUser", Field: field, @@ -26533,7 +27889,7 @@ func (ec *executionContext) _ServiceOnCallUser_stepNumber(ctx context.Context, f return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ServiceOnCallUser_stepNumber(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ServiceOnCallUser_stepNumber(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ServiceOnCallUser", Field: field, @@ -26577,7 +27933,7 @@ func (ec *executionContext) _SlackChannel_id(ctx context.Context, field graphql. return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SlackChannel_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SlackChannel_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SlackChannel", Field: field, @@ -26621,7 +27977,7 @@ func (ec *executionContext) _SlackChannel_name(ctx context.Context, field graphq return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SlackChannel_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SlackChannel_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SlackChannel", Field: field, @@ -26665,7 +28021,7 @@ func (ec *executionContext) _SlackChannel_teamID(ctx context.Context, field grap return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SlackChannel_teamID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SlackChannel_teamID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SlackChannel", Field: field, @@ -26709,7 +28065,7 @@ func (ec *executionContext) _SlackChannelConnection_nodes(ctx context.Context, f return ec.marshalNSlackChannel2ᚕgithubᚗcomᚋtargetᚋgoalertᚋnotificationᚋslackᚐChannelᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SlackChannelConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SlackChannelConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SlackChannelConnection", Field: field, @@ -26761,7 +28117,7 @@ func (ec *executionContext) _SlackChannelConnection_pageInfo(ctx context.Context return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SlackChannelConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SlackChannelConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SlackChannelConnection", Field: field, @@ -26811,7 +28167,7 @@ func (ec *executionContext) _SlackUserGroup_id(ctx context.Context, field graphq return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SlackUserGroup_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SlackUserGroup_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SlackUserGroup", Field: field, @@ -26855,7 +28211,7 @@ func (ec *executionContext) _SlackUserGroup_name(ctx context.Context, field grap return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SlackUserGroup_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SlackUserGroup_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SlackUserGroup", Field: field, @@ -26899,7 +28255,7 @@ func (ec *executionContext) _SlackUserGroup_handle(ctx context.Context, field gr return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SlackUserGroup_handle(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SlackUserGroup_handle(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SlackUserGroup", Field: field, @@ -26943,7 +28299,7 @@ func (ec *executionContext) _SlackUserGroupConnection_nodes(ctx context.Context, return ec.marshalNSlackUserGroup2ᚕgithubᚗcomᚋtargetᚋgoalertᚋnotificationᚋslackᚐUserGroupᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SlackUserGroupConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SlackUserGroupConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SlackUserGroupConnection", Field: field, @@ -26995,7 +28351,7 @@ func (ec *executionContext) _SlackUserGroupConnection_pageInfo(ctx context.Conte return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SlackUserGroupConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SlackUserGroupConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SlackUserGroupConnection", Field: field, @@ -27045,7 +28401,7 @@ func (ec *executionContext) _StringConnection_nodes(ctx context.Context, field g return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_StringConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_StringConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "StringConnection", Field: field, @@ -27089,7 +28445,7 @@ func (ec *executionContext) _StringConnection_pageInfo(ctx context.Context, fiel return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_StringConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_StringConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "StringConnection", Field: field, @@ -27139,7 +28495,7 @@ func (ec *executionContext) _SystemLimit_id(ctx context.Context, field graphql.C return ec.marshalNSystemLimitID2githubᚗcomᚋtargetᚋgoalertᚋlimitᚐID(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SystemLimit_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SystemLimit_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SystemLimit", Field: field, @@ -27183,7 +28539,7 @@ func (ec *executionContext) _SystemLimit_description(ctx context.Context, field return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SystemLimit_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SystemLimit_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SystemLimit", Field: field, @@ -27227,7 +28583,7 @@ func (ec *executionContext) _SystemLimit_value(ctx context.Context, field graphq return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_SystemLimit_value(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_SystemLimit_value(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "SystemLimit", Field: field, @@ -27271,7 +28627,7 @@ func (ec *executionContext) _Target_id(ctx context.Context, field graphql.Collec return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Target_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Target_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Target", Field: field, @@ -27315,7 +28671,7 @@ func (ec *executionContext) _Target_type(ctx context.Context, field graphql.Coll return ec.marshalNTargetType2githubᚗcomᚋtargetᚋgoalertᚋassignmentᚐTargetType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Target_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Target_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Target", Field: field, @@ -27359,7 +28715,7 @@ func (ec *executionContext) _Target_name(ctx context.Context, field graphql.Coll return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Target_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Target_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Target", Field: field, @@ -27403,7 +28759,7 @@ func (ec *executionContext) _TemporarySchedule_start(ctx context.Context, field return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_TemporarySchedule_start(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TemporarySchedule_start(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TemporarySchedule", Field: field, @@ -27447,7 +28803,7 @@ func (ec *executionContext) _TemporarySchedule_end(ctx context.Context, field gr return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_TemporarySchedule_end(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TemporarySchedule_end(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TemporarySchedule", Field: field, @@ -27491,7 +28847,7 @@ func (ec *executionContext) _TemporarySchedule_shifts(ctx context.Context, field return ec.marshalNOnCallShift2ᚕgithubᚗcomᚋtargetᚋgoalertᚋoncallᚐShiftᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_TemporarySchedule_shifts(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TemporarySchedule_shifts(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TemporarySchedule", Field: field, @@ -27547,7 +28903,7 @@ func (ec *executionContext) _TimeSeriesBucket_start(ctx context.Context, field g return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_TimeSeriesBucket_start(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TimeSeriesBucket_start(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TimeSeriesBucket", Field: field, @@ -27591,7 +28947,7 @@ func (ec *executionContext) _TimeSeriesBucket_end(ctx context.Context, field gra return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_TimeSeriesBucket_end(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TimeSeriesBucket_end(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TimeSeriesBucket", Field: field, @@ -27635,7 +28991,7 @@ func (ec *executionContext) _TimeSeriesBucket_count(ctx context.Context, field g return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_TimeSeriesBucket_count(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TimeSeriesBucket_count(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TimeSeriesBucket", Field: field, @@ -27679,7 +29035,7 @@ func (ec *executionContext) _TimeZone_id(ctx context.Context, field graphql.Coll return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_TimeZone_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TimeZone_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TimeZone", Field: field, @@ -27723,7 +29079,7 @@ func (ec *executionContext) _TimeZoneConnection_nodes(ctx context.Context, field return ec.marshalNTimeZone2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐTimeZoneᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_TimeZoneConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TimeZoneConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TimeZoneConnection", Field: field, @@ -27771,7 +29127,7 @@ func (ec *executionContext) _TimeZoneConnection_pageInfo(ctx context.Context, fi return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_TimeZoneConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TimeZoneConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "TimeZoneConnection", Field: field, @@ -27790,6 +29146,94 @@ func (ec *executionContext) fieldContext_TimeZoneConnection_pageInfo(ctx context return fc, nil } +func (ec *executionContext) _TokenInfo_primaryHint(ctx context.Context, field graphql.CollectedField, obj *TokenInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TokenInfo_primaryHint(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PrimaryHint, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TokenInfo_primaryHint(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TokenInfo", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _TokenInfo_secondaryHint(ctx context.Context, field graphql.CollectedField, obj *TokenInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TokenInfo_secondaryHint(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SecondaryHint, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TokenInfo_secondaryHint(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TokenInfo", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *user.User) (ret graphql.Marshaler) { fc, err := ec.fieldContext_User_id(ctx, field) if err != nil { @@ -27821,7 +29265,7 @@ func (ec *executionContext) _User_id(ctx context.Context, field graphql.Collecte return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -27865,7 +29309,7 @@ func (ec *executionContext) _User_role(ctx context.Context, field graphql.Collec return ec.marshalNUserRole2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐUserRole(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_role(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_role(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -27909,7 +29353,7 @@ func (ec *executionContext) _User_name(ctx context.Context, field graphql.Collec return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -27953,7 +29397,7 @@ func (ec *executionContext) _User_email(ctx context.Context, field graphql.Colle return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_email(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_email(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -27997,7 +29441,7 @@ func (ec *executionContext) _User_contactMethods(ctx context.Context, field grap return ec.marshalNUserContactMethod2ᚕgithubᚗcomᚋtargetᚋgoalertᚋuserᚋcontactmethodᚐContactMethodᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_contactMethods(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_contactMethods(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -28067,7 +29511,7 @@ func (ec *executionContext) _User_notificationRules(ctx context.Context, field g return ec.marshalNUserNotificationRule2ᚕgithubᚗcomᚋtargetᚋgoalertᚋuserᚋnotificationruleᚐNotificationRuleᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_notificationRules(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_notificationRules(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -28121,7 +29565,7 @@ func (ec *executionContext) _User_calendarSubscriptions(ctx context.Context, fie return ec.marshalNUserCalendarSubscription2ᚕgithubᚗcomᚋtargetᚋgoalertᚋcalsubᚐSubscriptionᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_calendarSubscriptions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_calendarSubscriptions(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -28185,7 +29629,7 @@ func (ec *executionContext) _User_statusUpdateContactMethodID(ctx context.Contex return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_statusUpdateContactMethodID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_statusUpdateContactMethodID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -28229,7 +29673,7 @@ func (ec *executionContext) _User_authSubjects(ctx context.Context, field graphq return ec.marshalNAuthSubject2ᚕgithubᚗcomᚋtargetᚋgoalertᚋuserᚐAuthSubjectᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_authSubjects(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_authSubjects(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -28281,7 +29725,7 @@ func (ec *executionContext) _User_sessions(ctx context.Context, field graphql.Co return ec.marshalNUserSession2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐUserSessionᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_sessions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_sessions(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -28337,7 +29781,7 @@ func (ec *executionContext) _User_onCallSteps(ctx context.Context, field graphql return ec.marshalNEscalationPolicyStep2ᚕgithubᚗcomᚋtargetᚋgoalertᚋescalationᚐStepᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_onCallSteps(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_onCallSteps(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -28364,6 +29808,56 @@ func (ec *executionContext) fieldContext_User_onCallSteps(ctx context.Context, f return fc, nil } +func (ec *executionContext) _User_onCallOverview(ctx context.Context, field graphql.CollectedField, obj *user.User) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_User_onCallOverview(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.User().OnCallOverview(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*OnCallOverview) + fc.Result = res + return ec.marshalNOnCallOverview2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐOnCallOverview(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_User_onCallOverview(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "User", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "serviceCount": + return ec.fieldContext_OnCallOverview_serviceCount(ctx, field) + case "serviceAssignments": + return ec.fieldContext_OnCallOverview_serviceAssignments(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type OnCallOverview", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _User_isFavorite(ctx context.Context, field graphql.CollectedField, obj *user.User) (ret graphql.Marshaler) { fc, err := ec.fieldContext_User_isFavorite(ctx, field) if err != nil { @@ -28395,7 +29889,7 @@ func (ec *executionContext) _User_isFavorite(ctx context.Context, field graphql. return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_isFavorite(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_isFavorite(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -28439,7 +29933,7 @@ func (ec *executionContext) _User_assignedSchedules(ctx context.Context, field g return ec.marshalNSchedule2ᚕgithubᚗcomᚋtargetᚋgoalertᚋscheduleᚐScheduleᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_User_assignedSchedules(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_User_assignedSchedules(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "User", Field: field, @@ -28507,7 +30001,7 @@ func (ec *executionContext) _UserCalendarSubscription_id(ctx context.Context, fi return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserCalendarSubscription_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserCalendarSubscription_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserCalendarSubscription", Field: field, @@ -28551,7 +30045,7 @@ func (ec *executionContext) _UserCalendarSubscription_name(ctx context.Context, return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserCalendarSubscription_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserCalendarSubscription_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserCalendarSubscription", Field: field, @@ -28595,7 +30089,7 @@ func (ec *executionContext) _UserCalendarSubscription_reminderMinutes(ctx contex return ec.marshalNInt2ᚕintᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserCalendarSubscription_reminderMinutes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserCalendarSubscription_reminderMinutes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserCalendarSubscription", Field: field, @@ -28639,7 +30133,7 @@ func (ec *executionContext) _UserCalendarSubscription_fullSchedule(ctx context.C return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserCalendarSubscription_fullSchedule(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserCalendarSubscription_fullSchedule(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserCalendarSubscription", Field: field, @@ -28683,7 +30177,7 @@ func (ec *executionContext) _UserCalendarSubscription_scheduleID(ctx context.Con return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserCalendarSubscription_scheduleID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserCalendarSubscription_scheduleID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserCalendarSubscription", Field: field, @@ -28724,7 +30218,7 @@ func (ec *executionContext) _UserCalendarSubscription_schedule(ctx context.Conte return ec.marshalOSchedule2ᚖgithubᚗcomᚋtargetᚋgoalertᚋscheduleᚐSchedule(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserCalendarSubscription_schedule(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserCalendarSubscription_schedule(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserCalendarSubscription", Field: field, @@ -28792,7 +30286,7 @@ func (ec *executionContext) _UserCalendarSubscription_lastAccess(ctx context.Con return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserCalendarSubscription_lastAccess(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserCalendarSubscription_lastAccess(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserCalendarSubscription", Field: field, @@ -28836,7 +30330,7 @@ func (ec *executionContext) _UserCalendarSubscription_disabled(ctx context.Conte return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserCalendarSubscription_disabled(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserCalendarSubscription_disabled(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserCalendarSubscription", Field: field, @@ -28877,7 +30371,7 @@ func (ec *executionContext) _UserCalendarSubscription_url(ctx context.Context, f return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserCalendarSubscription_url(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserCalendarSubscription_url(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserCalendarSubscription", Field: field, @@ -28921,7 +30415,7 @@ func (ec *executionContext) _UserConnection_nodes(ctx context.Context, field gra return ec.marshalNUser2ᚕgithubᚗcomᚋtargetᚋgoalertᚋuserᚐUserᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserConnection", Field: field, @@ -28951,6 +30445,8 @@ func (ec *executionContext) fieldContext_UserConnection_nodes(ctx context.Contex return ec.fieldContext_User_sessions(ctx, field) case "onCallSteps": return ec.fieldContext_User_onCallSteps(ctx, field) + case "onCallOverview": + return ec.fieldContext_User_onCallOverview(ctx, field) case "isFavorite": return ec.fieldContext_User_isFavorite(ctx, field) case "assignedSchedules": @@ -28993,7 +30489,7 @@ func (ec *executionContext) _UserConnection_pageInfo(ctx context.Context, field return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserConnection", Field: field, @@ -29043,7 +30539,7 @@ func (ec *executionContext) _UserContactMethod_id(ctx context.Context, field gra return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29084,7 +30580,7 @@ func (ec *executionContext) _UserContactMethod_type(ctx context.Context, field g return ec.marshalOContactMethodType2githubᚗcomᚋtargetᚋgoalertᚋuserᚋcontactmethodᚐType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29128,7 +30624,7 @@ func (ec *executionContext) _UserContactMethod_dest(ctx context.Context, field g return ec.marshalNDestination2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDestination(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_dest(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_dest(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29140,6 +30636,8 @@ func (ec *executionContext) fieldContext_UserContactMethod_dest(ctx context.Cont return ec.fieldContext_Destination_type(ctx, field) case "values": return ec.fieldContext_Destination_values(ctx, field) + case "args": + return ec.fieldContext_Destination_args(ctx, field) case "displayInfo": return ec.fieldContext_Destination_displayInfo(ctx, field) } @@ -29180,7 +30678,7 @@ func (ec *executionContext) _UserContactMethod_name(ctx context.Context, field g return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29224,7 +30722,7 @@ func (ec *executionContext) _UserContactMethod_value(ctx context.Context, field return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_value(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_value(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29268,7 +30766,7 @@ func (ec *executionContext) _UserContactMethod_formattedValue(ctx context.Contex return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_formattedValue(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_formattedValue(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29312,7 +30810,7 @@ func (ec *executionContext) _UserContactMethod_disabled(ctx context.Context, fie return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_disabled(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_disabled(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29356,7 +30854,7 @@ func (ec *executionContext) _UserContactMethod_pending(ctx context.Context, fiel return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_pending(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_pending(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29397,7 +30895,7 @@ func (ec *executionContext) _UserContactMethod_lastTestVerifyAt(ctx context.Cont return ec.marshalOISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_lastTestVerifyAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_lastTestVerifyAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29438,7 +30936,7 @@ func (ec *executionContext) _UserContactMethod_lastTestMessageState(ctx context. return ec.marshalONotificationState2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐNotificationState(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_lastTestMessageState(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_lastTestMessageState(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29487,7 +30985,7 @@ func (ec *executionContext) _UserContactMethod_lastVerifyMessageState(ctx contex return ec.marshalONotificationState2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐNotificationState(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_lastVerifyMessageState(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_lastVerifyMessageState(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29539,7 +31037,7 @@ func (ec *executionContext) _UserContactMethod_statusUpdates(ctx context.Context return ec.marshalNStatusUpdateState2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐStatusUpdateState(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserContactMethod_statusUpdates(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserContactMethod_statusUpdates(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserContactMethod", Field: field, @@ -29583,7 +31081,7 @@ func (ec *executionContext) _UserNotificationRule_id(ctx context.Context, field return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserNotificationRule_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserNotificationRule_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserNotificationRule", Field: field, @@ -29627,7 +31125,7 @@ func (ec *executionContext) _UserNotificationRule_delayMinutes(ctx context.Conte return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserNotificationRule_delayMinutes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserNotificationRule_delayMinutes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserNotificationRule", Field: field, @@ -29671,7 +31169,7 @@ func (ec *executionContext) _UserNotificationRule_contactMethodID(ctx context.Co return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserNotificationRule_contactMethodID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserNotificationRule_contactMethodID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserNotificationRule", Field: field, @@ -29712,7 +31210,7 @@ func (ec *executionContext) _UserNotificationRule_contactMethod(ctx context.Cont return ec.marshalOUserContactMethod2ᚖgithubᚗcomᚋtargetᚋgoalertᚋuserᚋcontactmethodᚐContactMethod(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserNotificationRule_contactMethod(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserNotificationRule_contactMethod(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserNotificationRule", Field: field, @@ -29782,7 +31280,7 @@ func (ec *executionContext) _UserOverride_id(ctx context.Context, field graphql. return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserOverride_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserOverride_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserOverride", Field: field, @@ -29826,7 +31324,7 @@ func (ec *executionContext) _UserOverride_start(ctx context.Context, field graph return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserOverride_start(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserOverride_start(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserOverride", Field: field, @@ -29870,7 +31368,7 @@ func (ec *executionContext) _UserOverride_end(ctx context.Context, field graphql return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserOverride_end(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserOverride_end(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserOverride", Field: field, @@ -29914,7 +31412,7 @@ func (ec *executionContext) _UserOverride_addUserID(ctx context.Context, field g return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserOverride_addUserID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserOverride_addUserID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserOverride", Field: field, @@ -29958,7 +31456,7 @@ func (ec *executionContext) _UserOverride_removeUserID(ctx context.Context, fiel return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserOverride_removeUserID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserOverride_removeUserID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserOverride", Field: field, @@ -29999,7 +31497,7 @@ func (ec *executionContext) _UserOverride_addUser(ctx context.Context, field gra return ec.marshalOUser2ᚖgithubᚗcomᚋtargetᚋgoalertᚋuserᚐUser(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserOverride_addUser(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserOverride_addUser(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserOverride", Field: field, @@ -30029,6 +31527,8 @@ func (ec *executionContext) fieldContext_UserOverride_addUser(ctx context.Contex return ec.fieldContext_User_sessions(ctx, field) case "onCallSteps": return ec.fieldContext_User_onCallSteps(ctx, field) + case "onCallOverview": + return ec.fieldContext_User_onCallOverview(ctx, field) case "isFavorite": return ec.fieldContext_User_isFavorite(ctx, field) case "assignedSchedules": @@ -30068,7 +31568,7 @@ func (ec *executionContext) _UserOverride_removeUser(ctx context.Context, field return ec.marshalOUser2ᚖgithubᚗcomᚋtargetᚋgoalertᚋuserᚐUser(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserOverride_removeUser(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserOverride_removeUser(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserOverride", Field: field, @@ -30098,6 +31598,8 @@ func (ec *executionContext) fieldContext_UserOverride_removeUser(ctx context.Con return ec.fieldContext_User_sessions(ctx, field) case "onCallSteps": return ec.fieldContext_User_onCallSteps(ctx, field) + case "onCallOverview": + return ec.fieldContext_User_onCallOverview(ctx, field) case "isFavorite": return ec.fieldContext_User_isFavorite(ctx, field) case "assignedSchedules": @@ -30140,7 +31642,7 @@ func (ec *executionContext) _UserOverride_target(ctx context.Context, field grap return ec.marshalNTarget2ᚖgithubᚗcomᚋtargetᚋgoalertᚋassignmentᚐRawTarget(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserOverride_target(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserOverride_target(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserOverride", Field: field, @@ -30192,7 +31694,7 @@ func (ec *executionContext) _UserOverrideConnection_nodes(ctx context.Context, f return ec.marshalNUserOverride2ᚕgithubᚗcomᚋtargetᚋgoalertᚋoverrideᚐUserOverrideᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserOverrideConnection_nodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserOverrideConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserOverrideConnection", Field: field, @@ -30254,7 +31756,7 @@ func (ec *executionContext) _UserOverrideConnection_pageInfo(ctx context.Context return ec.marshalNPageInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserOverrideConnection_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserOverrideConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserOverrideConnection", Field: field, @@ -30304,7 +31806,7 @@ func (ec *executionContext) _UserSession_id(ctx context.Context, field graphql.C return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserSession_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserSession_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserSession", Field: field, @@ -30348,7 +31850,7 @@ func (ec *executionContext) _UserSession_current(ctx context.Context, field grap return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserSession_current(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserSession_current(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserSession", Field: field, @@ -30392,7 +31894,7 @@ func (ec *executionContext) _UserSession_userAgent(ctx context.Context, field gr return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserSession_userAgent(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserSession_userAgent(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserSession", Field: field, @@ -30436,7 +31938,7 @@ func (ec *executionContext) _UserSession_createdAt(ctx context.Context, field gr return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserSession_createdAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserSession_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserSession", Field: field, @@ -30480,7 +31982,7 @@ func (ec *executionContext) _UserSession_lastAccessAt(ctx context.Context, field return ec.marshalNISOTimestamp2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserSession_lastAccessAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_UserSession_lastAccessAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "UserSession", Field: field, @@ -30524,7 +32026,7 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Directive_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Directive_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Directive", Field: field, @@ -30565,7 +32067,7 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Directive_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Directive_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Directive", Field: field, @@ -30609,7 +32111,7 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr return ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Directive_locations(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Directive_locations(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Directive", Field: field, @@ -30653,7 +32155,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Directive_args(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Directive_args(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Directive", Field: field, @@ -30707,7 +32209,7 @@ func (ec *executionContext) ___Directive_isRepeatable(ctx context.Context, field return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Directive_isRepeatable(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Directive_isRepeatable(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Directive", Field: field, @@ -30751,7 +32253,7 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___EnumValue_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___EnumValue_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__EnumValue", Field: field, @@ -30792,7 +32294,7 @@ func (ec *executionContext) ___EnumValue_description(ctx context.Context, field return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___EnumValue_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___EnumValue_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__EnumValue", Field: field, @@ -30836,7 +32338,7 @@ func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___EnumValue_isDeprecated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__EnumValue", Field: field, @@ -30877,7 +32379,7 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___EnumValue_deprecationReason(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__EnumValue", Field: field, @@ -30921,7 +32423,7 @@ func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.Col return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Field_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Field_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Field", Field: field, @@ -30962,7 +32464,7 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Field_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Field_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Field", Field: field, @@ -31006,7 +32508,7 @@ func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.Col return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Field_args(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Field_args(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Field", Field: field, @@ -31060,7 +32562,7 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Field_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Field_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Field", Field: field, @@ -31126,7 +32628,7 @@ func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field gra return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Field_isDeprecated(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Field_isDeprecated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Field", Field: field, @@ -31167,7 +32669,7 @@ func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, fiel return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Field_deprecationReason(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Field_deprecationReason(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Field", Field: field, @@ -31211,7 +32713,7 @@ func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphq return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___InputValue_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___InputValue_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__InputValue", Field: field, @@ -31252,7 +32754,7 @@ func (ec *executionContext) ___InputValue_description(ctx context.Context, field return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___InputValue_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___InputValue_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__InputValue", Field: field, @@ -31296,7 +32798,7 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___InputValue_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___InputValue_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__InputValue", Field: field, @@ -31359,7 +32861,7 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___InputValue_defaultValue(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__InputValue", Field: field, @@ -31400,7 +32902,7 @@ func (ec *executionContext) ___Schema_description(ctx context.Context, field gra return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Schema_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Schema_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Schema", Field: field, @@ -31444,7 +32946,7 @@ func (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.C return ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Schema_types(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Schema_types(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Schema", Field: field, @@ -31510,7 +33012,7 @@ func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graph return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Schema_queryType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Schema_queryType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Schema", Field: field, @@ -31573,7 +33075,7 @@ func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field gr return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Schema_mutationType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Schema_mutationType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Schema", Field: field, @@ -31636,7 +33138,7 @@ func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, fiel return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Schema_subscriptionType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Schema", Field: field, @@ -31702,7 +33204,7 @@ func (ec *executionContext) ___Schema_directives(ctx context.Context, field grap return ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Schema_directives(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Schema_directives(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Schema", Field: field, @@ -31758,7 +33260,7 @@ func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.Coll return ec.marshalN__TypeKind2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Type_kind(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Type_kind(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Type", Field: field, @@ -31799,7 +33301,7 @@ func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.Coll return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Type_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Type_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Type", Field: field, @@ -31840,7 +33342,7 @@ func (ec *executionContext) ___Type_description(ctx context.Context, field graph return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Type_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Type_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Type", Field: field, @@ -31947,7 +33449,7 @@ func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphq return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Type_interfaces(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Type_interfaces(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Type", Field: field, @@ -32010,7 +33512,7 @@ func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field gra return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Type_possibleTypes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Type_possibleTypes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Type", Field: field, @@ -32135,7 +33637,7 @@ func (ec *executionContext) ___Type_inputFields(ctx context.Context, field graph return ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Type_inputFields(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Type_inputFields(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Type", Field: field, @@ -32186,7 +33688,7 @@ func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.Co return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Type_ofType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Type_ofType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Type", Field: field, @@ -32249,7 +33751,7 @@ func (ec *executionContext) ___Type_specifiedByURL(ctx context.Context, field gr return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext___Type_specifiedByURL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext___Type_specifiedByURL(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "__Type", Field: field, @@ -32289,7 +33791,7 @@ func (ec *executionContext) unmarshalInputActionInput(ctx context.Context, obj i it.Dest = data case "params": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) - data, err := ec.unmarshalNDynamicParamInput2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParamInputᚄ(ctx, v) + data, err := ec.unmarshalNExprStringMap2map(ctx, v) if err != nil { return it, err } @@ -33551,32 +35053,11 @@ func (ec *executionContext) unmarshalInputCreateUserContactMethodInput(ctx conte it.Type = data case "dest": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("dest")) - directive0 := func(ctx context.Context) (interface{}, error) { - return ec.unmarshalODestinationInput2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDestinationInput(ctx, v) - } - directive1 := func(ctx context.Context) (interface{}, error) { - flagName, err := ec.unmarshalNString2string(ctx, "dest-types") - if err != nil { - return nil, err - } - if ec.directives.Experimental == nil { - return nil, errors.New("directive experimental is not implemented") - } - return ec.directives.Experimental(ctx, obj, directive0, flagName) - } - - tmp, err := directive1(ctx) + data, err := ec.unmarshalODestinationInput2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDestinationInput(ctx, v) if err != nil { - return it, graphql.ErrorOnPath(ctx, err) - } - if data, ok := tmp.(*DestinationInput); ok { - it.Dest = data - } else if tmp == nil { - it.Dest = nil - } else { - err := fmt.Errorf(`unexpected type %T from directive, should be *github.com/target/goalert/graphql2.DestinationInput`, tmp) - return it, graphql.ErrorOnPath(ctx, err) + return it, err } + it.Dest = data case "name": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) data, err := ec.unmarshalNString2string(ctx, v) @@ -34023,7 +35504,7 @@ func (ec *executionContext) unmarshalInputDestinationInput(ctx context.Context, asMap[k] = v } - fieldsInOrder := [...]string{"type", "values"} + fieldsInOrder := [...]string{"type", "values", "args"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -34039,45 +35520,22 @@ func (ec *executionContext) unmarshalInputDestinationInput(ctx context.Context, it.Type = data case "values": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("values")) - data, err := ec.unmarshalNFieldValueInput2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐFieldValueInputᚄ(ctx, v) + data, err := ec.unmarshalOFieldValueInput2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐFieldValueInputᚄ(ctx, v) if err != nil { return it, err } - it.Values = data - } - } - - return it, nil -} - -func (ec *executionContext) unmarshalInputDynamicParamInput(ctx context.Context, obj interface{}) (DynamicParamInput, error) { - var it DynamicParamInput - asMap := map[string]interface{}{} - for k, v := range obj.(map[string]interface{}) { - asMap[k] = v - } - - fieldsInOrder := [...]string{"paramID", "expr"} - for _, k := range fieldsInOrder { - v, ok := asMap[k] - if !ok { - continue - } - switch k { - case "paramID": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("paramID")) - data, err := ec.unmarshalNID2string(ctx, v) - if err != nil { + if err = ec.resolvers.DestinationInput().Values(ctx, &it, data); err != nil { return it, err } - it.ParamID = data - case "expr": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("expr")) - data, err := ec.unmarshalNExprStringExpression2string(ctx, v) + case "args": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("args")) + data, err := ec.unmarshalOStringMap2map(ctx, v) if err != nil { return it, err } - it.Expr = data + if err = ec.resolvers.DestinationInput().Args(ctx, &it, data); err != nil { + return it, err + } } } @@ -34288,7 +35746,7 @@ func (ec *executionContext) unmarshalInputKeyRuleInput(ctx context.Context, obj asMap[k] = v } - fieldsInOrder := [...]string{"id", "name", "description", "conditionExpr", "actions"} + fieldsInOrder := [...]string{"id", "name", "description", "conditionExpr", "actions", "continueAfterMatch"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -34330,6 +35788,13 @@ func (ec *executionContext) unmarshalInputKeyRuleInput(ctx context.Context, obj return it, err } it.Actions = data + case "continueAfterMatch": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("continueAfterMatch")) + data, err := ec.unmarshalNBoolean2bool(ctx, v) + if err != nil { + return it, err + } + it.ContinueAfterMatch = data } } @@ -35852,7 +37317,7 @@ func (ec *executionContext) unmarshalInputUpdateKeyConfigInput(ctx context.Conte asMap[k] = v } - fieldsInOrder := [...]string{"keyID", "stopAtFirstRule", "rules", "defaultActions"} + fieldsInOrder := [...]string{"keyID", "rules", "setRule", "deleteRule", "defaultActions"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -35866,13 +37331,6 @@ func (ec *executionContext) unmarshalInputUpdateKeyConfigInput(ctx context.Conte return it, err } it.KeyID = data - case "stopAtFirstRule": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("stopAtFirstRule")) - data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) - if err != nil { - return it, err - } - it.StopAtFirstRule = data case "rules": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("rules")) data, err := ec.unmarshalOKeyRuleInput2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐKeyRuleInputᚄ(ctx, v) @@ -35880,6 +37338,20 @@ func (ec *executionContext) unmarshalInputUpdateKeyConfigInput(ctx context.Conte return it, err } it.Rules = data + case "setRule": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("setRule")) + data, err := ec.unmarshalOKeyRuleInput2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐKeyRuleInput(ctx, v) + if err != nil { + return it, err + } + it.SetRule = data + case "deleteRule": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("deleteRule")) + data, err := ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.DeleteRule = data case "defaultActions": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("defaultActions")) data, err := ec.unmarshalOActionInput2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐActionInputᚄ(ctx, v) @@ -36735,7 +38207,7 @@ func (ec *executionContext) _Alert(ctx context.Context, sel ast.SelectionSet, ob case "service": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -36768,7 +38240,7 @@ func (ec *executionContext) _Alert(ctx context.Context, sel ast.SelectionSet, ob case "state": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -36873,7 +38345,7 @@ func (ec *executionContext) _Alert(ctx context.Context, sel ast.SelectionSet, ob case "metrics": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -36906,7 +38378,7 @@ func (ec *executionContext) _Alert(ctx context.Context, sel ast.SelectionSet, ob case "noiseReason": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -36939,7 +38411,7 @@ func (ec *executionContext) _Alert(ctx context.Context, sel ast.SelectionSet, ob case "meta": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -37176,7 +38648,7 @@ func (ec *executionContext) _AlertLogEntry(ctx context.Context, sel ast.Selectio case "state": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -38103,10 +39575,77 @@ func (ec *executionContext) _Destination(ctx context.Context, sel ast.SelectionS atomic.AddUint32(&out.Invalids, 1) } case "values": - out.Values[i] = ec._Destination_values(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Destination_values(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "args": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Destination_args(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) case "displayInfo": field := field @@ -38379,6 +39918,11 @@ func (ec *executionContext) _DestinationTypeInfo(ctx context.Context, sel ast.Se if out.Values[i] == graphql.Null { out.Invalids++ } + case "dynamicParams": + out.Values[i] = ec._DestinationTypeInfo_dynamicParams(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "userDisclaimer": out.Values[i] = ec._DestinationTypeInfo_userDisclaimer(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -38399,6 +39943,11 @@ func (ec *executionContext) _DestinationTypeInfo(ctx context.Context, sel ast.Se if out.Values[i] == graphql.Null { out.Invalids++ } + case "isDynamicAction": + out.Values[i] = ec._DestinationTypeInfo_isDynamicAction(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "supportsStatusUpdates": out.Values[i] = ec._DestinationTypeInfo_supportsStatusUpdates(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -38432,24 +39981,34 @@ func (ec *executionContext) _DestinationTypeInfo(ctx context.Context, sel ast.Se return out } -var dynamicParamImplementors = []string{"DynamicParam"} +var dynamicParamConfigImplementors = []string{"DynamicParamConfig"} -func (ec *executionContext) _DynamicParam(ctx context.Context, sel ast.SelectionSet, obj *DynamicParam) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, dynamicParamImplementors) +func (ec *executionContext) _DynamicParamConfig(ctx context.Context, sel ast.SelectionSet, obj *DynamicParamConfig) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, dynamicParamConfigImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("DynamicParam") + out.Values[i] = graphql.MarshalString("DynamicParamConfig") case "paramID": - out.Values[i] = ec._DynamicParam_paramID(ctx, field, obj) + out.Values[i] = ec._DynamicParamConfig_paramID(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "expr": - out.Values[i] = ec._DynamicParam_expr(ctx, field, obj) + case "label": + out.Values[i] = ec._DynamicParamConfig_label(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "hint": + out.Values[i] = ec._DynamicParamConfig_hint(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "hintURL": + out.Values[i] = ec._DynamicParamConfig_hintURL(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } @@ -38783,7 +40342,7 @@ func (ec *executionContext) _EscalationPolicyStep(ctx context.Context, sel ast.S case "escalationPolicy": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -39154,7 +40713,7 @@ func (ec *executionContext) _GQLAPIKey(ctx context.Context, sel ast.SelectionSet case "createdBy": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -39192,7 +40751,7 @@ func (ec *executionContext) _GQLAPIKey(ctx context.Context, sel ast.SelectionSet case "updatedBy": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -39580,152 +41139,216 @@ func (ec *executionContext) _IntegrationKey(ctx context.Context, sel ast.Selecti } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch(ctx) - if out.Invalids > 0 { - return graphql.Null - } - - atomic.AddInt32(&ec.deferred, int32(len(deferred))) - - for label, dfs := range deferred { - ec.processDeferredGroup(graphql.DeferredGroup{ - Label: label, - Path: graphql.GetPath(ctx), - FieldSet: dfs, - Context: ctx, - }) - } - - return out -} - -var integrationKeyConnectionImplementors = []string{"IntegrationKeyConnection"} - -func (ec *executionContext) _IntegrationKeyConnection(ctx context.Context, sel ast.SelectionSet, obj *IntegrationKeyConnection) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, integrationKeyConnectionImplementors) - - out := graphql.NewFieldSet(fields) - deferred := make(map[string]*graphql.FieldSet) - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("IntegrationKeyConnection") - case "nodes": - out.Values[i] = ec._IntegrationKeyConnection_nodes(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "pageInfo": - out.Values[i] = ec._IntegrationKeyConnection_pageInfo(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch(ctx) - if out.Invalids > 0 { - return graphql.Null - } - - atomic.AddInt32(&ec.deferred, int32(len(deferred))) - - for label, dfs := range deferred { - ec.processDeferredGroup(graphql.DeferredGroup{ - Label: label, - Path: graphql.GetPath(ctx), - FieldSet: dfs, - Context: ctx, - }) - } - - return out -} - -var integrationKeyTypeInfoImplementors = []string{"IntegrationKeyTypeInfo"} - -func (ec *executionContext) _IntegrationKeyTypeInfo(ctx context.Context, sel ast.SelectionSet, obj *IntegrationKeyTypeInfo) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, integrationKeyTypeInfoImplementors) - - out := graphql.NewFieldSet(fields) - deferred := make(map[string]*graphql.FieldSet) - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("IntegrationKeyTypeInfo") - case "id": - out.Values[i] = ec._IntegrationKeyTypeInfo_id(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "name": - out.Values[i] = ec._IntegrationKeyTypeInfo_name(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "label": - out.Values[i] = ec._IntegrationKeyTypeInfo_label(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "enabled": - out.Values[i] = ec._IntegrationKeyTypeInfo_enabled(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch(ctx) - if out.Invalids > 0 { - return graphql.Null - } - - atomic.AddInt32(&ec.deferred, int32(len(deferred))) - - for label, dfs := range deferred { - ec.processDeferredGroup(graphql.DeferredGroup{ - Label: label, - Path: graphql.GetPath(ctx), - FieldSet: dfs, - Context: ctx, - }) - } - - return out -} - -var keyConfigImplementors = []string{"KeyConfig"} - -func (ec *executionContext) _KeyConfig(ctx context.Context, sel ast.SelectionSet, obj *KeyConfig) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, keyConfigImplementors) - - out := graphql.NewFieldSet(fields) - deferred := make(map[string]*graphql.FieldSet) - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("KeyConfig") - case "stopAtFirstRule": - out.Values[i] = ec._KeyConfig_stopAtFirstRule(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "rules": - out.Values[i] = ec._KeyConfig_rules(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } + case "tokenInfo": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._IntegrationKey_tokenInfo(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var integrationKeyConnectionImplementors = []string{"IntegrationKeyConnection"} + +func (ec *executionContext) _IntegrationKeyConnection(ctx context.Context, sel ast.SelectionSet, obj *IntegrationKeyConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, integrationKeyConnectionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("IntegrationKeyConnection") + case "nodes": + out.Values[i] = ec._IntegrationKeyConnection_nodes(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._IntegrationKeyConnection_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var integrationKeyTypeInfoImplementors = []string{"IntegrationKeyTypeInfo"} + +func (ec *executionContext) _IntegrationKeyTypeInfo(ctx context.Context, sel ast.SelectionSet, obj *IntegrationKeyTypeInfo) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, integrationKeyTypeInfoImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("IntegrationKeyTypeInfo") + case "id": + out.Values[i] = ec._IntegrationKeyTypeInfo_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "name": + out.Values[i] = ec._IntegrationKeyTypeInfo_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "label": + out.Values[i] = ec._IntegrationKeyTypeInfo_label(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "enabled": + out.Values[i] = ec._IntegrationKeyTypeInfo_enabled(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var keyConfigImplementors = []string{"KeyConfig"} + +func (ec *executionContext) _KeyConfig(ctx context.Context, sel ast.SelectionSet, obj *KeyConfig) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, keyConfigImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("KeyConfig") + case "rules": + out.Values[i] = ec._KeyConfig_rules(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "oneRule": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._KeyConfig_oneRule(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) case "defaultActions": out.Values[i] = ec._KeyConfig_defaultActions(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } default: panic("unknown field " + strconv.Quote(field.Name)) @@ -39786,6 +41409,11 @@ func (ec *executionContext) _KeyRule(ctx context.Context, sel ast.SelectionSet, if out.Values[i] == graphql.Null { out.Invalids++ } + case "continueAfterMatch": + out.Values[i] = ec._KeyRule_continueAfterMatch(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -40404,6 +42032,27 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } + case "promoteSecondaryToken": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_promoteSecondaryToken(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deleteSecondaryToken": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_deleteSecondaryToken(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "generateKeyToken": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_generateKeyToken(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -40637,6 +42286,109 @@ func (ec *executionContext) _OnCallNotificationRule(ctx context.Context, sel ast return out } +var onCallOverviewImplementors = []string{"OnCallOverview"} + +func (ec *executionContext) _OnCallOverview(ctx context.Context, sel ast.SelectionSet, obj *OnCallOverview) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, onCallOverviewImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("OnCallOverview") + case "serviceCount": + out.Values[i] = ec._OnCallOverview_serviceCount(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "serviceAssignments": + out.Values[i] = ec._OnCallOverview_serviceAssignments(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var onCallServiceAssignmentImplementors = []string{"OnCallServiceAssignment"} + +func (ec *executionContext) _OnCallServiceAssignment(ctx context.Context, sel ast.SelectionSet, obj *OnCallServiceAssignment) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, onCallServiceAssignmentImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("OnCallServiceAssignment") + case "stepNumber": + out.Values[i] = ec._OnCallServiceAssignment_stepNumber(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "escalationPolicyID": + out.Values[i] = ec._OnCallServiceAssignment_escalationPolicyID(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "escalationPolicyName": + out.Values[i] = ec._OnCallServiceAssignment_escalationPolicyName(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "serviceID": + out.Values[i] = ec._OnCallServiceAssignment_serviceID(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "serviceName": + out.Values[i] = ec._OnCallServiceAssignment_serviceName(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var onCallShiftImplementors = []string{"OnCallShift"} func (ec *executionContext) _OnCallShift(ctx context.Context, sel ast.SelectionSet, obj *oncall.Shift) graphql.Marshaler { @@ -40656,7 +42408,7 @@ func (ec *executionContext) _OnCallShift(ctx context.Context, sel ast.SelectionS case "user": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -40851,7 +42603,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "phoneNumberInfo": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -40936,7 +42688,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "user": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -40977,7 +42729,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "alert": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41018,7 +42770,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "service": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41037,7 +42789,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "integrationKey": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41056,7 +42808,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "heartbeatMonitor": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41097,7 +42849,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "rotation": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41160,7 +42912,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "schedule": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41179,7 +42931,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "userCalendarSubscription": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41220,7 +42972,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "escalationPolicy": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41415,7 +43167,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "userOverride": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41544,7 +43296,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "userContactMethod": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41585,7 +43337,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "slackChannel": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41626,7 +43378,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "slackUserGroup": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41667,7 +43419,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "linkAccountInfo": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -41858,6 +43610,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "actionInputValidate": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_actionInputValidate(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "__type": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { @@ -42571,7 +44345,7 @@ func (ec *executionContext) _Schedule(ctx context.Context, sel ast.SelectionSet, case "target": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -42954,7 +44728,7 @@ func (ec *executionContext) _Service(ctx context.Context, sel ast.SelectionSet, case "escalationPolicy": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -43889,6 +45663,50 @@ func (ec *executionContext) _TimeZoneConnection(ctx context.Context, sel ast.Sel return out } +var tokenInfoImplementors = []string{"TokenInfo"} + +func (ec *executionContext) _TokenInfo(ctx context.Context, sel ast.SelectionSet, obj *TokenInfo) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, tokenInfoImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("TokenInfo") + case "primaryHint": + out.Values[i] = ec._TokenInfo_primaryHint(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "secondaryHint": + out.Values[i] = ec._TokenInfo_secondaryHint(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var userImplementors = []string{"User"} func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *user.User) graphql.Marshaler { @@ -44171,6 +45989,42 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "onCallOverview": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._User_onCallOverview(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) case "isFavorite": field := field @@ -44368,7 +46222,7 @@ func (ec *executionContext) _UserCalendarSubscription(ctx context.Context, sel a case "schedule": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -44411,7 +46265,7 @@ func (ec *executionContext) _UserCalendarSubscription(ctx context.Context, sel a case "url": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -44654,7 +46508,7 @@ func (ec *executionContext) _UserContactMethod(ctx context.Context, sel ast.Sele case "lastTestMessageState": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -44687,7 +46541,7 @@ func (ec *executionContext) _UserContactMethod(ctx context.Context, sel ast.Sele case "lastVerifyMessageState": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -44805,7 +46659,7 @@ func (ec *executionContext) _UserNotificationRule(ctx context.Context, sel ast.S case "contactMethod": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -44897,7 +46751,7 @@ func (ec *executionContext) _UserOverride(ctx context.Context, sel ast.Selection case "addUser": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -44930,7 +46784,7 @@ func (ec *executionContext) _UserOverride(ctx context.Context, sel ast.Selection case "removeUser": field := field - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -46399,11 +48253,11 @@ func (ec *executionContext) marshalNDestinationTypeInfo2ᚕgithubᚗcomᚋtarget return ret } -func (ec *executionContext) marshalNDynamicParam2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParam(ctx context.Context, sel ast.SelectionSet, v DynamicParam) graphql.Marshaler { - return ec._DynamicParam(ctx, sel, &v) +func (ec *executionContext) marshalNDynamicParamConfig2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParamConfig(ctx context.Context, sel ast.SelectionSet, v DynamicParamConfig) graphql.Marshaler { + return ec._DynamicParamConfig(ctx, sel, &v) } -func (ec *executionContext) marshalNDynamicParam2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParamᚄ(ctx context.Context, sel ast.SelectionSet, v []DynamicParam) graphql.Marshaler { +func (ec *executionContext) marshalNDynamicParamConfig2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParamConfigᚄ(ctx context.Context, sel ast.SelectionSet, v []DynamicParamConfig) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -46427,7 +48281,7 @@ func (ec *executionContext) marshalNDynamicParam2ᚕgithubᚗcomᚋtargetᚋgoal if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNDynamicParam2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParam(ctx, sel, v[i]) + ret[i] = ec.marshalNDynamicParamConfig2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParamConfig(ctx, sel, v[i]) } if isLen1 { f(i) @@ -46447,28 +48301,6 @@ func (ec *executionContext) marshalNDynamicParam2ᚕgithubᚗcomᚋtargetᚋgoal return ret } -func (ec *executionContext) unmarshalNDynamicParamInput2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParamInput(ctx context.Context, v interface{}) (DynamicParamInput, error) { - res, err := ec.unmarshalInputDynamicParamInput(ctx, v) - return res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) unmarshalNDynamicParamInput2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParamInputᚄ(ctx context.Context, v interface{}) ([]DynamicParamInput, error) { - var vSlice []interface{} - if v != nil { - vSlice = graphql.CoerceList(v) - } - var err error - res := make([]DynamicParamInput, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNDynamicParamInput2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐDynamicParamInput(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - func (ec *executionContext) marshalNEscalationPolicy2githubᚗcomᚋtargetᚋgoalertᚋescalationᚐPolicy(ctx context.Context, sel ast.SelectionSet, v escalation.Policy) graphql.Marshaler { return ec._EscalationPolicy(ctx, sel, &v) } @@ -46644,13 +48476,19 @@ func (ec *executionContext) marshalNExprOperator2string(ctx context.Context, sel return res } -func (ec *executionContext) unmarshalNExprStringExpression2string(ctx context.Context, v interface{}) (string, error) { - res, err := UnmarshalExprStringExpression(v) +func (ec *executionContext) unmarshalNExprStringMap2map(ctx context.Context, v interface{}) (map[string]string, error) { + res, err := UnmarshalExprStringMap(v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNExprStringExpression2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { - res := MarshalExprStringExpression(v) +func (ec *executionContext) marshalNExprStringMap2map(ctx context.Context, sel ast.SelectionSet, v map[string]string) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + res := MarshalExprStringMap(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") @@ -46752,23 +48590,6 @@ func (ec *executionContext) unmarshalNFieldValueInput2githubᚗcomᚋtargetᚋgo return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalNFieldValueInput2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐFieldValueInputᚄ(ctx context.Context, v interface{}) ([]FieldValueInput, error) { - var vSlice []interface{} - if v != nil { - vSlice = graphql.CoerceList(v) - } - var err error - res := make([]FieldValueInput, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNFieldValueInput2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐFieldValueInput(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - func (ec *executionContext) marshalNFieldValuePair2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐFieldValuePair(ctx context.Context, sel ast.SelectionSet, v FieldValuePair) graphql.Marshaler { return ec._FieldValuePair(ctx, sel, &v) } @@ -47537,6 +49358,68 @@ func (ec *executionContext) unmarshalNOnCallNotificationRuleInput2ᚕgithubᚗco return res, nil } +func (ec *executionContext) marshalNOnCallOverview2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐOnCallOverview(ctx context.Context, sel ast.SelectionSet, v OnCallOverview) graphql.Marshaler { + return ec._OnCallOverview(ctx, sel, &v) +} + +func (ec *executionContext) marshalNOnCallOverview2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐOnCallOverview(ctx context.Context, sel ast.SelectionSet, v *OnCallOverview) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._OnCallOverview(ctx, sel, v) +} + +func (ec *executionContext) marshalNOnCallServiceAssignment2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐOnCallServiceAssignment(ctx context.Context, sel ast.SelectionSet, v OnCallServiceAssignment) graphql.Marshaler { + return ec._OnCallServiceAssignment(ctx, sel, &v) +} + +func (ec *executionContext) marshalNOnCallServiceAssignment2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐOnCallServiceAssignmentᚄ(ctx context.Context, sel ast.SelectionSet, v []OnCallServiceAssignment) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNOnCallServiceAssignment2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐOnCallServiceAssignment(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalNOnCallShift2githubᚗcomᚋtargetᚋgoalertᚋoncallᚐShift(ctx context.Context, sel ast.SelectionSet, v oncall.Shift) graphql.Marshaler { return ec._OnCallShift(ctx, sel, &v) } @@ -48295,6 +50178,27 @@ func (ec *executionContext) marshalNStringConnection2ᚖgithubᚗcomᚋtargetᚋ return ec._StringConnection(ctx, sel, v) } +func (ec *executionContext) unmarshalNStringMap2map(ctx context.Context, v interface{}) (map[string]string, error) { + res, err := UnmarshalStringMap(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNStringMap2map(ctx context.Context, sel ast.SelectionSet, v map[string]string) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + res := MarshalStringMap(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + func (ec *executionContext) marshalNSystemLimit2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐSystemLimit(ctx context.Context, sel ast.SelectionSet, v SystemLimit) graphql.Marshaler { return ec._SystemLimit(ctx, sel, &v) } @@ -48622,6 +50526,20 @@ func (ec *executionContext) marshalNTimeZoneConnection2ᚖgithubᚗcomᚋtarget return ec._TimeZoneConnection(ctx, sel, v) } +func (ec *executionContext) marshalNTokenInfo2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐTokenInfo(ctx context.Context, sel ast.SelectionSet, v TokenInfo) graphql.Marshaler { + return ec._TokenInfo(ctx, sel, &v) +} + +func (ec *executionContext) marshalNTokenInfo2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐTokenInfo(ctx context.Context, sel ast.SelectionSet, v *TokenInfo) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._TokenInfo(ctx, sel, v) +} + func (ec *executionContext) unmarshalNUpdateAlertsByServiceInput2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐUpdateAlertsByServiceInput(ctx context.Context, v interface{}) (UpdateAlertsByServiceInput, error) { res, err := ec.unmarshalInputUpdateAlertsByServiceInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -49844,6 +51762,26 @@ func (ec *executionContext) marshalOEscalationPolicyStep2ᚖgithubᚗcomᚋtarge return ec._EscalationPolicyStep(ctx, sel, v) } +func (ec *executionContext) unmarshalOFieldValueInput2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐFieldValueInputᚄ(ctx context.Context, v interface{}) ([]FieldValueInput, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]FieldValueInput, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNFieldValueInput2githubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐFieldValueInput(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + func (ec *executionContext) marshalOGQLAPIKeyUsage2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐGQLAPIKeyUsage(ctx context.Context, sel ast.SelectionSet, v *GQLAPIKeyUsage) graphql.Marshaler { if v == nil { return graphql.Null @@ -50033,6 +51971,13 @@ func (ec *executionContext) unmarshalOIntegrationKeySearchOptions2ᚖgithubᚗco return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalOKeyRule2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐKeyRule(ctx context.Context, sel ast.SelectionSet, v *KeyRule) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._KeyRule(ctx, sel, v) +} + func (ec *executionContext) unmarshalOKeyRuleInput2ᚕgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐKeyRuleInputᚄ(ctx context.Context, v interface{}) ([]KeyRuleInput, error) { if v == nil { return nil, nil @@ -50053,6 +51998,14 @@ func (ec *executionContext) unmarshalOKeyRuleInput2ᚕgithubᚗcomᚋtargetᚋgo return res, nil } +func (ec *executionContext) unmarshalOKeyRuleInput2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐKeyRuleInput(ctx context.Context, v interface{}) (*KeyRuleInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputKeyRuleInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOLabelKeySearchOptions2ᚖgithubᚗcomᚋtargetᚋgoalertᚋgraphql2ᚐLabelKeySearchOptions(ctx context.Context, v interface{}) (*LabelKeySearchOptions, error) { if v == nil { return nil, nil @@ -50371,6 +52324,22 @@ func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel as return res } +func (ec *executionContext) unmarshalOStringMap2map(ctx context.Context, v interface{}) (map[string]string, error) { + if v == nil { + return nil, nil + } + res, err := UnmarshalStringMap(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOStringMap2map(ctx context.Context, sel ast.SelectionSet, v map[string]string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := MarshalStringMap(v) + return res +} + func (ec *executionContext) unmarshalOTargetInput2githubᚗcomᚋtargetᚋgoalertᚋassignmentᚐRawTarget(ctx context.Context, v interface{}) (assignment.RawTarget, error) { res, err := ec.unmarshalInputTargetInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/graphql2/gqlgen.yml b/graphql2/gqlgen.yml index 0a96c78119..e74984e203 100644 --- a/graphql2/gqlgen.yml +++ b/graphql2/gqlgen.yml @@ -120,3 +120,7 @@ models: model: github.com/target/goalert/graphql2.ExprValue ExprIdentifier: model: github.com/target/goalert/graphql2.ExprIdentifier + ExprStringMap: + model: github.com/target/goalert/graphql2.ExprStringMap + StringMap: + model: github.com/target/goalert/graphql2.StringMap diff --git a/graphql2/graph/destinations.graphqls b/graphql2/graph/destinations.graphqls index 8d64821b7e..89935a2508 100644 --- a/graphql2/graph/destinations.graphqls +++ b/graphql2/graph/destinations.graphqls @@ -3,7 +3,7 @@ extend type Query { destinationTypes returns a list of destination types that can be used for notifications. """ - destinationTypes: [DestinationTypeInfo!]! + destinationTypes(isDynamicAction: Boolean): [DestinationTypeInfo!]! """ destinationFieldValidate validates a destination field value as valid or invalid. @@ -110,12 +110,20 @@ input DestinationFieldSearchInput { union InlineDisplayInfo = DestinationDisplayInfo | DestinationDisplayInfoError +""" +A map of string keys to string values +""" +scalar StringMap + """ Destination represents a destination that can be used for notifications. """ type Destination { type: DestinationType! values: [FieldValuePair!]! + @goField(forceResolver: true) + @deprecated(reason: "Use the args field instead") + args: StringMap! @goField(forceResolver: true) displayInfo: InlineDisplayInfo! @goField(forceResolver: true) } @@ -165,7 +173,10 @@ type FieldValuePair { input DestinationInput { type: DestinationType! - values: [FieldValueInput!]! + values: [FieldValueInput!] + @goField(forceResolver: true) + @deprecated(reason: "Use the args field instead") + args: StringMap @goField(forceResolver: true) } input FieldValueInput { @@ -197,6 +208,11 @@ type DestinationTypeInfo { enabled: Boolean! requiredFields: [DestinationFieldConfig!]! + """ + expr parameters that can be used for this destination type + """ + dynamicParams: [DynamicParamConfig!]! + """ disclaimer text to display when a user is selecting this destination type for a contact method """ @@ -217,6 +233,11 @@ type DestinationTypeInfo { """ isSchedOnCallNotify: Boolean! + """ + this destination type can be used for dynamic actions + """ + isDynamicAction: Boolean! + """ if true, the destination type supports status updates """ @@ -274,3 +295,25 @@ type DestinationFieldConfig { """ supportsValidation: Boolean! } + +type DynamicParamConfig { + """ + unique ID for the input field + """ + paramID: ID! + + """ + user-friendly label (should be singular) + """ + label: String! + + """ + user-friendly helper text for input fields (i.e., "Enter a phone number") + """ + hint: String! + + """ + URL to link to for more information about the destination type + """ + hintURL: String! +} diff --git a/graphql2/graph/errorcodes.graphqls b/graphql2/graph/errorcodes.graphqls index 618eb986db..a7fdf30935 100644 --- a/graphql2/graph/errorcodes.graphqls +++ b/graphql2/graph/errorcodes.graphqls @@ -20,6 +20,15 @@ enum ErrorCode { """ INVALID_DEST_FIELD_VALUE + """ + The `path` field contains the exact path to the map that is invalid. + + The `extensions.key` field contains the key of the value that is invalid. + + A separate error will be returned for each invalid value. + """ + INVALID_MAP_FIELD_VALUE + """ The expr expression is too complex to be converted to a Condition. """ diff --git a/graphql2/graph/univkeys.graphqls b/graphql2/graph/univkeys.graphqls index 16283431d0..3a5c190140 100644 --- a/graphql2/graph/univkeys.graphqls +++ b/graphql2/graph/univkeys.graphqls @@ -3,21 +3,64 @@ extend type IntegrationKey { config returns the configuration for the key. """ config: KeyConfig! @experimental(flagName: "univ-keys") + + """ + tokenInfo returns information about the access tokens for the key. + """ + tokenInfo: TokenInfo! @experimental(flagName: "univ-keys") +} + +type TokenInfo { + """ + primaryHint is a hint for the primary token. It is empty if the primary token is not set. + """ + primaryHint: String! + + """ + secondaryHint is a hint for the secondary token. It is empty if the secondary token is not set. + """ + secondaryHint: String! } extend type Mutation { updateKeyConfig(input: UpdateKeyConfigInput!): Boolean! @experimental(flagName: "univ-keys") -} -type KeyConfig { """ - Stop evaluating rules after the first rule that matches. + promoteSecondaryToken promotes the secondary token to the primary token. """ - stopAtFirstRule: Boolean! + promoteSecondaryToken(id: ID!): Boolean! @experimental(flagName: "univ-keys") + """ + deleteSecondaryToken deletes the secondary token. + """ + deleteSecondaryToken(id: ID!): Boolean! @experimental(flagName: "univ-keys") + + """ + generateKeyToken generates a new token for an integration key. + + If the integration key already has a primary token, the new token will be the secondary token. + + If the integration key does not have a primary token, the new token will be the primary token. + + If the integration key already has a secondary token, an error will be returned. + """ + generateKeyToken(id: ID!): String! @experimental(flagName: "univ-keys") +} + +extend type Query { + actionInputValidate(input: ActionInput!): Boolean! + @experimental(flagName: "univ-keys") +} + +type KeyConfig { rules: [KeyRule!]! + """ + Get a single rule by ID. + """ + oneRule(id: ID!): KeyRule @goField(forceResolver: true) + """ defaultAction is the action to take if no rules match the request. """ @@ -36,17 +79,27 @@ type KeyRule { conditionExpr: ExprBooleanExpression! actions: [Action!]! + + """ + Continue evaluating rules after this rule matches. + """ + continueAfterMatch: Boolean! } input UpdateKeyConfigInput { keyID: ID! + rules: [KeyRuleInput!] + """ - Stop evaluating rules after the first rule that matches. + setRule allows you to set a single rule. If ID is provided, the rule with that ID will be updated. If ID is not provided, a new rule will be created and appended to the list of rules. """ - stopAtFirstRule: Boolean + setRule: KeyRuleInput - rules: [KeyRuleInput!] + """ + deleteRule allows you to delete a single rule by ID. + """ + deleteRule: ID """ defaultAction is the action to take if no rules match the request. @@ -69,24 +122,29 @@ input KeyRuleInput { conditionExpr: ExprBooleanExpression! actions: [ActionInput!]! + + """ + Continue evaluating rules after this rule matches. + + If this is set to false (default), no further rules will be evaluated after this rule matches. + """ + continueAfterMatch: Boolean! } +""" +ExprStringMap is a map of string expressions. + +Example: +{ "paramID": "expr expression" } +""" +scalar ExprStringMap + input ActionInput { dest: DestinationInput! - params: [DynamicParamInput!]! + params: ExprStringMap! } type Action { dest: Destination! - params: [DynamicParam!]! -} - -input DynamicParamInput { - paramID: ID! - expr: ExprStringExpression! -} - -type DynamicParam { - paramID: ID! - expr: ExprStringExpression! + params: ExprStringMap! } diff --git a/graphql2/graphqlapp/app.go b/graphql2/graphqlapp/app.go index 68a36a954a..fa8b80e0c6 100644 --- a/graphql2/graphqlapp/app.go +++ b/graphql2/graphqlapp/app.go @@ -273,6 +273,15 @@ func (a *App) Handler() http.Handler { } } + var mapErr graphql2.MapValueError + if errors.As(err, &mapErr) { + gqlErr.Message = mapErr.Err.Error() + gqlErr.Extensions = map[string]interface{}{ + "code": "INVALID_MAP_FIELD_VALUE", + "key": mapErr.Key, + } + } + return gqlErr }) diff --git a/graphql2/graphqlapp/compat.go b/graphql2/graphqlapp/compat.go index dc06c541f9..e033af1ad5 100644 --- a/graphql2/graphqlapp/compat.go +++ b/graphql2/graphqlapp/compat.go @@ -18,38 +18,28 @@ func CompatTargetToDest(tgt assignment.Target) (graphql2.Destination, error) { case assignment.TargetTypeUser: return graphql2.Destination{ Type: destUser, - Values: []graphql2.FieldValuePair{{ - FieldID: fieldUserID, - Value: tgt.TargetID(), - }}}, nil + Args: map[string]string{fieldUserID: tgt.TargetID()}, + }, nil case assignment.TargetTypeRotation: return graphql2.Destination{ Type: destRotation, - Values: []graphql2.FieldValuePair{{ - FieldID: fieldRotationID, - Value: tgt.TargetID(), - }}}, nil + Args: map[string]string{fieldRotationID: tgt.TargetID()}, + }, nil case assignment.TargetTypeSchedule: return graphql2.Destination{ Type: destSchedule, - Values: []graphql2.FieldValuePair{{ - FieldID: fieldScheduleID, - Value: tgt.TargetID(), - }}}, nil + Args: map[string]string{fieldScheduleID: tgt.TargetID()}, + }, nil case assignment.TargetTypeChanWebhook: return graphql2.Destination{ Type: destWebhook, - Values: []graphql2.FieldValuePair{{ - FieldID: fieldWebhookURL, - Value: tgt.TargetID(), - }}}, nil + Args: map[string]string{fieldWebhookURL: tgt.TargetID()}, + }, nil case assignment.TargetTypeSlackChannel: return graphql2.Destination{ Type: destSlackChan, - Values: []graphql2.FieldValuePair{{ - FieldID: fieldSlackChanID, - Value: tgt.TargetID(), - }}}, nil + Args: map[string]string{fieldSlackChanID: tgt.TargetID()}, + }, nil } return graphql2.Destination{}, fmt.Errorf("unknown target type: %s", tgt.TargetType()) @@ -66,12 +56,7 @@ func (a *App) CompatNCToDest(ctx context.Context, ncID uuid.UUID) (*graphql2.Des case notificationchannel.TypeSlackChan: return &graphql2.Destination{ Type: destSlackChan, - Values: []graphql2.FieldValuePair{ - { - FieldID: fieldSlackChanID, - Value: nc.Value, - }, - }, + Args: map[string]string{fieldSlackChanID: nc.Value}, }, nil case notificationchannel.TypeSlackUG: ugID, chanID, ok := strings.Cut(nc.Value, ":") @@ -81,26 +66,15 @@ func (a *App) CompatNCToDest(ctx context.Context, ncID uuid.UUID) (*graphql2.Des return &graphql2.Destination{ Type: destSlackUG, - Values: []graphql2.FieldValuePair{ - { - FieldID: fieldSlackUGID, - Value: ugID, - }, - { - FieldID: fieldSlackChanID, - Value: chanID, - }, + Args: map[string]string{ + fieldSlackUGID: ugID, + fieldSlackChanID: chanID, }, }, nil case notificationchannel.TypeWebhook: return &graphql2.Destination{ Type: destWebhook, - Values: []graphql2.FieldValuePair{ - { - FieldID: fieldWebhookURL, - Value: nc.Value, - }, - }, + Args: map[string]string{fieldWebhookURL: nc.Value}, }, nil default: return nil, fmt.Errorf("unsupported notification channel type: %s", nc.Type) @@ -112,15 +86,15 @@ func (a *App) CompatNCToDest(ctx context.Context, ncID uuid.UUID) (*graphql2.Des func CompatDestToCMTypeVal(d graphql2.DestinationInput) (contactmethod.Type, string) { switch d.Type { case destTwilioSMS: - return contactmethod.TypeSMS, d.FieldValue(fieldPhoneNumber) + return contactmethod.TypeSMS, d.Args[fieldPhoneNumber] case destTwilioVoice: - return contactmethod.TypeVoice, d.FieldValue(fieldPhoneNumber) + return contactmethod.TypeVoice, d.Args[fieldPhoneNumber] case destSMTP: - return contactmethod.TypeEmail, d.FieldValue(fieldEmailAddress) + return contactmethod.TypeEmail, d.Args[fieldEmailAddress] case destWebhook: - return contactmethod.TypeWebhook, d.FieldValue(fieldWebhookURL) + return contactmethod.TypeWebhook, d.Args[fieldWebhookURL] case destSlackDM: - return contactmethod.TypeSlackDM, d.FieldValue(fieldSlackUserID) + return contactmethod.TypeSlackDM, d.Args[fieldSlackUserID] } return "", "" @@ -132,32 +106,32 @@ func CompatDestToTarget(d graphql2.DestinationInput) (assignment.RawTarget, erro case destUser: return assignment.RawTarget{ Type: assignment.TargetTypeUser, - ID: d.FieldValue(fieldUserID), + ID: d.Args[fieldUserID], }, nil case destRotation: return assignment.RawTarget{ Type: assignment.TargetTypeRotation, - ID: d.FieldValue(fieldRotationID), + ID: d.Args[fieldRotationID], }, nil case destSchedule: return assignment.RawTarget{ Type: assignment.TargetTypeSchedule, - ID: d.FieldValue(fieldScheduleID), + ID: d.Args[fieldScheduleID], }, nil case destSlackChan: return assignment.RawTarget{ Type: assignment.TargetTypeSlackChannel, - ID: d.FieldValue(fieldSlackChanID), + ID: d.Args[fieldSlackChanID], }, nil case destSlackUG: return assignment.RawTarget{ Type: assignment.TargetTypeSlackUserGroup, - ID: d.FieldValue(fieldSlackUGID) + ":" + d.FieldValue(fieldSlackChanID), + ID: d.Args[fieldSlackUGID] + ":" + d.Args[fieldSlackChanID], }, nil case destWebhook: return assignment.RawTarget{ Type: assignment.TargetTypeChanWebhook, - ID: d.FieldValue(fieldWebhookURL), + ID: d.Args[fieldWebhookURL], }, nil } diff --git a/graphql2/graphqlapp/contactmethod.go b/graphql2/graphqlapp/contactmethod.go index 2b14a37f22..248bf41a26 100644 --- a/graphql2/graphqlapp/contactmethod.go +++ b/graphql2/graphqlapp/contactmethod.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/target/goalert/config" - "github.com/target/goalert/expflag" "github.com/target/goalert/graphql2" "github.com/target/goalert/notification" "github.com/target/goalert/notification/webhook" @@ -28,37 +27,27 @@ func (a *ContactMethod) Dest(ctx context.Context, obj *contactmethod.ContactMeth case contactmethod.TypeSMS: return &graphql2.Destination{ Type: destTwilioSMS, - Values: []graphql2.FieldValuePair{ - {FieldID: fieldPhoneNumber, Value: obj.Value}, - }, + Args: map[string]string{fieldPhoneNumber: obj.Value}, }, nil case contactmethod.TypeVoice: return &graphql2.Destination{ Type: destTwilioVoice, - Values: []graphql2.FieldValuePair{ - {FieldID: fieldPhoneNumber, Value: obj.Value}, - }, + Args: map[string]string{fieldPhoneNumber: obj.Value}, }, nil case contactmethod.TypeEmail: return &graphql2.Destination{ Type: destSMTP, - Values: []graphql2.FieldValuePair{ - {FieldID: fieldEmailAddress, Value: obj.Value}, - }, + Args: map[string]string{fieldEmailAddress: obj.Value}, }, nil case contactmethod.TypeWebhook: return &graphql2.Destination{ Type: destWebhook, - Values: []graphql2.FieldValuePair{ - {FieldID: fieldWebhookURL, Value: obj.Value}, - }, + Args: map[string]string{fieldWebhookURL: obj.Value}, }, nil case contactmethod.TypeSlackDM: return &graphql2.Destination{ Type: destSlackDM, - Values: []graphql2.FieldValuePair{ - {FieldID: fieldSlackUserID, Value: obj.Value}, - }, + Args: map[string]string{fieldSlackUserID: obj.Value}, }, nil } @@ -191,7 +180,6 @@ func (m *Mutation) CreateUserContactMethod(ctx context.Context, input graphql2.C input.NewUserNotificationRule.ContactMethodID = &cm.ID _, err = m.CreateUserNotificationRule(ctx, *input.NewUserNotificationRule) - if err != nil { return validation.AddPrefix("newUserNotificationRule.", err) } @@ -216,7 +204,7 @@ func (m *Mutation) UpdateUserContactMethod(ctx context.Context, input graphql2.U } if input.Name != nil { err := validate.IDName("input.name", *input.Name) - if err != nil && expflag.ContextHas(ctx, expflag.DestTypes) { + if err != nil { addInputError(ctx, err) return errAlreadySet } diff --git a/graphql2/graphqlapp/destinationdisplayinfo.go b/graphql2/graphqlapp/destinationdisplayinfo.go index 35a0f742b6..a728d523da 100644 --- a/graphql2/graphqlapp/destinationdisplayinfo.go +++ b/graphql2/graphqlapp/destinationdisplayinfo.go @@ -14,10 +14,57 @@ import ( ) type ( - Destination App + Destination App + DestinationInput App ) -func (a *App) Destination() graphql2.DestinationResolver { return (*Destination)(a) } +func (a *App) Destination() graphql2.DestinationResolver { return (*Destination)(a) } +func (a *App) DestinationInput() graphql2.DestinationInputResolver { return (*DestinationInput)(a) } + +func (a *DestinationInput) Args(ctx context.Context, obj *graphql2.DestinationInput, args map[string]string) error { + obj.Args = args + + obj.Values = make([]graphql2.FieldValueInput, 0, len(args)) + for k, v := range args { + obj.Values = append(obj.Values, graphql2.FieldValueInput{FieldID: k, Value: v}) + } + + return nil +} + +func (a *DestinationInput) Values(ctx context.Context, obj *graphql2.DestinationInput, values []graphql2.FieldValueInput) error { + obj.Values = values + obj.Args = make(map[string]string, len(values)) + for _, val := range values { + obj.Args[val.FieldID] = val.Value + } + return nil +} + +func (a *Destination) Args(ctx context.Context, obj *graphql2.Destination) (map[string]string, error) { + if obj.Args != nil { + return obj.Args, nil + } + + m := make(map[string]string, len(obj.Values)) + for _, val := range obj.Values { + m[val.FieldID] = val.Value + } + + return m, nil +} + +func (a *Destination) Values(ctx context.Context, obj *graphql2.Destination) ([]graphql2.FieldValuePair, error) { + if obj.Args != nil { + pairs := make([]graphql2.FieldValuePair, 0, len(obj.Args)) + for k, v := range obj.Args { + pairs = append(pairs, graphql2.FieldValuePair{FieldID: k, Value: v}) + } + return pairs, nil + } + + return obj.Values, nil +} // DisplayInfo will return the display information for a destination by mapping to Query.DestinationDisplayInfo. func (a *Destination) DisplayInfo(ctx context.Context, obj *graphql2.Destination) (graphql2.InlineDisplayInfo, error) { @@ -25,12 +72,7 @@ func (a *Destination) DisplayInfo(ctx context.Context, obj *graphql2.Destination return obj.DisplayInfo, nil } - values := make([]graphql2.FieldValueInput, len(obj.Values)) - for i, v := range obj.Values { - values[i] = graphql2.FieldValueInput(v) - } - - info, err := (*Query)(a)._DestinationDisplayInfo(ctx, graphql2.DestinationInput{Type: obj.Type, Values: values}, true) + info, err := (*Query)(a)._DestinationDisplayInfo(ctx, graphql2.DestinationInput{Type: obj.Type, Args: obj.Args}, true) if err != nil { isUnsafe, safeErr := errutil.ScrubError(err) if isUnsafe { @@ -55,8 +97,14 @@ func (a *Query) _DestinationDisplayInfo(ctx context.Context, dest graphql2.Desti } } switch dest.Type { + case destAlert: + return &graphql2.DestinationDisplayInfo{ + IconURL: "builtin://alert", + IconAltText: "Alert", + Text: "Create new alert", + }, nil case destTwilioSMS: - n, err := phonenumbers.Parse(dest.FieldValue(fieldPhoneNumber), "") + n, err := phonenumbers.Parse(dest.Args[fieldPhoneNumber], "") if err != nil { return nil, validation.WrapError(err) } @@ -67,7 +115,7 @@ func (a *Query) _DestinationDisplayInfo(ctx context.Context, dest graphql2.Desti Text: phonenumbers.Format(n, phonenumbers.INTERNATIONAL), }, nil case destTwilioVoice: - n, err := phonenumbers.Parse(dest.FieldValue(fieldPhoneNumber), "") + n, err := phonenumbers.Parse(dest.Args[fieldPhoneNumber], "") if err != nil { return nil, validation.WrapError(err) } @@ -77,7 +125,7 @@ func (a *Query) _DestinationDisplayInfo(ctx context.Context, dest graphql2.Desti Text: phonenumbers.Format(n, phonenumbers.INTERNATIONAL), }, nil case destSMTP: - e, err := mail.ParseAddress(dest.FieldValue(fieldEmailAddress)) + e, err := mail.ParseAddress(dest.Args[fieldEmailAddress]) if err != nil { return nil, validation.WrapError(err) } @@ -87,7 +135,7 @@ func (a *Query) _DestinationDisplayInfo(ctx context.Context, dest graphql2.Desti Text: e.Address, }, nil case destRotation: - r, err := app.FindOneRotation(ctx, dest.FieldValue(fieldRotationID)) + r, err := app.FindOneRotation(ctx, dest.Args[fieldRotationID]) if err != nil { return nil, err } @@ -98,7 +146,7 @@ func (a *Query) _DestinationDisplayInfo(ctx context.Context, dest graphql2.Desti Text: r.Name, }, nil case destSchedule: - s, err := app.FindOneSchedule(ctx, dest.FieldValue(fieldScheduleID)) + s, err := app.FindOneSchedule(ctx, dest.Args[fieldScheduleID]) if err != nil { return nil, err } @@ -109,7 +157,7 @@ func (a *Query) _DestinationDisplayInfo(ctx context.Context, dest graphql2.Desti Text: s.Name, }, nil case destUser: - u, err := app.FindOneUser(ctx, dest.FieldValue(fieldUserID)) + u, err := app.FindOneUser(ctx, dest.Args[fieldUserID]) if err != nil { return nil, err } @@ -121,7 +169,7 @@ func (a *Query) _DestinationDisplayInfo(ctx context.Context, dest graphql2.Desti }, nil case destWebhook: - u, err := url.Parse(dest.FieldValue(fieldWebhookURL)) + u, err := url.Parse(dest.Args[fieldWebhookURL]) if err != nil { return nil, validation.WrapError(err) } @@ -131,7 +179,7 @@ func (a *Query) _DestinationDisplayInfo(ctx context.Context, dest graphql2.Desti Text: u.Hostname(), }, nil case destSlackDM: - u, err := app.SlackStore.User(ctx, dest.FieldValue(fieldSlackUserID)) + u, err := app.SlackStore.User(ctx, dest.Args[fieldSlackUserID]) if err != nil { return nil, err } @@ -152,7 +200,7 @@ func (a *Query) _DestinationDisplayInfo(ctx context.Context, dest graphql2.Desti Text: u.Name, }, nil case destSlackChan: - ch, err := app.SlackStore.Channel(ctx, dest.FieldValue(fieldSlackChanID)) + ch, err := app.SlackStore.Channel(ctx, dest.Args[fieldSlackChanID]) if err != nil { return nil, err } @@ -173,7 +221,7 @@ func (a *Query) _DestinationDisplayInfo(ctx context.Context, dest graphql2.Desti }, nil case destSlackUG: - ug, err := app.SlackStore.UserGroup(ctx, dest.FieldValue(fieldSlackUGID)) + ug, err := app.SlackStore.UserGroup(ctx, dest.Args[fieldSlackUGID]) if err != nil { return nil, err } diff --git a/graphql2/graphqlapp/destinationtypes.go b/graphql2/graphqlapp/destinationtypes.go index 0a0a28448e..29f31a316e 100644 --- a/graphql2/graphqlapp/destinationtypes.go +++ b/graphql2/graphqlapp/destinationtypes.go @@ -23,6 +23,7 @@ const ( destUser = "builtin-user" destRotation = "builtin-rotation" destSchedule = "builtin-schedule" + destAlert = "builtin-alert" fieldPhoneNumber = "phone-number" fieldEmailAddress = "email-address" @@ -35,8 +36,10 @@ const ( fieldScheduleID = "schedule-id" ) -type FieldValuePair App -type DestinationDisplayInfo App +type ( + FieldValuePair App + DestinationDisplayInfo App +) func (q *Query) DestinationFieldValueName(ctx context.Context, input graphql2.DestinationFieldValidateInput) (string, error) { switch input.FieldID { @@ -243,9 +246,32 @@ func (q *Query) DestinationFieldValidate(ctx context.Context, input graphql2.Des return false, validation.NewGenericError("unsupported data type") } -func (q *Query) DestinationTypes(ctx context.Context) ([]graphql2.DestinationTypeInfo, error) { +func (q *Query) DestinationTypes(ctx context.Context, isDynamicAction *bool) ([]graphql2.DestinationTypeInfo, error) { cfg := config.FromContext(ctx) types := []graphql2.DestinationTypeInfo{ + { + Type: destAlert, + Name: "Alert", + Enabled: true, + IsDynamicAction: true, + DynamicParams: []graphql2.DynamicParamConfig{{ + ParamID: "summary", + Label: "Summary", + Hint: "Short summary of the alert (used for things like SMS).", + }, { + ParamID: "details", + Label: "Details", + Hint: "Full body (markdown) text of the alert.", + }, { + ParamID: "dedup", + Label: "Dedup", + Hint: "Stable identifier for de-duplication and closing existing alerts.", + }, { + ParamID: "close", + Label: "Close", + Hint: "If true, close an existing alert.", + }}, + }, { Type: destTwilioSMS, Name: "Text Message (SMS)", @@ -413,5 +439,14 @@ func (q *Query) DestinationTypes(ctx context.Context) ([]graphql2.DestinationTyp return 0 }) - return types, nil + filtered := types[:0] + for _, t := range types { + if isDynamicAction != nil && *isDynamicAction != t.IsDynamicAction { + continue + } + + filtered = append(filtered, t) + } + + return filtered, nil } diff --git a/graphql2/graphqlapp/destinationvalidation.go b/graphql2/graphqlapp/destinationvalidation.go index b6eaf4ac7a..0b84836125 100644 --- a/graphql2/graphqlapp/destinationvalidation.go +++ b/graphql2/graphqlapp/destinationvalidation.go @@ -27,8 +27,10 @@ var errAlreadySet = errors.New("error already set") // and are only used for signaling to other parts of the system. type errSkipHandler struct{} -var _ graphql.ResponseInterceptor = errSkipHandler{} -var _ graphql.HandlerExtension = errSkipHandler{} +var ( + _ graphql.ResponseInterceptor = errSkipHandler{} + _ graphql.HandlerExtension = errSkipHandler{} +) func (errSkipHandler) ExtensionName() string { return "ErrorSkipHandler" } @@ -133,22 +135,24 @@ func addInputError(ctx context.Context, err error) { func (a *App) ValidateDestination(ctx context.Context, fieldName string, dest *graphql2.DestinationInput) (err error) { cfg := config.FromContext(ctx) switch dest.Type { + case destAlert: + return nil case destTwilioSMS: - phone := dest.FieldValue(fieldPhoneNumber) + phone := dest.Args[fieldPhoneNumber] err := validate.Phone(fieldPhoneNumber, phone) if err != nil { return addDestFieldError(ctx, fieldName, fieldPhoneNumber, err) } return nil case destTwilioVoice: - phone := dest.FieldValue(fieldPhoneNumber) + phone := dest.Args[fieldPhoneNumber] err := validate.Phone(fieldPhoneNumber, phone) if err != nil { return addDestFieldError(ctx, fieldName, fieldPhoneNumber, err) } return nil case destSlackChan: - chanID := dest.FieldValue(fieldSlackChanID) + chanID := dest.Args[fieldSlackChanID] err := a.SlackStore.ValidateChannel(ctx, chanID) if err != nil { return addDestFieldError(ctx, fieldName, fieldSlackChanID, err) @@ -156,34 +160,34 @@ func (a *App) ValidateDestination(ctx context.Context, fieldName string, dest *g return nil case destSlackDM: - userID := dest.FieldValue(fieldSlackUserID) + userID := dest.Args[fieldSlackUserID] if err := a.SlackStore.ValidateUser(ctx, userID); err != nil { return addDestFieldError(ctx, fieldName, fieldSlackUserID, err) } return nil case destSlackUG: - ugID := dest.FieldValue(fieldSlackUGID) + ugID := dest.Args[fieldSlackUGID] userErr := a.SlackStore.ValidateUserGroup(ctx, ugID) - if err != nil { + if userErr != nil { return addDestFieldError(ctx, fieldName, fieldSlackUGID, userErr) } - chanID := dest.FieldValue(fieldSlackChanID) + chanID := dest.Args[fieldSlackChanID] chanErr := a.SlackStore.ValidateChannel(ctx, chanID) - if err != nil { + if chanErr != nil { return addDestFieldError(ctx, fieldName, fieldSlackChanID, chanErr) } return nil case destSMTP: - email := dest.FieldValue(fieldEmailAddress) + email := dest.Args[fieldEmailAddress] err := validate.Email(fieldEmailAddress, email) if err != nil { return addDestFieldError(ctx, fieldName, fieldEmailAddress, err) } return nil case destWebhook: - url := dest.FieldValue(fieldWebhookURL) + url := dest.Args[fieldWebhookURL] err := validate.AbsoluteURL(fieldWebhookURL, url) if err != nil { return addDestFieldError(ctx, fieldName, fieldWebhookURL, err) @@ -193,12 +197,12 @@ func (a *App) ValidateDestination(ctx context.Context, fieldName string, dest *g } return nil case destSchedule: // must be valid UUID and exist - _, err := validate.ParseUUID(fieldScheduleID, dest.FieldValue(fieldScheduleID)) + _, err := validate.ParseUUID(fieldScheduleID, dest.Args[fieldScheduleID]) if err != nil { return addDestFieldError(ctx, fieldName, fieldScheduleID, err) } - _, err = a.ScheduleStore.FindOne(ctx, dest.FieldValue(fieldScheduleID)) + _, err = a.ScheduleStore.FindOne(ctx, dest.Args[fieldScheduleID]) if errors.Is(err, sql.ErrNoRows) { return addDestFieldError(ctx, fieldName, fieldScheduleID, validation.NewGenericError("schedule does not exist")) } @@ -208,7 +212,7 @@ func (a *App) ValidateDestination(ctx context.Context, fieldName string, dest *g return nil case destRotation: // must be valid UUID and exist - rotID := dest.FieldValue(fieldRotationID) + rotID := dest.Args[fieldRotationID] _, err := validate.ParseUUID(fieldRotationID, rotID) if err != nil { return addDestFieldError(ctx, fieldName, fieldRotationID, err) @@ -223,7 +227,7 @@ func (a *App) ValidateDestination(ctx context.Context, fieldName string, dest *g return nil case destUser: // must be valid UUID and exist - userID := dest.FieldValue(fieldUserID) + userID := dest.Args[fieldUserID] uid, err := validate.ParseUUID(fieldUserID, userID) if err != nil { return addDestFieldError(ctx, fieldName, fieldUserID, err) @@ -238,9 +242,14 @@ func (a *App) ValidateDestination(ctx context.Context, fieldName string, dest *g return nil } + message := fmt.Sprintf("unsupported destination type: %s", dest.Type) + if dest.Type == "" { + message = "destination type is required" + } + // unsupported destination type graphql.AddError(ctx, &gqlerror.Error{ - Message: "unsupported destination type", + Message: message, Path: appendPath(ctx, fieldName+".type"), Extensions: map[string]interface{}{ "code": graphql2.ErrorCodeInvalidInputValue, diff --git a/graphql2/graphqlapp/integrationkey.go b/graphql2/graphqlapp/integrationkey.go index 7d71ff65e5..f09d51ea88 100644 --- a/graphql2/graphqlapp/integrationkey.go +++ b/graphql2/graphqlapp/integrationkey.go @@ -10,17 +10,93 @@ import ( "github.com/target/goalert/graphql2" "github.com/target/goalert/integrationkey" "github.com/target/goalert/search" + "github.com/target/goalert/validation" "github.com/target/goalert/validation/validate" ) type IntegrationKey App +type KeyConfig App + func (a *App) IntegrationKey() graphql2.IntegrationKeyResolver { return (*IntegrationKey)(a) } +func (a *App) KeyConfig() graphql2.KeyConfigResolver { return (*KeyConfig)(a) } + +func (k *KeyConfig) OneRule(ctx context.Context, key *graphql2.KeyConfig, ruleID string) (*graphql2.KeyRule, error) { + for _, r := range key.Rules { + if r.ID == ruleID { + return &r, nil + } + } + + return nil, validation.NewFieldError("RuleID", "not found") +} func (q *Query) IntegrationKey(ctx context.Context, id string) (*integrationkey.IntegrationKey, error) { return q.IntKeyStore.FindOne(ctx, id) } +func (q *Query) ActionInputValidate(ctx context.Context, input graphql2.ActionInput) (bool, error) { + err := (*App)(q).ValidateDestination(ctx, "input.dest", input.Dest) + if err != nil { + return false, err + } + + return true, nil +} + +func (m *Mutation) GenerateKeyToken(ctx context.Context, keyID string) (string, error) { + id, err := validate.ParseUUID("ID", keyID) + if err != nil { + return "", err + } + return m.IntKeyStore.GenerateToken(ctx, m.DB, id) +} + +func (m *Mutation) DeleteSecondaryToken(ctx context.Context, keyID string) (bool, error) { + id, err := validate.ParseUUID("ID", keyID) + if err != nil { + return false, err + } + + err = m.IntKeyStore.DeleteSecondaryToken(ctx, m.DB, id) + if err != nil { + return false, err + } + + return true, nil +} + +func (m *Mutation) PromoteSecondaryToken(ctx context.Context, keyID string) (bool, error) { + id, err := validate.ParseUUID("ID", keyID) + if err != nil { + return false, err + } + + err = m.IntKeyStore.PromoteSecondaryToken(ctx, m.DB, id) + if err != nil { + return false, err + } + + return true, nil +} + +func (key *IntegrationKey) TokenInfo(ctx context.Context, raw *integrationkey.IntegrationKey) (*graphql2.TokenInfo, error) { + id, err := validate.ParseUUID("ID", raw.ID) + if err != nil { + return nil, err + } + + prim, sec, err := key.IntKeyStore.TokenHints(ctx, key.DB, id) + if err != nil { + return nil, err + } + + return &graphql2.TokenInfo{ + PrimaryHint: prim, + SecondaryHint: sec, + }, nil +} + func (m *Mutation) UpdateKeyConfig(ctx context.Context, input graphql2.UpdateKeyConfigInput) (bool, error) { err := withContextTx(ctx, m.DB, func(ctx context.Context, tx *sql.Tx) error { id, err := validate.ParseUUID("IntegrationKey.ID", input.KeyID) @@ -33,10 +109,6 @@ func (m *Mutation) UpdateKeyConfig(ctx context.Context, input graphql2.UpdateKey return err } - if input.StopAtFirstRule != nil { - cfg.StopAfterFirstMatchingRule = *input.StopAtFirstRule - } - if input.Rules != nil { cfg.Rules = make([]integrationkey.Rule, 0, len(input.Rules)) for _, r := range input.Rules { @@ -54,10 +126,52 @@ func (m *Mutation) UpdateKeyConfig(ctx context.Context, input graphql2.UpdateKey Description: r.Description, ConditionExpr: r.ConditionExpr, Actions: actionsGQLToGo(r.Actions), + + ContinueAfterMatch: r.ContinueAfterMatch, }) } } + if input.SetRule != nil { + if input.SetRule.ID == nil { + // Since we don't have a rule ID, we're need to create a new rule. + cfg.Rules = append(cfg.Rules, integrationkey.Rule{ + ID: uuid.New(), + Name: input.SetRule.Name, + Description: input.SetRule.Description, + ConditionExpr: input.SetRule.ConditionExpr, + Actions: actionsGQLToGo(input.SetRule.Actions), + }) + } else { + var found bool + for i, r := range cfg.Rules { + if r.ID.String() == *input.SetRule.ID { + cfg.Rules[i] = integrationkey.Rule{ + ID: r.ID, + Name: input.SetRule.Name, + Description: input.SetRule.Description, + ConditionExpr: input.SetRule.ConditionExpr, + Actions: actionsGQLToGo(input.SetRule.Actions), + } + found = true + break + } + } + if !found { + return validation.NewFieldError("SetRule.ID", "not found") + } + } + } + + if input.DeleteRule != nil { + for i, r := range cfg.Rules { + if r.ID.String() == *input.DeleteRule { + cfg.Rules = append(cfg.Rules[:i], cfg.Rules[i+1:]...) + break + } + } + } + if input.DefaultActions != nil { cfg.DefaultActions = actionsGQLToGo(input.DefaultActions) } @@ -106,18 +220,18 @@ func (key *IntegrationKey) Config(ctx context.Context, raw *integrationkey.Integ var rules []graphql2.KeyRule for _, r := range cfg.Rules { rules = append(rules, graphql2.KeyRule{ - ID: r.ID.String(), - Name: r.Name, - Description: r.Description, - ConditionExpr: r.ConditionExpr, - Actions: actionsGoToGQL(r.Actions), + ID: r.ID.String(), + Name: r.Name, + Description: r.Description, + ConditionExpr: r.ConditionExpr, + Actions: actionsGoToGQL(r.Actions), + ContinueAfterMatch: r.ContinueAfterMatch, }) } return &graphql2.KeyConfig{ - StopAtFirstRule: cfg.StopAfterFirstMatchingRule, - Rules: rules, - DefaultActions: actionsGoToGQL(cfg.DefaultActions), + Rules: rules, + DefaultActions: actionsGoToGQL(cfg.DefaultActions), }, nil } @@ -126,8 +240,8 @@ func actionsGQLToGo(a []graphql2.ActionInput) []integrationkey.Action { for _, v := range a { res = append(res, integrationkey.Action{ Type: v.Dest.Type, - StaticParams: fviToMap(v.Dest.Values), - DynamicParams: paramInputToMap(v.Params), + StaticParams: v.Dest.Args, + DynamicParams: v.Params, }) } return res @@ -137,46 +251,8 @@ func actionsGoToGQL(a []integrationkey.Action) []graphql2.Action { res := make([]graphql2.Action, 0, len(a)) for _, v := range a { res = append(res, graphql2.Action{ - Dest: &graphql2.Destination{Type: v.Type, Values: mapToFieldValue(v.StaticParams)}, - Params: mapToParams(v.DynamicParams), - }) - } - return res -} - -func fviToMap(f []graphql2.FieldValueInput) map[string]string { - res := make(map[string]string, len(f)) - for _, v := range f { - res[v.FieldID] = v.Value - } - return res -} - -func paramInputToMap(p []graphql2.DynamicParamInput) map[string]string { - res := make(map[string]string, len(p)) - for _, v := range p { - res[v.ParamID] = v.Expr - } - return res -} - -func mapToFieldValue(m map[string]string) []graphql2.FieldValuePair { - res := make([]graphql2.FieldValuePair, 0, len(m)) - for k, v := range m { - res = append(res, graphql2.FieldValuePair{ - FieldID: k, - Value: v, - }) - } - return res -} - -func mapToParams(m map[string]string) []graphql2.DynamicParam { - res := make([]graphql2.DynamicParam, 0, len(m)) - for k, v := range m { - res = append(res, graphql2.DynamicParam{ - ParamID: k, - Expr: v, + Dest: &graphql2.Destination{Type: v.Type, Args: v.StaticParams}, + Params: v.DynamicParams, }) } return res @@ -204,6 +280,8 @@ func (key *IntegrationKey) Href(ctx context.Context, raw *integrationkey.Integra return "", nil } return "mailto:" + raw.ID + "@" + cfg.EmailIngressDomain(), nil + case integrationkey.TypeUniversal: + return cfg.CallbackURL("/api/v2/uik"), nil } return "", nil diff --git a/graphql2/graphqlapp/queries.sql b/graphql2/graphqlapp/queries.sql index fc701347be..7939a3f21b 100644 --- a/graphql2/graphqlapp/queries.sql +++ b/graphql2/graphqlapp/queries.sql @@ -16,3 +16,18 @@ WHERE OR (om.message_type = 'alert_notification_bundle' AND om.service_id = @service_id::uuid)); +-- name: GQLUserOnCallOverview :many +SELECT + svc.id AS service_id, + svc.name AS service_name, + ep.id AS policy_id, + ep.name AS policy_name, + step.step_number +FROM + ep_step_on_call_users oc + JOIN escalation_policy_steps step ON step.id = oc.ep_step_id + JOIN escalation_policies ep ON ep.id = step.escalation_policy_id + JOIN services svc ON svc.escalation_policy_id = ep.id +WHERE + oc.user_id = $1; + diff --git a/graphql2/graphqlapp/user.go b/graphql2/graphqlapp/user.go index 2764dc61f1..af40f71bf4 100644 --- a/graphql2/graphqlapp/user.go +++ b/graphql2/graphqlapp/user.go @@ -3,10 +3,12 @@ package graphqlapp import ( context "context" "database/sql" + "sort" "github.com/google/uuid" "github.com/target/goalert/auth/basic" "github.com/target/goalert/calsub" + "github.com/target/goalert/gadb" "github.com/target/goalert/schedule" "github.com/target/goalert/validation" "github.com/target/goalert/validation/validate" @@ -28,6 +30,53 @@ type ( func (a *App) User() graphql2.UserResolver { return (*User)(a) } +func (a *User) OnCallOverview(ctx context.Context, obj *user.User) (*graphql2.OnCallOverview, error) { + err := permission.LimitCheckAny(ctx, permission.User) + if err != nil { + return nil, err + } + id, err := validate.ParseUUID("UserID", obj.ID) + if err != nil { + return nil, err + } + + data, err := gadb.New(a.DB).GQLUserOnCallOverview(ctx, id) + if errors.Is(err, sql.ErrNoRows) { + return &graphql2.OnCallOverview{ServiceAssignments: []graphql2.OnCallServiceAssignment{}}, nil + } + if err != nil { + return nil, err + } + + svcCount := make(map[uuid.UUID]struct{}) + var overview graphql2.OnCallOverview + for _, svc := range data { + svcCount[svc.ServiceID] = struct{}{} + overview.ServiceAssignments = append(overview.ServiceAssignments, graphql2.OnCallServiceAssignment{ + StepNumber: int(svc.StepNumber), + EscalationPolicyID: svc.PolicyID.String(), + EscalationPolicyName: svc.PolicyName, + ServiceID: svc.ServiceID.String(), + ServiceName: svc.ServiceName, + }) + } + overview.ServiceCount = len(svcCount) + + // sort by service name, then step number + sort.Slice(overview.ServiceAssignments, func(i, j int) bool { + a := overview.ServiceAssignments[i] + b := overview.ServiceAssignments[j] + + if a.ServiceName != b.ServiceName { + return a.ServiceName < b.ServiceName + } + + return a.StepNumber < b.StepNumber + }) + + return &overview, nil +} + func (a *User) Sessions(ctx context.Context, obj *user.User) ([]graphql2.UserSession, error) { sess, err := a.AuthHandler.FindAllUserSessions(ctx, obj.ID) if err != nil { @@ -36,7 +85,6 @@ func (a *User) Sessions(ctx context.Context, obj *user.User) ([]graphql2.UserSes out := make([]graphql2.UserSession, len(sess)) for i, s := range sess { - out[i] = graphql2.UserSession{ ID: s.ID, UserAgent: s.UserAgent, @@ -48,6 +96,7 @@ func (a *User) Sessions(ctx context.Context, obj *user.User) ([]graphql2.UserSes return out, nil } + func isCurrentSession(ctx context.Context, sessID string) bool { src := permission.Source(ctx) if src == nil { diff --git a/graphql2/models_gen.go b/graphql2/models_gen.go index d2b3285339..ac67ff160e 100644 --- a/graphql2/models_gen.go +++ b/graphql2/models_gen.go @@ -33,13 +33,13 @@ type InlineDisplayInfo interface { } type Action struct { - Dest *Destination `json:"dest"` - Params []DynamicParam `json:"params"` + Dest *Destination `json:"dest"` + Params map[string]string `json:"params"` } type ActionInput struct { - Dest *DestinationInput `json:"dest"` - Params []DynamicParamInput `json:"params"` + Dest *DestinationInput `json:"dest"` + Params map[string]string `json:"params"` } type AlertConnection struct { @@ -357,6 +357,7 @@ type DebugSendSMSInput struct { type Destination struct { Type string `json:"type"` Values []FieldValuePair `json:"values"` + Args map[string]string `json:"args"` DisplayInfo InlineDisplayInfo `json:"displayInfo"` } @@ -428,7 +429,8 @@ type DestinationFieldValidateInput struct { type DestinationInput struct { Type string `json:"type"` - Values []FieldValueInput `json:"values"` + Values []FieldValueInput `json:"values,omitempty"` + Args map[string]string `json:"args,omitempty"` } type DestinationTypeInfo struct { @@ -441,6 +443,8 @@ type DestinationTypeInfo struct { // if false, the destination type is disabled and cannot be used Enabled bool `json:"enabled"` RequiredFields []DestinationFieldConfig `json:"requiredFields"` + // expr parameters that can be used for this destination type + DynamicParams []DynamicParamConfig `json:"dynamicParams"` // disclaimer text to display when a user is selecting this destination type for a contact method UserDisclaimer string `json:"userDisclaimer"` // this destination type can be used as a user contact method @@ -449,20 +453,23 @@ type DestinationTypeInfo struct { IsEPTarget bool `json:"isEPTarget"` // this destination type can be used for schedule on-call notifications IsSchedOnCallNotify bool `json:"isSchedOnCallNotify"` + // this destination type can be used for dynamic actions + IsDynamicAction bool `json:"isDynamicAction"` // if true, the destination type supports status updates SupportsStatusUpdates bool `json:"supportsStatusUpdates"` // if true, the destination type requires status updates to be enabled StatusUpdatesRequired bool `json:"statusUpdatesRequired"` } -type DynamicParam struct { - ParamID string `json:"paramID"` - Expr string `json:"expr"` -} - -type DynamicParamInput struct { +type DynamicParamConfig struct { + // unique ID for the input field ParamID string `json:"paramID"` - Expr string `json:"expr"` + // user-friendly label (should be singular) + Label string `json:"label"` + // user-friendly helper text for input fields (i.e., "Enter a phone number") + Hint string `json:"hint"` + // URL to link to for more information about the destination type + HintURL string `json:"hintURL"` } type EscalationPolicyConnection struct { @@ -561,9 +568,9 @@ type IntegrationKeyTypeInfo struct { } type KeyConfig struct { - // Stop evaluating rules after the first rule that matches. - StopAtFirstRule bool `json:"stopAtFirstRule"` - Rules []KeyRule `json:"rules"` + Rules []KeyRule `json:"rules"` + // Get a single rule by ID. + OneRule *KeyRule `json:"oneRule,omitempty"` // defaultAction is the action to take if no rules match the request. DefaultActions []Action `json:"defaultActions"` } @@ -575,6 +582,8 @@ type KeyRule struct { // An expression that must evaluate to true for the rule to match. ConditionExpr string `json:"conditionExpr"` Actions []Action `json:"actions"` + // Continue evaluating rules after this rule matches. + ContinueAfterMatch bool `json:"continueAfterMatch"` } type KeyRuleInput struct { @@ -585,6 +594,10 @@ type KeyRuleInput struct { // An expression that must evaluate to true for the rule to match. ConditionExpr string `json:"conditionExpr"` Actions []ActionInput `json:"actions"` + // Continue evaluating rules after this rule matches. + // + // If this is set to false (default), no further rules will be evaluated after this rule matches. + ContinueAfterMatch bool `json:"continueAfterMatch"` } type LabelConnection struct { @@ -645,6 +658,20 @@ type NotificationState struct { FormattedSrcValue string `json:"formattedSrcValue"` } +type OnCallOverview struct { + ServiceCount int `json:"serviceCount"` + ServiceAssignments []OnCallServiceAssignment `json:"serviceAssignments"` +} + +type OnCallServiceAssignment struct { + // stepNumber is the escalation step this assignment is from (beginning with 0). + StepNumber int `json:"stepNumber"` + EscalationPolicyID string `json:"escalationPolicyID"` + EscalationPolicyName string `json:"escalationPolicyName"` + ServiceID string `json:"serviceID"` + ServiceName string `json:"serviceName"` +} + type PageInfo struct { EndCursor *string `json:"endCursor,omitempty"` HasNextPage bool `json:"hasNextPage"` @@ -852,6 +879,13 @@ type TimeZoneSearchOptions struct { Omit []string `json:"omit,omitempty"` } +type TokenInfo struct { + // primaryHint is a hint for the primary token. It is empty if the primary token is not set. + PrimaryHint string `json:"primaryHint"` + // secondaryHint is a hint for the secondary token. It is empty if the secondary token is not set. + SecondaryHint string `json:"secondaryHint"` +} + type UpdateAlertsByServiceInput struct { ServiceID string `json:"serviceID"` NewStatus AlertStatus `json:"newStatus"` @@ -898,10 +932,12 @@ type UpdateHeartbeatMonitorInput struct { } type UpdateKeyConfigInput struct { - KeyID string `json:"keyID"` - // Stop evaluating rules after the first rule that matches. - StopAtFirstRule *bool `json:"stopAtFirstRule,omitempty"` - Rules []KeyRuleInput `json:"rules,omitempty"` + KeyID string `json:"keyID"` + Rules []KeyRuleInput `json:"rules,omitempty"` + // setRule allows you to set a single rule. If ID is provided, the rule with that ID will be updated. If ID is not provided, a new rule will be created and appended to the list of rules. + SetRule *KeyRuleInput `json:"setRule,omitempty"` + // deleteRule allows you to delete a single rule by ID. + DeleteRule *string `json:"deleteRule,omitempty"` // defaultAction is the action to take if no rules match the request. DefaultActions []ActionInput `json:"defaultActions,omitempty"` } @@ -1158,6 +1194,12 @@ const ( // // A separate error will be returned for each invalid field. ErrorCodeInvalidDestFieldValue ErrorCode = "INVALID_DEST_FIELD_VALUE" + // The `path` field contains the exact path to the map that is invalid. + // + // The `extensions.key` field contains the key of the value that is invalid. + // + // A separate error will be returned for each invalid value. + ErrorCodeInvalidMapFieldValue ErrorCode = "INVALID_MAP_FIELD_VALUE" // The expr expression is too complex to be converted to a Condition. ErrorCodeExprTooComplex ErrorCode = "EXPR_TOO_COMPLEX" ) @@ -1165,12 +1207,13 @@ const ( var AllErrorCode = []ErrorCode{ ErrorCodeInvalidInputValue, ErrorCodeInvalidDestFieldValue, + ErrorCodeInvalidMapFieldValue, ErrorCodeExprTooComplex, } func (e ErrorCode) IsValid() bool { switch e { - case ErrorCodeInvalidInputValue, ErrorCodeInvalidDestFieldValue, ErrorCodeExprTooComplex: + case ErrorCodeInvalidInputValue, ErrorCodeInvalidDestFieldValue, ErrorCodeInvalidMapFieldValue, ErrorCodeExprTooComplex: return true } return false diff --git a/graphql2/schema.graphql b/graphql2/schema.graphql index c105149815..66981f1348 100644 --- a/graphql2/schema.graphql +++ b/graphql2/schema.graphql @@ -1178,6 +1178,9 @@ type User { sessions: [UserSession!]! onCallSteps: [EscalationPolicyStep!]! + @deprecated(reason: "Use `onCallOverview` instead.") + + onCallOverview: OnCallOverview! isFavorite: Boolean! @@ -1200,6 +1203,24 @@ type UserNotificationRule { contactMethod: UserContactMethod } +type OnCallOverview { + serviceCount: Int! + serviceAssignments: [OnCallServiceAssignment!]! +} + +type OnCallServiceAssignment { + """ + stepNumber is the escalation step this assignment is from (beginning with 0). + """ + stepNumber: Int! + + escalationPolicyID: ID! + escalationPolicyName: String! + + serviceID: ID! + serviceName: String! +} + enum ContactMethodType { SMS VOICE @@ -1241,7 +1262,7 @@ input CreateUserContactMethodInput { type: ContactMethodType - dest: DestinationInput @experimental(flagName: "dest-types") + dest: DestinationInput name: String! diff --git a/graphql2/stringmap.go b/graphql2/stringmap.go new file mode 100644 index 0000000000..c292ad9d02 --- /dev/null +++ b/graphql2/stringmap.go @@ -0,0 +1,41 @@ +package graphql2 + +import ( + "fmt" + + graphql "github.com/99designs/gqlgen/graphql" + "github.com/target/goalert/validation" +) + +// MapValueError is an error type for map values. +type MapValueError struct { + Key string + Err error +} + +func (m MapValueError) Error() string { + return fmt.Sprintf("field %s: %s", m.Key, m.Err) +} + +func (MapValueError) ClientError() bool { return true } + +func UnmarshalStringMap(v interface{}) (map[string]string, error) { + m, ok := v.(map[string]any) + if !ok { + return nil, validation.NewGenericError("must be a map") + } + res := make(map[string]string, len(m)) + for k, v := range m { + str, err := graphql.UnmarshalString(v) + if err != nil { + return nil, MapValueError{Key: k, Err: err} + } + res[k] = str + } + + return res, nil +} + +func MarshalStringMap(v map[string]string) graphql.Marshaler { + return graphql.MarshalAny(v) +} diff --git a/integrationkey/config.go b/integrationkey/config.go index f7cb443809..e5aade1c37 100644 --- a/integrationkey/config.go +++ b/integrationkey/config.go @@ -11,6 +11,13 @@ import ( "github.com/target/goalert/gadb" "github.com/target/goalert/permission" "github.com/target/goalert/validation" + "github.com/target/goalert/validation/validate" +) + +const ( + MaxRules = 100 + MaxActions = 10 + MaxParams = 10 ) type dbConfig struct { @@ -35,6 +42,8 @@ type Rule struct { Description string ConditionExpr string Actions []Action + + ContinueAfterMatch bool } // An Action is a single action to take if a rule matches. @@ -50,8 +59,64 @@ type Action struct { DynamicParams map[string]string } +func (cfg Config) Validate() error { + err := validate.Many( + validate.Len("Rules", cfg.Rules, 0, MaxRules), + validate.Len("DefaultActions", cfg.DefaultActions, 0, MaxActions), + ) + if err != nil { + return err + } + + for i, r := range cfg.Rules { + field := fmt.Sprintf("Rules[%d]", i) + err := validate.Many( + validate.Name(field+".Name", r.Name), + validate.Text(field+".Description", r.Description, 0, 255), // these are arbitrary and will likely change as the feature is developed + validate.Text(field+".ConditionExpr", r.ConditionExpr, 1, 1024), + validate.Len(field+".Actions", r.Actions, 0, MaxActions), + ) + if err != nil { + return err + } + + for j, a := range r.Actions { + field := fmt.Sprintf("Rules[%d].Actions[%d]", i, j) + err := validate.Many( + validate.MapLen(field+".StaticParams", a.StaticParams, 0, MaxParams), + validate.MapLen(field+".DynamicParams", a.DynamicParams, 0, MaxParams), + ) + if err != nil { + return err + } + } + } + + for i, a := range cfg.DefaultActions { + field := fmt.Sprintf("DefaultActions[%d]", i) + err := validate.Many( + validate.MapLen(field+".StaticParams", a.StaticParams, 0, MaxParams), + validate.MapLen(field+".DynamicParams", a.DynamicParams, 0, MaxParams), + ) + if err != nil { + return err + } + } + + data, err := json.Marshal(cfg) + if err != nil { + return err + } + + if len(data) > 64*1024 { + return validation.NewFieldError("Config", "must be less than 64KiB in total") + } + + return nil +} + func (s *Store) Config(ctx context.Context, db gadb.DBTX, keyID uuid.UUID) (*Config, error) { - err := permission.LimitCheckAny(ctx, permission.User) + err := permission.LimitCheckAny(ctx, permission.User, permission.Service) if err != nil { return nil, err } @@ -82,6 +147,13 @@ func (s *Store) SetConfig(ctx context.Context, db gadb.DBTX, keyID uuid.UUID, cf return err } + if cfg != nil { + err := cfg.Validate() + if err != nil { + return err + } + } + gdb := gadb.New(db) keyType, err := gdb.IntKeyGetType(ctx, keyID) if err != nil { diff --git a/integrationkey/queries.sql b/integrationkey/queries.sql index 6d1d3f3d6c..6d29d84a07 100644 --- a/integrationkey/queries.sql +++ b/integrationkey/queries.sql @@ -67,3 +67,71 @@ FROM WHERE id = $1; +-- name: IntKeyPromoteSecondary :one +UPDATE + uik_config +SET + primary_token = secondary_token, + primary_token_hint = secondary_token_hint, + secondary_token = NULL, + secondary_token_hint = NULL +WHERE + id = $1 +RETURNING + primary_token_hint; + +-- name: IntKeyTokenHints :one +SELECT + primary_token_hint, + secondary_token_hint +FROM + uik_config +WHERE + id = $1; + +-- name: IntKeySetPrimaryToken :one +UPDATE + uik_config +SET + primary_token = $2, + primary_token_hint = $3 +WHERE + id = $1 + AND primary_token IS NULL +RETURNING + id; + +-- name: IntKeySetSecondaryToken :one +UPDATE + uik_config +SET + secondary_token = $2, + secondary_token_hint = $3 +WHERE + id = $1 + AND secondary_token IS NULL + AND primary_token IS NOT NULL +RETURNING + id; + +-- name: IntKeyUIKValidateService :one +SELECT + k.service_id +FROM + uik_config c + JOIN integration_keys k ON k.id = c.id +WHERE + c.id = sqlc.arg(key_id) + AND k.type = 'universal' + AND (c.primary_token = sqlc.arg(token_id) + OR c.secondary_token = sqlc.arg(token_id)); + +-- name: IntKeyDeleteSecondaryToken :exec +UPDATE + uik_config +SET + secondary_token = NULL, + secondary_token_hint = NULL +WHERE + id = $1; + diff --git a/integrationkey/store.go b/integrationkey/store.go index dcd0b532af..e54e797ed0 100644 --- a/integrationkey/store.go +++ b/integrationkey/store.go @@ -7,6 +7,7 @@ import ( "github.com/target/goalert/auth/authtoken" "github.com/target/goalert/expflag" "github.com/target/goalert/gadb" + "github.com/target/goalert/keyring" "github.com/target/goalert/permission" "github.com/target/goalert/validation" "github.com/target/goalert/validation/validate" @@ -17,10 +18,12 @@ import ( type Store struct { db *sql.DB + + keys keyring.Keyring } -func NewStore(ctx context.Context, db *sql.DB) *Store { - return &Store{db: db} +func NewStore(ctx context.Context, db *sql.DB, keys keyring.Keyring) *Store { + return &Store{db: db, keys: keys} } func (s *Store) Authorize(ctx context.Context, tok authtoken.Token, t Type) (context.Context, error) { @@ -104,6 +107,15 @@ func (s *Store) Create(ctx context.Context, dbtx gadb.DBTX, i *IntegrationKey) ( if err != nil { return nil, err } + + if n.Type == TypeUniversal { + // ensure a config exists + err = s.SetConfig(ctx, dbtx, keyUUID, &Config{}) + if err != nil { + return nil, err + } + } + return n, nil } diff --git a/integrationkey/uik.go b/integrationkey/uik.go new file mode 100644 index 0000000000..ee6a6e93ee --- /dev/null +++ b/integrationkey/uik.go @@ -0,0 +1,200 @@ +package integrationkey + +import ( + "context" + "database/sql" + "errors" + "time" + + "github.com/golang-jwt/jwt/v5" + "github.com/google/uuid" + "github.com/target/goalert/expflag" + "github.com/target/goalert/gadb" + "github.com/target/goalert/permission" + "github.com/target/goalert/util/log" + + "github.com/target/goalert/validation" + "github.com/target/goalert/validation/validate" +) + +// Issuer is the JWT issuer for UIK API keys. +const Issuer = "goalert" + +// Audience is the JWT audience for UIK API keys. +const Audience = "uik-key-v1" + +func newClaims(keyID, tokenID uuid.UUID) jwt.Claims { + n := time.Now() + return jwt.RegisteredClaims{ + ID: tokenID.String(), + Subject: keyID.String(), + IssuedAt: jwt.NewNumericDate(n), + NotBefore: jwt.NewNumericDate(n.Add(-time.Minute)), + Issuer: Issuer, + Audience: []string{Audience}, + } +} + +type ActionResult struct { + DestType string + Values map[string]string + Params map[string]string +} + +func (s *Store) AuthorizeUIK(ctx context.Context, tokStr string) (context.Context, error) { + if !expflag.ContextHas(ctx, expflag.UnivKeys) { + return ctx, permission.Unauthorized() + } + + var claims jwt.RegisteredClaims + _, err := s.keys.VerifyJWT(tokStr, &claims, Issuer, Audience) + if err != nil { + return ctx, permission.Unauthorized() + } + + keyID, err := uuid.Parse(claims.Subject) + if err != nil { + log.Logf(ctx, "apikey: invalid subject: %v", err) + return ctx, permission.Unauthorized() + } + tokID, err := uuid.Parse(claims.ID) + if err != nil { + log.Logf(ctx, "apikey: invalid token ID: %v", err) + return ctx, permission.Unauthorized() + } + + serviceID, err := gadb.New(s.db).IntKeyUIKValidateService(ctx, gadb.IntKeyUIKValidateServiceParams{ + KeyID: keyID, + TokenID: uuid.NullUUID{UUID: tokID, Valid: true}, + }) + if errors.Is(err, sql.ErrNoRows) { + return ctx, permission.Unauthorized() + } + if err != nil { + return ctx, err + } + + ctx = permission.ServiceSourceContext(ctx, serviceID.String(), &permission.SourceInfo{ + Type: permission.SourceTypeUIK, + ID: keyID.String(), + }) + + return ctx, nil +} + +func (s *Store) TokenHints(ctx context.Context, db gadb.DBTX, id uuid.UUID) (primary, secondary string, err error) { + err = permission.LimitCheckAny(ctx, permission.User) + if err != nil { + return "", "", err + } + + row, err := gadb.New(s.db).IntKeyTokenHints(ctx, id) + if errors.Is(err, sql.ErrNoRows) { + return "", "", nil + } + if err != nil { + return "", "", err + } + + return row.PrimaryTokenHint.String, row.SecondaryTokenHint.String, nil +} + +func (s *Store) GenerateToken(ctx context.Context, db gadb.DBTX, id uuid.UUID) (string, error) { + err := permission.LimitCheckAny(ctx, permission.User) + if err != nil { + return "", err + } + + key, err := gadb.New(db).IntKeyFindOne(ctx, id) + if err != nil { + return "", err + } + if key.Type != gadb.EnumIntegrationKeysType(TypeUniversal) { + return "", validation.NewFieldError("ID", "key is not a universal key") + } + + tokID := uuid.New() + tokStr, err := s.keys.SignJWT(newClaims(id, tokID)) + if err != nil { + return "", err + } + + hint := tokStr[:2] + "..." + tokStr[len(tokStr)-4:] + + err = s.setToken(ctx, db, id, tokID, hint) + if err != nil { + return "", err + } + + return tokStr, nil +} + +func (s *Store) setToken(ctx context.Context, db gadb.DBTX, keyID, tokenID uuid.UUID, tokenHint string) error { + err := permission.LimitCheckAny(ctx, permission.User) + if err != nil { + return err + } + + if err := validate.ASCII("Token Hint", tokenHint, 1, 32); err != nil { + // not user specified, so return a generic error + return errors.New("invalid token hint") + } + + gdb := gadb.New(db) + + _, err = gdb.IntKeySetSecondaryToken(ctx, gadb.IntKeySetSecondaryTokenParams{ + ID: keyID, + SecondaryToken: uuid.NullUUID{UUID: tokenID, Valid: true}, + SecondaryTokenHint: sql.NullString{String: tokenHint, Valid: true}, + }) + if errors.Is(err, sql.ErrNoRows) { + // it's possible there was never a primary token set + _, err = gdb.IntKeySetPrimaryToken(ctx, gadb.IntKeySetPrimaryTokenParams{ + ID: keyID, + PrimaryToken: uuid.NullUUID{UUID: tokenID, Valid: true}, + PrimaryTokenHint: sql.NullString{String: tokenHint, Valid: true}, + }) + if errors.Is(err, sql.ErrNoRows) { + return validation.NewGenericError("key not found, or already has primary and secondary tokens") + } + + // Note: A possible race condition here is if multiple requests are made to set the primary token at the same time. In that case, the first request will win and the others will fail with a unique constraint violation. This is acceptable because the primary token is only set once, and only rotated thereafter. + } + if err != nil { + return err + } + + return nil +} + +func (s *Store) PromoteSecondaryToken(ctx context.Context, db gadb.DBTX, id uuid.UUID) error { + err := permission.LimitCheckAny(ctx, permission.User) + if err != nil { + return err + } + + hint, err := gadb.New(db).IntKeyPromoteSecondary(ctx, id) + if err != nil { + return err + } + + if !hint.Valid { + return validation.NewGenericError("no secondary token to promote") + } + + return nil +} + +func (s *Store) DeleteSecondaryToken(ctx context.Context, db gadb.DBTX, id uuid.UUID) error { + err := permission.LimitCheckAny(ctx, permission.User) + if err != nil { + return err + } + + err = gadb.New(db).IntKeyDeleteSecondaryToken(ctx, id) + if err != nil { + return err + } + + return nil +} diff --git a/integrationkey/uik/handler.go b/integrationkey/uik/handler.go new file mode 100644 index 0000000000..f4a8d4b6ce --- /dev/null +++ b/integrationkey/uik/handler.go @@ -0,0 +1,170 @@ +package uik + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/expr-lang/expr" + "github.com/google/uuid" + "github.com/target/goalert/alert" + "github.com/target/goalert/expflag" + "github.com/target/goalert/gadb" + "github.com/target/goalert/integrationkey" + "github.com/target/goalert/permission" + "github.com/target/goalert/util/errutil" + "github.com/target/goalert/util/log" + "github.com/target/goalert/validation" +) + +type Handler struct { + intStore *integrationkey.Store + alertStore *alert.Store + db gadb.DBTX +} + +func NewHandler(db gadb.DBTX, intStore *integrationkey.Store, aStore *alert.Store) *Handler { + return &Handler{intStore: intStore, db: db, alertStore: aStore} +} + +func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + ctx := req.Context() + if !expflag.ContextHas(ctx, expflag.UnivKeys) { + errutil.HTTPError(ctx, w, validation.NewGenericError("universal keys are disabled")) + return + } + + err := permission.LimitCheckAny(req.Context(), permission.Service) + if errutil.HTTPError(ctx, w, err) { + return + } + src := permission.Source(ctx) + if src.Type != permission.SourceTypeUIK { + // we don't want to allow regular API keys to be used here + errutil.HTTPError(ctx, w, permission.Unauthorized()) + return + } + + keyID, err := uuid.Parse(src.ID) + if errutil.HTTPError(ctx, w, err) { + return + } + data, err := io.ReadAll(req.Body) + if errutil.HTTPError(ctx, w, err) { + return + } + var body any + err = json.Unmarshal(data, &body) + if errutil.HTTPError(ctx, w, validation.WrapError(err)) { + return + } + + cfg, err := h.intStore.Config(ctx, h.db, keyID) + if errutil.HTTPError(ctx, w, err) { + return + } + + env := map[string]any{ + "sprintf": fmt.Sprintf, + "req": map[string]any{ + "body": body, + }, + } + + // We need to track if any rule matched, so we can apply default actions if none did. + var anyMatched bool + var results []integrationkey.ActionResult + for _, rule := range cfg.Rules { + result, err := expr.Eval("string("+rule.ConditionExpr+")", env) + if errutil.HTTPError(ctx, w, validation.WrapError(err)) { + return + } + r, ok := result.(string) + if !ok { + errutil.HTTPError(ctx, w, validation.NewGenericError("condition expression must return a boolean")) + return + } + anyMatched = anyMatched || r == "true" + if r != "true" { + continue + } + + for _, action := range rule.Actions { + res := integrationkey.ActionResult{ + DestType: action.Type, + Values: action.StaticParams, + Params: make(map[string]string, len(action.DynamicParams)), + } + + for name, exprStr := range action.DynamicParams { + val, err := expr.Eval("string("+exprStr+")", env) + if errutil.HTTPError(ctx, w, validation.WrapError(err)) { + return + } + if _, ok := val.(string); !ok { + errutil.HTTPError(ctx, w, validation.NewGenericError("dynamic param expressions must return a string")) + return + } + res.Params[name] = val.(string) + } + results = append(results, res) + } + + if !rule.ContinueAfterMatch { + break + } + } + + if !anyMatched { + // Default actions need to be applied if no rules matched (or if there are no rules at all). + for _, action := range cfg.DefaultActions { + res := integrationkey.ActionResult{ + DestType: action.Type, + Values: action.StaticParams, + Params: make(map[string]string, len(action.DynamicParams)), + } + + for name, exprStr := range action.DynamicParams { + val, err := expr.Eval("string("+exprStr+")", env) + if errutil.HTTPError(ctx, w, validation.WrapError(err)) { + return + } + if _, ok := val.(string); !ok { + errutil.HTTPError(ctx, w, validation.NewGenericError("dynamic param expressions must return a string")) + return + } + res.Params[name] = val.(string) + } + results = append(results, res) + } + } + + log.Logf(ctx, "uik: action result: %#v", results) + + for _, res := range results { + switch res.DestType { + case "builtin-alert": + status := alert.StatusTriggered + if res.Params["close"] == "true" { + status = alert.StatusClosed + } + + _, _, err = h.alertStore.CreateOrUpdate(ctx, &alert.Alert{ + ServiceID: permission.ServiceID(ctx), + Summary: res.Params["summary"], + Details: res.Params["details"], + Source: alert.SourceUniversal, + Status: status, + }) + if errutil.HTTPError(ctx, w, err) { + return + } + default: + errutil.HTTPError(ctx, w, validation.NewFieldError("action", "unknown action type")) + return + } + } + + w.WriteHeader(http.StatusNoContent) +} diff --git a/migrate/migrations/20240514135227-uik-tokens.sql b/migrate/migrations/20240514135227-uik-tokens.sql new file mode 100644 index 0000000000..8527927803 --- /dev/null +++ b/migrate/migrations/20240514135227-uik-tokens.sql @@ -0,0 +1,14 @@ +-- +migrate Up +ALTER TABLE uik_config + ADD COLUMN primary_token uuid UNIQUE, + ADD COLUMN primary_token_hint text, + ADD COLUMN secondary_token uuid UNIQUE, + ADD COLUMN secondary_token_hint text; + +-- +migrate Down +ALTER TABLE uik_config + DROP COLUMN primary_token, + DROP COLUMN primary_token_hint, + DROP COLUMN secondary_token, + DROP COLUMN secondary_token_hint; + diff --git a/migrate/migrations/20240628135216-dedup-notif-channels.sql b/migrate/migrations/20240628135216-dedup-notif-channels.sql new file mode 100644 index 0000000000..2a2227f423 --- /dev/null +++ b/migrate/migrations/20240628135216-dedup-notif-channels.sql @@ -0,0 +1,95 @@ +-- +migrate Up +CREATE TEMPORARY TABLE notification_channel_duplicates( + old_id uuid PRIMARY KEY, + new_id uuid NOT NULL +); + +LOCK notification_channels; + +INSERT INTO notification_channel_duplicates(old_id, new_id) +SELECT + nc.id, +( + SELECT + id + FROM + notification_channels sub + WHERE + sub.type = nc.type + AND sub.value = nc.value + ORDER BY + sub.created_at + LIMIT 1) +FROM + notification_channels nc +WHERE ( + SELECT + count(*) + FROM + notification_channels sub + WHERE + sub.type = nc.type + AND sub.value = nc.value) > 1; + +-- remove any non-duplicates +DELETE FROM notification_channel_duplicates +WHERE old_id = new_id; + +-- update alert_logs +UPDATE + alert_logs +SET + sub_channel_id = dup.new_id +FROM + notification_channel_duplicates dup +WHERE + sub_channel_id = dup.old_id; + +-- update ep actions, status updates, and outgoing_messages +-- ensure that no updates/inserts can be made until we are done +LOCK TABLE escalation_policy_actions IN share ROW exclusive mode; + +UPDATE + escalation_policy_actions +SET + channel_id = dup.new_id +FROM + notification_channel_duplicates dup +WHERE + channel_id = dup.old_id; + +LOCK TABLE alert_status_subscriptions IN share ROW exclusive mode; + +UPDATE + alert_status_subscriptions +SET + channel_id = dup.new_id +FROM + notification_channel_duplicates dup +WHERE + channel_id = dup.old_id; + +LOCK TABLE outgoing_messages IN share ROW exclusive mode; + +UPDATE + outgoing_messages +SET + channel_id = dup.new_id +FROM + notification_channel_duplicates dup +WHERE + channel_id = dup.old_id; + +-- delete duplicates +DELETE FROM notification_channels USING notification_channel_duplicates +WHERE id = old_id; + +ALTER TABLE notification_channels + ADD CONSTRAINT nc_unique_type_value UNIQUE (type, value); + +DROP TABLE notification_channel_duplicates; + +-- +migrate Down +ALTER TABLE notification_channels + DROP CONSTRAINT nc_unique_type_value; + diff --git a/migrate/migrations/20240628135304-dest-enum.sql b/migrate/migrations/20240628135304-dest-enum.sql new file mode 100644 index 0000000000..c7b0b41d07 --- /dev/null +++ b/migrate/migrations/20240628135304-dest-enum.sql @@ -0,0 +1,8 @@ +-- +migrate Up notransaction +ALTER TYPE enum_user_contact_method_type + ADD VALUE IF NOT EXISTS 'DEST'; + +ALTER TYPE enum_notif_channel_type + ADD VALUE IF NOT EXISTS 'DEST'; + +-- +migrate Down diff --git a/migrate/migrations/20240628136011-cm-dest.sql b/migrate/migrations/20240628136011-cm-dest.sql new file mode 100644 index 0000000000..c707e45dcf --- /dev/null +++ b/migrate/migrations/20240628136011-cm-dest.sql @@ -0,0 +1,123 @@ +-- +migrate Up +-- +migrate StatementBegin +CREATE OR REPLACE FUNCTION cm_type_val_to_dest(typeName enum_user_contact_method_type, value text) + RETURNS jsonb + AS $$ +BEGIN + IF typeName = 'EMAIL' THEN + RETURN jsonb_build_object('Type', 'builtin-smtp-email', 'Args', jsonb_build_object('email-address', value)); + ELSIF typeName = 'VOICE' THEN + RETURN jsonb_build_object('Type', 'builtin-twilio-voice', 'Args', jsonb_build_object('phone-number', value)); + ELSIF typeName = 'SMS' THEN + RETURN jsonb_build_object('Type', 'builtin-twilio-sms', 'Args', jsonb_build_object('phone-number', value)); + ELSIF typeName = 'WEBHOOK' THEN + RETURN jsonb_build_object('Type', 'builtin-webhook', 'Args', jsonb_build_object('webhook-url', value)); + ELSIF typeName = 'SLACK_DM' THEN + RETURN jsonb_build_object('Type', 'builtin-slack-dm', 'Args', jsonb_build_object('slack-user-id', value)); + ELSE + -- throw an error + RAISE EXCEPTION 'Unknown contact method type: %', typeName; + END IF; +END; +$$ +LANGUAGE plpgsql; + +-- +migrate StatementEnd +ALTER TABLE user_contact_methods + ADD COLUMN dest jsonb UNIQUE; + +UPDATE + user_contact_methods +SET + dest = cm_type_val_to_dest(type, value); + +ALTER TABLE user_contact_methods + ALTER COLUMN dest SET NOT NULL; + +-- +migrate StatementBegin +CREATE OR REPLACE FUNCTION fn_cm_set_dest_on_insert() + RETURNS TRIGGER + AS $$ +BEGIN + NEW.dest = cm_type_val_to_dest(NEW.type, NEW.value); + RETURN new; +END; +$$ +LANGUAGE plpgsql; + +-- +migrate StatementEnd +CREATE TRIGGER trg_10_cm_set_dest_on_insert + BEFORE INSERT ON user_contact_methods + FOR EACH ROW + WHEN(NEW.dest IS NULL) + EXECUTE FUNCTION fn_cm_set_dest_on_insert(); + +CREATE TRIGGER trg_10_cm_set_dest_on_update + BEFORE UPDATE ON user_contact_methods + FOR EACH ROW + WHEN(NEW.dest = OLD.dest) + EXECUTE FUNCTION fn_cm_set_dest_on_insert(); + +-- +migrate StatementBegin +CREATE OR REPLACE FUNCTION fn_cm_compat_set_type_val_on_insert() + RETURNS TRIGGER + AS $$ +BEGIN + IF NEW.dest ->> 'Type' = 'builtin-smtp-email' THEN + NEW.type = 'EMAIL'; + NEW.value = NEW.dest -> 'Args' ->> 'email-address'; + ELSIF NEW.dest ->> 'Type' = 'builtin-twilio-voice' THEN + NEW.type = 'VOICE'; + NEW.value = NEW.dest -> 'Args' ->> 'phone-number'; + ELSIF NEW.dest ->> 'Type' = 'builtin-twilio-sms' THEN + NEW.type = 'SMS'; + NEW.value = NEW.dest -> 'Args' ->> 'phone-number'; + ELSIF NEW.dest ->> 'Type' = 'builtin-webhook' THEN + NEW.type = 'WEBHOOK'; + NEW.value = NEW.dest -> 'Args' ->> 'webhook-url'; + ELSIF NEW.dest ->> 'Type' = 'builtin-slack-dm' THEN + NEW.type = 'SLACK_DM'; + NEW.value = NEW.dest -> 'Args' ->> 'slack-user-id'; + ELSE + NEW.type = 'DEST'; + NEW.value = gen_random_uuid()::text; + END IF; + RETURN new; +END; +$$ +LANGUAGE plpgsql; + +-- +migrate StatementEnd +CREATE TRIGGER trg_10_compat_set_type_val_on_insert + BEFORE INSERT ON user_contact_methods + FOR EACH ROW + WHEN(NEW.dest IS NOT NULL) + EXECUTE FUNCTION fn_cm_compat_set_type_val_on_insert(); + +CREATE TRIGGER trg_10_compat_set_type_val_on_update + BEFORE UPDATE ON user_contact_methods + FOR EACH ROW + WHEN(NEW.dest != OLD.dest) + EXECUTE FUNCTION fn_cm_compat_set_type_val_on_insert(); + +-- +migrate Down +DELETE FROM user_contact_methods +WHERE type = 'DEST'; + +DROP TRIGGER trg_10_compat_set_type_val_on_insert ON user_contact_methods; + +DROP TRIGGER trg_10_compat_set_type_val_on_update ON user_contact_methods; + +DROP TRIGGER trg_10_cm_set_dest_on_insert ON user_contact_methods; + +DROP TRIGGER trg_10_cm_set_dest_on_update ON user_contact_methods; + +DROP FUNCTION fn_cm_compat_set_type_val_on_insert(); + +DROP FUNCTION fn_cm_set_dest_on_insert(); + +DROP FUNCTION cm_type_val_to_dest(enum_user_contact_method_type, text); + +ALTER TABLE user_contact_methods + DROP COLUMN dest; + diff --git a/migrate/migrations/20240628163614-nc-dest.sql b/migrate/migrations/20240628163614-nc-dest.sql new file mode 100644 index 0000000000..0f6cf99cd9 --- /dev/null +++ b/migrate/migrations/20240628163614-nc-dest.sql @@ -0,0 +1,113 @@ +-- +migrate Up +-- +migrate StatementBegin +CREATE OR REPLACE FUNCTION nc_type_val_to_dest(typeName enum_notif_channel_type, value text) + RETURNS jsonb + AS $$ +BEGIN + IF typeName = 'SLACK' THEN + RETURN jsonb_build_object('Type', 'builtin-slack-channel', 'Args', jsonb_build_object('slack-channel-id', value)); + ELSIF typeName = 'WEBHOOK' THEN + RETURN jsonb_build_object('Type', 'builtin-webhook', 'Args', jsonb_build_object('webhook-url', value)); + ELSIF typeName = 'SLACK_USER_GROUP' THEN + RETURN jsonb_build_object('Type', 'builtin-slack-usergroup', 'Args', jsonb_build_object('slack-usergroup-id', split_part(value, ':', 1), 'slack-channel-id', split_part(value, ':', 2))); + ELSE + -- throw an error + RAISE EXCEPTION 'Unknown notification channel type: %', typeName; + END IF; +END; +$$ +LANGUAGE plpgsql; + +-- +migrate StatementEnd +ALTER TABLE notification_channels + ADD COLUMN dest jsonb UNIQUE; + +UPDATE + notification_channels +SET + dest = nc_type_val_to_dest(type, value); + +ALTER TABLE notification_channels + ALTER COLUMN dest SET NOT NULL; + +-- +migrate StatementBegin +CREATE OR REPLACE FUNCTION fn_nc_set_dest_on_insert() + RETURNS TRIGGER + AS $$ +BEGIN + NEW.dest = nc_type_val_to_dest(NEW.type, NEW.value); + RETURN new; +END; +$$ +LANGUAGE plpgsql; + +-- +migrate StatementEnd +CREATE TRIGGER trg_10_nc_set_dest_on_insert + BEFORE INSERT ON notification_channels + FOR EACH ROW + WHEN(NEW.dest IS NULL) + EXECUTE FUNCTION fn_nc_set_dest_on_insert(); + +CREATE TRIGGER trg_10_nc_set_dest_on_update + BEFORE UPDATE ON notification_channels + FOR EACH ROW + WHEN(NEW.dest = OLD.dest) + EXECUTE FUNCTION fn_nc_set_dest_on_insert(); + +-- +migrate StatementBegin +CREATE OR REPLACE FUNCTION fn_nc_compat_set_type_val_on_insert() + RETURNS TRIGGER + AS $$ +BEGIN + IF NEW.dest ->> 'Type' = 'builtin-slack-channel' THEN + NEW.type = 'SLACK'; + NEW.value = NEW.dest -> 'Args' ->> 'slack-channel-id'; + ELSIF NEW.dest ->> 'Type' = 'builtin-slack-usergroup' THEN + NEW.type = 'SLACK_USER_GROUP'; + NEW.value = NEW.dest -> 'Args' ->> 'slack-usergroup-id' || ':' || NEW.dest -> 'Args' ->> 'slack-channel-id'; + ELSIF NEW.dest ->> 'Type' = 'builtin-webhook' THEN + NEW.type = 'WEBHOOK'; + NEW.value = NEW.dest -> 'Args' ->> 'webhook-url'; + ELSE + NEW.type = 'DEST'; + NEW.value = gen_random_uuid()::text; + END IF; + RETURN new; +END; +$$ +LANGUAGE plpgsql; + +-- +migrate StatementEnd +CREATE TRIGGER trg_10_nc_compat_set_type_val_on_insert + BEFORE INSERT ON notification_channels + FOR EACH ROW + WHEN(NEW.dest IS NOT NULL) + EXECUTE FUNCTION fn_nc_compat_set_type_val_on_insert(); + +CREATE TRIGGER trg_10_nc_compat_set_type_val_on_update + BEFORE UPDATE ON notification_channels + FOR EACH ROW + WHEN(NEW.dest != OLD.dest) + EXECUTE FUNCTION fn_nc_compat_set_type_val_on_insert(); + +-- +migrate Down +DELETE FROM notification_channels +WHERE type = 'DEST'; + +DROP TRIGGER trg_10_nc_compat_set_type_val_on_insert ON notification_channels; + +DROP TRIGGER trg_10_nc_compat_set_type_val_on_update ON notification_channels; + +DROP TRIGGER trg_10_nc_set_dest_on_insert ON notification_channels; + +DROP TRIGGER trg_10_nc_set_dest_on_update ON notification_channels; + +DROP FUNCTION fn_nc_compat_set_type_val_on_insert(); + +DROP FUNCTION fn_nc_set_dest_on_insert(); + +DROP FUNCTION nc_type_val_to_dest(typeName enum_notif_channel_type, value text); + +ALTER TABLE notification_channels + DROP COLUMN dest; + diff --git a/migrate/schema.sql b/migrate/schema.sql index edd864ea8f..5ee645dbe0 100644 --- a/migrate/schema.sql +++ b/migrate/schema.sql @@ -1,7 +1,7 @@ -- This file is auto-generated by "make db-schema"; DO NOT EDIT --- DATA=ca94260e928d52a6fec1ec867af04164ce3cbe37fdab8dca0325fbecae48eb5e - --- DISK=738e979eb383a4af2ae1795cbb3c9a8afce45b5fecc9223b4b1912090579595e - --- PSQL=738e979eb383a4af2ae1795cbb3c9a8afce45b5fecc9223b4b1912090579595e - +-- DATA=32c7c9f3d27ccebf366251246b5f60359cc149dbbfb6c5ee1199ac4f5f4b4c23 - +-- DISK=62f752bd160eadf84722529fe05060e6d4f43daff8ab964f1db11e26ce1fa242 - +-- PSQL=62f752bd160eadf84722529fe05060e6d4f43daff8ab964f1db11e26ce1fa242 - -- -- pgdump-lite database dump -- @@ -96,6 +96,7 @@ CREATE TYPE enum_limit_type AS ENUM ( ); CREATE TYPE enum_notif_channel_type AS ENUM ( + 'DEST', 'SLACK', 'SLACK_USER_GROUP', 'WEBHOOK' @@ -140,6 +141,7 @@ CREATE TYPE enum_throttle_type AS ENUM ( ); CREATE TYPE enum_user_contact_method_type AS ENUM ( + 'DEST', 'EMAIL', 'PUSH', 'SLACK_DM', @@ -182,6 +184,29 @@ AS $function$ $function$ ; +CREATE OR REPLACE FUNCTION public.cm_type_val_to_dest(typename enum_user_contact_method_type, value text) + RETURNS jsonb + LANGUAGE plpgsql +AS $function$ +BEGIN + IF typeName = 'EMAIL' THEN + RETURN jsonb_build_object('Type', 'builtin-smtp-email', 'Args', jsonb_build_object('email-address', value)); + ELSIF typeName = 'VOICE' THEN + RETURN jsonb_build_object('Type', 'builtin-twilio-voice', 'Args', jsonb_build_object('phone-number', value)); + ELSIF typeName = 'SMS' THEN + RETURN jsonb_build_object('Type', 'builtin-twilio-sms', 'Args', jsonb_build_object('phone-number', value)); + ELSIF typeName = 'WEBHOOK' THEN + RETURN jsonb_build_object('Type', 'builtin-webhook', 'Args', jsonb_build_object('webhook-url', value)); + ELSIF typeName = 'SLACK_DM' THEN + RETURN jsonb_build_object('Type', 'builtin-slack-dm', 'Args', jsonb_build_object('slack-user-id', value)); + ELSE + -- throw an error + RAISE EXCEPTION 'Unknown contact method type: %', typeName; + END IF; +END; +$function$ +; + CREATE OR REPLACE FUNCTION public.escalate_alerts() RETURNS void LANGUAGE plpgsql @@ -309,6 +334,46 @@ END; $function$ ; +CREATE OR REPLACE FUNCTION public.fn_cm_compat_set_type_val_on_insert() + RETURNS trigger + LANGUAGE plpgsql +AS $function$ +BEGIN + IF NEW.dest ->> 'Type' = 'builtin-smtp-email' THEN + NEW.type = 'EMAIL'; + NEW.value = NEW.dest -> 'Args' ->> 'email-address'; + ELSIF NEW.dest ->> 'Type' = 'builtin-twilio-voice' THEN + NEW.type = 'VOICE'; + NEW.value = NEW.dest -> 'Args' ->> 'phone-number'; + ELSIF NEW.dest ->> 'Type' = 'builtin-twilio-sms' THEN + NEW.type = 'SMS'; + NEW.value = NEW.dest -> 'Args' ->> 'phone-number'; + ELSIF NEW.dest ->> 'Type' = 'builtin-webhook' THEN + NEW.type = 'WEBHOOK'; + NEW.value = NEW.dest -> 'Args' ->> 'webhook-url'; + ELSIF NEW.dest ->> 'Type' = 'builtin-slack-dm' THEN + NEW.type = 'SLACK_DM'; + NEW.value = NEW.dest -> 'Args' ->> 'slack-user-id'; + ELSE + NEW.type = 'DEST'; + NEW.value = gen_random_uuid()::text; + END IF; + RETURN new; +END; +$function$ +; + +CREATE OR REPLACE FUNCTION public.fn_cm_set_dest_on_insert() + RETURNS trigger + LANGUAGE plpgsql +AS $function$ +BEGIN + NEW.dest = cm_type_val_to_dest(NEW.type, NEW.value); + RETURN new; +END; +$function$ +; + CREATE OR REPLACE FUNCTION public.fn_cm_set_not_pending_on_verify() RETURNS trigger LANGUAGE plpgsql @@ -999,6 +1064,40 @@ END; $function$ ; +CREATE OR REPLACE FUNCTION public.fn_nc_compat_set_type_val_on_insert() + RETURNS trigger + LANGUAGE plpgsql +AS $function$ +BEGIN + IF NEW.dest ->> 'Type' = 'builtin-slack-channel' THEN + NEW.type = 'SLACK'; + NEW.value = NEW.dest -> 'Args' ->> 'slack-channel-id'; + ELSIF NEW.dest ->> 'Type' = 'builtin-slack-usergroup' THEN + NEW.type = 'SLACK_USER_GROUP'; + NEW.value = NEW.dest -> 'Args' ->> 'slack-usergroup-id' || ':' || NEW.dest -> 'Args' ->> 'slack-channel-id'; + ELSIF NEW.dest ->> 'Type' = 'builtin-webhook' THEN + NEW.type = 'WEBHOOK'; + NEW.value = NEW.dest -> 'Args' ->> 'webhook-url'; + ELSE + NEW.type = 'DEST'; + NEW.value = gen_random_uuid()::text; + END IF; + RETURN new; +END; +$function$ +; + +CREATE OR REPLACE FUNCTION public.fn_nc_set_dest_on_insert() + RETURNS trigger + LANGUAGE plpgsql +AS $function$ +BEGIN + NEW.dest = nc_type_val_to_dest(NEW.type, NEW.value); + RETURN new; +END; +$function$ +; + CREATE OR REPLACE FUNCTION public.fn_notification_rule_same_user() RETURNS trigger LANGUAGE plpgsql @@ -1188,6 +1287,25 @@ AS $function$ $function$ ; +CREATE OR REPLACE FUNCTION public.nc_type_val_to_dest(typename enum_notif_channel_type, value text) + RETURNS jsonb + LANGUAGE plpgsql +AS $function$ +BEGIN + IF typeName = 'SLACK' THEN + RETURN jsonb_build_object('Type', 'builtin-slack-channel', 'Args', jsonb_build_object('slack-channel-id', value)); + ELSIF typeName = 'WEBHOOK' THEN + RETURN jsonb_build_object('Type', 'builtin-webhook', 'Args', jsonb_build_object('webhook-url', value)); + ELSIF typeName = 'SLACK_USER_GROUP' THEN + RETURN jsonb_build_object('Type', 'builtin-slack-usergroup', 'Args', jsonb_build_object('slack-usergroup-id', split_part(value, ':', 1), 'slack-channel-id', split_part(value, ':', 2))); + ELSE + -- throw an error + RAISE EXCEPTION 'Unknown notification channel type: %', typeName; + END IF; +END; +$function$ +; + CREATE OR REPLACE FUNCTION public.release_user_contact_method_lock(_client_id uuid, _id uuid, success boolean) RETURNS void LANGUAGE plpgsql @@ -1723,16 +1841,26 @@ CREATE UNIQUE INDEX labels_tgt_service_id_key_key ON public.labels USING btree ( CREATE TABLE notification_channels ( created_at timestamp with time zone DEFAULT now() NOT NULL, + dest jsonb NOT NULL, id uuid NOT NULL, meta jsonb DEFAULT '{}'::jsonb NOT NULL, name text NOT NULL, type enum_notif_channel_type NOT NULL, value text NOT NULL, + CONSTRAINT nc_unique_type_value UNIQUE (type, value), + CONSTRAINT notification_channels_dest_key UNIQUE (dest), CONSTRAINT notification_channels_pkey PRIMARY KEY (id) ); +CREATE UNIQUE INDEX nc_unique_type_value ON public.notification_channels USING btree (type, value); +CREATE UNIQUE INDEX notification_channels_dest_key ON public.notification_channels USING btree (dest); CREATE UNIQUE INDEX notification_channels_pkey ON public.notification_channels USING btree (id); +CREATE TRIGGER trg_10_nc_compat_set_type_val_on_insert BEFORE INSERT ON public.notification_channels FOR EACH ROW WHEN ((new.dest IS NOT NULL)) EXECUTE FUNCTION fn_nc_compat_set_type_val_on_insert(); +CREATE TRIGGER trg_10_nc_compat_set_type_val_on_update BEFORE UPDATE ON public.notification_channels FOR EACH ROW WHEN ((new.dest <> old.dest)) EXECUTE FUNCTION fn_nc_compat_set_type_val_on_insert(); +CREATE TRIGGER trg_10_nc_set_dest_on_insert BEFORE INSERT ON public.notification_channels FOR EACH ROW WHEN ((new.dest IS NULL)) EXECUTE FUNCTION fn_nc_set_dest_on_insert(); +CREATE TRIGGER trg_10_nc_set_dest_on_update BEFORE UPDATE ON public.notification_channels FOR EACH ROW WHEN ((new.dest = old.dest)) EXECUTE FUNCTION fn_nc_set_dest_on_insert(); + CREATE TABLE notification_policy_cycles ( alert_id integer NOT NULL, @@ -2062,11 +2190,19 @@ CREATE UNIQUE INDEX twilio_voice_errors_uniq_id ON public.twilio_voice_errors US CREATE TABLE uik_config ( config jsonb NOT NULL, id uuid NOT NULL, + primary_token uuid, + primary_token_hint text, + secondary_token uuid, + secondary_token_hint text, CONSTRAINT uik_config_id_fkey FOREIGN KEY (id) REFERENCES integration_keys(id) ON DELETE CASCADE, - CONSTRAINT uik_config_pkey PRIMARY KEY (id) + CONSTRAINT uik_config_pkey PRIMARY KEY (id), + CONSTRAINT uik_config_primary_token_key UNIQUE (primary_token), + CONSTRAINT uik_config_secondary_token_key UNIQUE (secondary_token) ); CREATE UNIQUE INDEX uik_config_pkey ON public.uik_config USING btree (id); +CREATE UNIQUE INDEX uik_config_primary_token_key ON public.uik_config USING btree (primary_token); +CREATE UNIQUE INDEX uik_config_secondary_token_key ON public.uik_config USING btree (secondary_token); CREATE TABLE user_calendar_subscriptions ( @@ -2092,6 +2228,7 @@ CREATE CONSTRAINT TRIGGER trg_enforce_calendar_subscriptions_per_user_limit AFTE CREATE TABLE user_contact_methods ( + dest jsonb NOT NULL, disabled boolean DEFAULT false NOT NULL, enable_status_updates boolean DEFAULT false NOT NULL, id uuid DEFAULT gen_random_uuid() NOT NULL, @@ -2102,6 +2239,7 @@ CREATE TABLE user_contact_methods ( type enum_user_contact_method_type NOT NULL, user_id uuid NOT NULL, value text NOT NULL, + CONSTRAINT user_contact_methods_dest_key UNIQUE (dest), CONSTRAINT user_contact_methods_pkey PRIMARY KEY (id), CONSTRAINT user_contact_methods_type_value_key UNIQUE (type, value), CONSTRAINT user_contact_methods_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE @@ -2109,9 +2247,14 @@ CREATE TABLE user_contact_methods ( CREATE INDEX idx_contact_method_users ON public.user_contact_methods USING btree (user_id); CREATE INDEX idx_valid_contact_methods ON public.user_contact_methods USING btree (id) WHERE (NOT disabled); +CREATE UNIQUE INDEX user_contact_methods_dest_key ON public.user_contact_methods USING btree (dest); CREATE UNIQUE INDEX user_contact_methods_pkey ON public.user_contact_methods USING btree (id); CREATE UNIQUE INDEX user_contact_methods_type_value_key ON public.user_contact_methods USING btree (type, value); +CREATE TRIGGER trg_10_cm_set_dest_on_insert BEFORE INSERT ON public.user_contact_methods FOR EACH ROW WHEN ((new.dest IS NULL)) EXECUTE FUNCTION fn_cm_set_dest_on_insert(); +CREATE TRIGGER trg_10_cm_set_dest_on_update BEFORE UPDATE ON public.user_contact_methods FOR EACH ROW WHEN ((new.dest = old.dest)) EXECUTE FUNCTION fn_cm_set_dest_on_insert(); +CREATE TRIGGER trg_10_compat_set_type_val_on_insert BEFORE INSERT ON public.user_contact_methods FOR EACH ROW WHEN ((new.dest IS NOT NULL)) EXECUTE FUNCTION fn_cm_compat_set_type_val_on_insert(); +CREATE TRIGGER trg_10_compat_set_type_val_on_update BEFORE UPDATE ON public.user_contact_methods FOR EACH ROW WHEN ((new.dest <> old.dest)) EXECUTE FUNCTION fn_cm_compat_set_type_val_on_insert(); CREATE TRIGGER trg_cm_set_not_pending_on_verify BEFORE UPDATE OF disabled ON public.user_contact_methods FOR EACH ROW WHEN (((NOT new.disabled) AND old.pending)) EXECUTE FUNCTION fn_cm_set_not_pending_on_verify(); CREATE CONSTRAINT TRIGGER trg_enforce_contact_method_limit AFTER INSERT ON public.user_contact_methods NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE FUNCTION fn_enforce_contact_method_limit(); diff --git a/notification/desttype.go b/notification/desttype.go index bfba51024b..394fd52be5 100644 --- a/notification/desttype.go +++ b/notification/desttype.go @@ -1,8 +1,11 @@ package notification import ( + "database/sql" "fmt" + "github.com/google/uuid" + "github.com/target/goalert/gadb" "github.com/target/goalert/notificationchannel" "github.com/target/goalert/user/contactmethod" ) @@ -14,6 +17,35 @@ type Dest struct { Type DestType Value string } +type SQLDest struct { + CMID uuid.NullUUID + CMType gadb.NullEnumUserContactMethodType + CMValue sql.NullString + + NCID uuid.NullUUID + NCType gadb.NullEnumNotifChannelType + NCValue sql.NullString +} + +func (s SQLDest) Dest() Dest { + if s.CMID.Valid { + return Dest{ + ID: s.CMID.UUID.String(), + Value: s.CMValue.String, + Type: ScannableDestType{CM: contactmethod.Type(s.CMType.EnumUserContactMethodType)}.DestType(), + } + } + + if s.NCID.Valid { + return Dest{ + ID: s.NCID.UUID.String(), + Value: s.NCValue.String, + Type: ScannableDestType{NC: notificationchannel.Type(s.NCType.EnumNotifChannelType)}.DestType(), + } + } + + panic("no valid ID") +} // DestFromPair will return a Dest for a notification channel/contact method pair. func DestFromPair(cm *contactmethod.ContactMethod, nc *notificationchannel.Channel) Dest { diff --git a/notification/messagetype.go b/notification/messagetype.go index ad83222d87..8d8031b456 100644 --- a/notification/messagetype.go +++ b/notification/messagetype.go @@ -3,6 +3,8 @@ package notification import ( "database/sql/driver" "fmt" + + "github.com/target/goalert/gadb" ) //go:generate go run golang.org/x/tools/cmd/stringer -type MessageType @@ -47,6 +49,16 @@ func (s MessageType) Value() (driver.Value, error) { return nil, fmt.Errorf("could not process unknown type for MessageType %s", s) } +func (s *MessageType) FromDB(value gadb.EnumOutgoingMessagesType) error { return s.Scan(string(value)) } + +func (s MessageType) ToDB() (gadb.EnumOutgoingMessagesType, error) { + val, err := s.Value() + if err != nil { + return "", err + } + return gadb.EnumOutgoingMessagesType(val.(string)), nil +} + func (s *MessageType) Scan(value interface{}) error { str := value.(string) diff --git a/notificationchannel/channel.go b/notificationchannel/channel.go index 9bbf9324eb..93568505dd 100644 --- a/notificationchannel/channel.go +++ b/notificationchannel/channel.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/google/uuid" + "github.com/target/goalert/gadb" "github.com/target/goalert/validation/validate" ) @@ -14,6 +15,13 @@ type Channel struct { Value string } +func (c *Channel) fromRow(row gadb.NotificationChannel) { + c.ID = row.ID.String() + c.Name = row.Name + c.Type = Type(row.Type) + c.Value = row.Value +} + func (c Channel) Normalize() (*Channel, error) { if c.ID == "" { c.ID = uuid.New().String() diff --git a/notificationchannel/queries.sql b/notificationchannel/queries.sql new file mode 100644 index 0000000000..dca46b2793 --- /dev/null +++ b/notificationchannel/queries.sql @@ -0,0 +1,44 @@ +-- name: NotifChanFindOne :one +SELECT + * +FROM + notification_channels +WHERE + id = $1; + +-- name: NotifChanFindMany :many +SELECT + * +FROM + notification_channels +WHERE + id = ANY ($1::uuid[]); + +-- name: NotifChanCreate :exec +INSERT INTO notification_channels(id, name, type, value) + VALUES ($1, $2, $3, $4); + +-- name: NotifChanUpdateName :exec +UPDATE + notification_channels +SET + name = $2 +WHERE + id = $1; + +-- name: NotifChanDeleteMany :exec +DELETE FROM notification_channels +WHERE id = ANY ($1::uuid[]); + +-- name: NotifChanFindByValue :one +SELECT + * +FROM + notification_channels +WHERE + type = $1 + AND value = $2; + +-- name: NotifChanLock :exec +LOCK notification_channels IN SHARE ROW EXCLUSIVE MODE; + diff --git a/notificationchannel/store.go b/notificationchannel/store.go index 15e4a1e055..a023e177df 100644 --- a/notificationchannel/store.go +++ b/notificationchannel/store.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/google/uuid" + "github.com/target/goalert/gadb" "github.com/target/goalert/permission" "github.com/target/goalert/search" "github.com/target/goalert/util" @@ -16,16 +17,6 @@ import ( type Store struct { db *sql.DB - - findAll *sql.Stmt - findOne *sql.Stmt - findMany *sql.Stmt - create *sql.Stmt - deleteMany *sql.Stmt - - updateName *sql.Stmt - findByValue *sql.Stmt - lock *sql.Stmt } func NewStore(ctx context.Context, db *sql.DB) (*Store, error) { @@ -33,68 +24,31 @@ func NewStore(ctx context.Context, db *sql.DB) (*Store, error) { return &Store{ db: db, - - findAll: p.P(` - select id, name, type, value from notification_channels - `), - findOne: p.P(` - select id, name, type, value from notification_channels where id = $1 - `), - findMany: p.P(` - select id, name, type, value from notification_channels where id = any($1) - `), - create: p.P(` - insert into notification_channels (id, name, type, value) - values ($1, $2, $3, $4) - `), - updateName: p.P(`update notification_channels set name = $2 where id = $1`), - deleteMany: p.P(`DELETE FROM notification_channels WHERE id = any($1)`), - - findByValue: p.P(`select id, name from notification_channels where type = $1 and value = $2`), - - // Lock the table so only one tx can insert/update at a time, but allows the above SELECT FOR UPDATE to run - // so only required changes block. - lock: p.P(`LOCK notification_channels IN SHARE ROW EXCLUSIVE MODE`), }, p.Err } -func stmt(ctx context.Context, tx *sql.Tx, stmt *sql.Stmt) *sql.Stmt { - if tx == nil { - return stmt - } - - return tx.StmtContext(ctx, stmt) -} - func (s *Store) FindMany(ctx context.Context, ids []string) ([]Channel, error) { err := permission.LimitCheckAny(ctx, permission.User) if err != nil { return nil, err } - err = validate.ManyUUID("ID", ids, search.MaxResults) + uuids, err := validate.ParseManyUUID("ID", ids, search.MaxResults) if err != nil { return nil, err } - rows, err := s.findMany.QueryContext(ctx, sqlutil.UUIDArray(ids)) + rows, err := gadb.New(s.db).NotifChanFindMany(ctx, uuids) if errors.Is(err, sql.ErrNoRows) { return nil, nil } if err != nil { return nil, err } - defer rows.Close() - - var channels []Channel - for rows.Next() { - var c Channel - err = rows.Scan(&c.ID, &c.Name, &c.Type, &c.Value) - if err != nil { - return nil, err - } - channels = append(channels, c) + channels := make([]Channel, len(rows)) + for i, r := range rows { + channels[i].fromRow(r) } return channels, nil @@ -111,9 +65,15 @@ func (s *Store) MapToID(ctx context.Context, tx *sql.Tx, c *Channel) (uuid.UUID, return uuid.UUID{}, err } - var id sqlutil.NullUUID - var name sql.NullString - err = stmt(ctx, tx, s.findByValue).QueryRowContext(ctx, n.Type, n.Value).Scan(&id, &name) + db := gadb.New(s.db) + if tx != nil { + db = db.WithTx(tx) + } + + row, err := db.NotifChanFindByValue(ctx, gadb.NotifChanFindByValueParams{ + Type: gadb.EnumNotifChannelType(n.Type), + Value: n.Value, + }) if errors.Is(err, sql.ErrNoRows) { err = nil } @@ -121,9 +81,9 @@ func (s *Store) MapToID(ctx context.Context, tx *sql.Tx, c *Channel) (uuid.UUID, return uuid.UUID{}, fmt.Errorf("lookup existing entry: %w", err) } - if id.Valid && name.String == c.Name { + if row.Name == c.Name { // short-circuit if it already exists and is up-to-date. - return id.UUID, nil + return row.ID, nil } var ownTx bool @@ -134,45 +94,61 @@ func (s *Store) MapToID(ctx context.Context, tx *sql.Tx, c *Channel) (uuid.UUID, return uuid.UUID{}, fmt.Errorf("start tx: %w", err) } defer sqlutil.Rollback(ctx, "notificationchannel: map channel ID to UUID", tx) + db = db.WithTx(tx) } - _, err = tx.StmtContext(ctx, s.lock).ExecContext(ctx) + err = db.NotifChanLock(ctx) if err != nil { return uuid.UUID{}, fmt.Errorf("acquire lock: %w", err) } // try again after exclusive lock - err = tx.StmtContext(ctx, s.findByValue).QueryRowContext(ctx, n.Type, n.Value).Scan(&id, &name) + row, err = db.NotifChanFindByValue(ctx, gadb.NotifChanFindByValueParams{ + Type: gadb.EnumNotifChannelType(n.Type), + Value: n.Value, + }) if errors.Is(err, sql.ErrNoRows) { err = nil } if err != nil { return uuid.UUID{}, fmt.Errorf("lookup existing entry exclusively: %w", err) } - if id.Valid && name.String == c.Name { + if row.Name == c.Name { // short-circuit if it already exists and is up-to-date. - return id.UUID, nil + return row.ID, nil } - if !id.Valid { + + if row.ID == uuid.Nil { // create new one - id.Valid = true - id.UUID = uuid.New() - _, err = tx.StmtContext(ctx, s.create).ExecContext(ctx, id, n.Name, n.Type, n.Value) + row.ID = uuid.New() + err = db.NotifChanCreate(ctx, gadb.NotifChanCreateParams{ + ID: row.ID, + Name: n.Name, + Type: gadb.EnumNotifChannelType(n.Type), + Value: n.Value, + }) if err != nil { return uuid.UUID{}, fmt.Errorf("create new NC: %w", err) } } else { // update existing name - _, err = tx.StmtContext(ctx, s.updateName).ExecContext(ctx, id, n.Name) + err = db.NotifChanUpdateName(ctx, gadb.NotifChanUpdateNameParams{ + ID: row.ID, + Name: n.Name, + }) if err != nil { return uuid.UUID{}, fmt.Errorf("update NC name: %w", err) } } if ownTx { - return id.UUID, tx.Commit() + err = tx.Commit() + if err != nil { + return uuid.UUID{}, fmt.Errorf("commit tx: %w", err) + } } - return id.UUID, nil + + return row.ID, nil } func (s *Store) DeleteManyTx(ctx context.Context, tx *sql.Tx, ids []string) error { @@ -181,18 +157,17 @@ func (s *Store) DeleteManyTx(ctx context.Context, tx *sql.Tx, ids []string) erro return err } - err = validate.Range("Count", len(ids), 1, 100) + uuids, err := validate.ParseManyUUID("ID", ids, 100) if err != nil { return err } - del := s.deleteMany + db := gadb.New(s.db) if tx != nil { - tx.StmtContext(ctx, del) + db = db.WithTx(tx) } - _, err = del.ExecContext(ctx, sqlutil.UUIDArray(ids)) - return err + return db.NotifChanDeleteMany(ctx, uuids) } func (s *Store) FindOne(ctx context.Context, id uuid.UUID) (*Channel, error) { @@ -202,34 +177,11 @@ func (s *Store) FindOne(ctx context.Context, id uuid.UUID) (*Channel, error) { } var c Channel - err = s.findOne.QueryRowContext(ctx, id).Scan(&c.ID, &c.Name, &c.Type, &c.Value) + row, err := gadb.New(s.db).NotifChanFindOne(ctx, id) if err != nil { return nil, err } - return &c, nil -} + c.fromRow(row) -func (s *Store) FindAll(ctx context.Context) ([]Channel, error) { - err := permission.LimitCheckAny(ctx, permission.System, permission.User) - if err != nil { - return nil, err - } - - rows, err := s.findAll.QueryContext(ctx) - if err != nil { - return nil, err - } - defer rows.Close() - - var channels []Channel - for rows.Next() { - var c Channel - err = rows.Scan(&c.ID, &c.Name, &c.Type, &c.Value) - if err != nil { - return nil, err - } - channels = append(channels, c) - } - - return channels, nil + return &c, nil } diff --git a/package.json b/package.json index 6000e919e6..0279a96ea1 100644 --- a/package.json +++ b/package.json @@ -39,13 +39,13 @@ "@dnd-kit/sortable": "8.0.0", "@dnd-kit/utilities": "3.2.2", "@emotion/react": "11.11.1", - "@emotion/styled": "11.11.0", + "@emotion/styled": "11.11.5", "@material/material-color-utilities": "0.2.7", "@mui/icons-material": "5.15.13", - "@mui/lab": "5.0.0-alpha.162", - "@mui/material": "5.15.15", + "@mui/lab": "5.0.0-alpha.170", + "@mui/material": "5.15.19", "@mui/styles": "5.15.15", - "@mui/system": "5.15.6", + "@mui/system": "5.15.15", "@mui/x-data-grid": "6.19.6", "@playwright/test": "1.41.2", "@storybook/addon-essentials": "8.0.0", @@ -56,10 +56,10 @@ "@storybook/react": "8.0.0", "@storybook/react-vite": "8.0.0", "@storybook/test": "8.0.8", - "@storybook/test-runner": "0.17.0", + "@storybook/test-runner": "0.18.2", "@storybook/types": "8.0.6", "@types/chance": "1.1.6", - "@types/diff": "5.0.8", + "@types/diff": "5.2.1", "@types/glob": "8.1.0", "@types/jest": "29.5.12", "@types/lodash": "4.17.1", @@ -67,20 +67,20 @@ "@types/node": "20.11.30", "@types/prop-types": "15.7.11", "@types/react": "18.2.48", - "@types/react-big-calendar": "1.6.5", + "@types/react-big-calendar": "1.8.9", "@types/react-dom": "18.2.22", "@types/react-transition-group": "4.4.10", "@types/react-virtualized-auto-sizer": "1.0.4", - "@typescript-eslint/eslint-plugin": "7.7.0", + "@typescript-eslint/eslint-plugin": "7.11.0", "@typescript-eslint/parser": "6.21.0", "@urql/exchange-retry": "1.2.1", "bowser": "2.11.0", "chance": "1.1.11", - "classnames": "2.3.2", + "classnames": "2.5.1", "concurrently": "8.2.2", "cypress": "13.3.0", "detect-package-manager": "3.0.1", - "diff": "5.1.0", + "diff": "5.2.0", "esbuild": "0.20.2", "esbuild-jest": "0.5.0", "eslint": "8.57.0", @@ -98,7 +98,7 @@ "eslint-plugin-react-hooks": "4.6.2", "eslint-plugin-storybook": "0.8.0", "fuse.js": "7.0.0", - "glob": "10.3.10", + "glob": "10.3.14", "graphiql": "3.0.10", "graphql": "16.8.1", "http-server": "14.1.1", @@ -107,14 +107,14 @@ "luxon": "3.4.4", "mdast-util-find-and-replace": "3.0.1", "mdi-material-ui": "7.8.0", - "msw": "2.0.11", - "msw-storybook-addon": "2.0.0--canary.122.06f0c92.0", + "msw": "2.3.0", + "msw-storybook-addon": "2.0.2", "prettier": "3.2.5", "prettier-plugin-go-template": "0.0.15", "prop-types": "15.8.1", "punycode": "2.3.1", "react": "18.2.0", - "react-big-calendar": "1.8.5", + "react-big-calendar": "1.12.2", "react-colorful": "5.6.1", "react-countdown": "2.3.5", "react-dom": "18.2.0", @@ -135,7 +135,7 @@ "storybook": "8.0.9", "storybook-addon-mock": "4.3.0", "stylelint": "16.2.1", - "stylelint-config-standard": "34.0.0", + "stylelint-config-standard": "36.0.0", "typescript": "5.2.2", "urql": "4.0.6", "vite": "5.1.7", diff --git a/permission/source.go b/permission/source.go index 221c1b20f7..400e769169 100644 --- a/permission/source.go +++ b/permission/source.go @@ -29,6 +29,9 @@ const ( // SourceTypeGQLAPIKey is set when a context is authorized for use of the GraphQL API. SourceTypeGQLAPIKey + + // SourceTypeUIK is set when a context is authorized for use of a universal integration key. + SourceTypeUIK ) // SourceInfo provides information about the source of a context's authorization. diff --git a/permission/sourcetype_string.go b/permission/sourcetype_string.go index c9f21edf2b..27c9485e6d 100644 --- a/permission/sourcetype_string.go +++ b/permission/sourcetype_string.go @@ -16,11 +16,12 @@ func _() { _ = x[SourceTypeNotificationChannel-5] _ = x[SourceTypeCalendarSubscription-6] _ = x[SourceTypeGQLAPIKey-7] + _ = x[SourceTypeUIK-8] } -const _SourceType_name = "SourceTypeNotificationCallbackSourceTypeIntegrationKeySourceTypeAuthProviderSourceTypeContactMethodSourceTypeHeartbeatSourceTypeNotificationChannelSourceTypeCalendarSubscriptionSourceTypeGQLAPIKey" +const _SourceType_name = "SourceTypeNotificationCallbackSourceTypeIntegrationKeySourceTypeAuthProviderSourceTypeContactMethodSourceTypeHeartbeatSourceTypeNotificationChannelSourceTypeCalendarSubscriptionSourceTypeGQLAPIKeySourceTypeUIK" -var _SourceType_index = [...]uint8{0, 30, 54, 76, 99, 118, 147, 177, 196} +var _SourceType_index = [...]uint8{0, 30, 54, 76, 99, 118, 147, 177, 196, 209} func (i SourceType) String() string { if i < 0 || i >= SourceType(len(_SourceType_index)-1) { diff --git a/pkg/sysapi/client_test.go b/pkg/sysapi/client_test.go index a67f27c667..a4ebbdd165 100644 --- a/pkg/sysapi/client_test.go +++ b/pkg/sysapi/client_test.go @@ -19,7 +19,7 @@ func ExampleSysAPIClient_AuthSubjects() { target := flag.String("target", "localhost:1234", "Server address.") flag.Parse() - conn, err := grpc.Dial(*target, grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.NewClient(*target, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatal(err) } @@ -59,7 +59,7 @@ func ExampleSysAPIClient_DeleteUser() { log.Fatal(err) } - conn, err := grpc.Dial(*target, grpc.WithTransportCredentials(credentials.NewTLS(cfg))) + conn, err := grpc.NewClient(*target, grpc.WithTransportCredentials(credentials.NewTLS(cfg))) if err != nil { log.Fatal(err) } diff --git a/pkg/sysapi/sysapi.pb.go b/pkg/sysapi/sysapi.pb.go index d1b5ed11f0..5acf5bc9be 100644 --- a/pkg/sysapi/sysapi.pb.go +++ b/pkg/sysapi/sysapi.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.2 // protoc v5.26.0 // source: pkg/sysapi/sysapi.proto @@ -495,7 +495,7 @@ func file_pkg_sysapi_sysapi_proto_rawDescGZIP() []byte { } var file_pkg_sysapi_sysapi_proto_msgTypes = make([]protoimpl.MessageInfo, 8) -var file_pkg_sysapi_sysapi_proto_goTypes = []interface{}{ +var file_pkg_sysapi_sysapi_proto_goTypes = []any{ (*UsersWithoutAuthProviderRequest)(nil), // 0: goalert.v1.UsersWithoutAuthProviderRequest (*SetAuthSubjectRequest)(nil), // 1: goalert.v1.SetAuthSubjectRequest (*UserInfo)(nil), // 2: goalert.v1.UserInfo @@ -528,7 +528,7 @@ func file_pkg_sysapi_sysapi_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_pkg_sysapi_sysapi_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_pkg_sysapi_sysapi_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*UsersWithoutAuthProviderRequest); i { case 0: return &v.state @@ -540,7 +540,7 @@ func file_pkg_sysapi_sysapi_proto_init() { return nil } } - file_pkg_sysapi_sysapi_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_pkg_sysapi_sysapi_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*SetAuthSubjectRequest); i { case 0: return &v.state @@ -552,7 +552,7 @@ func file_pkg_sysapi_sysapi_proto_init() { return nil } } - file_pkg_sysapi_sysapi_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_pkg_sysapi_sysapi_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*UserInfo); i { case 0: return &v.state @@ -564,7 +564,7 @@ func file_pkg_sysapi_sysapi_proto_init() { return nil } } - file_pkg_sysapi_sysapi_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_pkg_sysapi_sysapi_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*SetAuthSubjectResponse); i { case 0: return &v.state @@ -576,7 +576,7 @@ func file_pkg_sysapi_sysapi_proto_init() { return nil } } - file_pkg_sysapi_sysapi_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_pkg_sysapi_sysapi_proto_msgTypes[4].Exporter = func(v any, i int) any { switch v := v.(*DeleteUserRequest); i { case 0: return &v.state @@ -588,7 +588,7 @@ func file_pkg_sysapi_sysapi_proto_init() { return nil } } - file_pkg_sysapi_sysapi_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_pkg_sysapi_sysapi_proto_msgTypes[5].Exporter = func(v any, i int) any { switch v := v.(*DeleteUserResponse); i { case 0: return &v.state @@ -600,7 +600,7 @@ func file_pkg_sysapi_sysapi_proto_init() { return nil } } - file_pkg_sysapi_sysapi_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_pkg_sysapi_sysapi_proto_msgTypes[6].Exporter = func(v any, i int) any { switch v := v.(*AuthSubjectsRequest); i { case 0: return &v.state @@ -612,7 +612,7 @@ func file_pkg_sysapi_sysapi_proto_init() { return nil } } - file_pkg_sysapi_sysapi_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_pkg_sysapi_sysapi_proto_msgTypes[7].Exporter = func(v any, i int) any { switch v := v.(*AuthSubject); i { case 0: return &v.state diff --git a/pkg/sysapi/sysapi_grpc.pb.go b/pkg/sysapi/sysapi_grpc.pb.go index 8b646d3bb6..1dcd07f400 100644 --- a/pkg/sysapi/sysapi_grpc.pb.go +++ b/pkg/sysapi/sysapi_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.4.0 // - protoc v5.26.0 // source: pkg/sysapi/sysapi.proto @@ -15,8 +15,8 @@ import ( // 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.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.62.0 or later. +const _ = grpc.SupportPackageIsVersion8 const ( SysAPI_AuthSubjects_FullMethodName = "/goalert.v1.SysAPI/AuthSubjects" @@ -44,11 +44,12 @@ func NewSysAPIClient(cc grpc.ClientConnInterface) SysAPIClient { } func (c *sysAPIClient) AuthSubjects(ctx context.Context, in *AuthSubjectsRequest, opts ...grpc.CallOption) (SysAPI_AuthSubjectsClient, error) { - stream, err := c.cc.NewStream(ctx, &SysAPI_ServiceDesc.Streams[0], SysAPI_AuthSubjects_FullMethodName, opts...) + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &SysAPI_ServiceDesc.Streams[0], SysAPI_AuthSubjects_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &sysAPIAuthSubjectsClient{stream} + x := &sysAPIAuthSubjectsClient{ClientStream: stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -76,8 +77,9 @@ func (x *sysAPIAuthSubjectsClient) Recv() (*AuthSubject, error) { } func (c *sysAPIClient) DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*DeleteUserResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(DeleteUserResponse) - err := c.cc.Invoke(ctx, SysAPI_DeleteUser_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, SysAPI_DeleteUser_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -85,11 +87,12 @@ func (c *sysAPIClient) DeleteUser(ctx context.Context, in *DeleteUserRequest, op } func (c *sysAPIClient) UsersWithoutAuthProvider(ctx context.Context, in *UsersWithoutAuthProviderRequest, opts ...grpc.CallOption) (SysAPI_UsersWithoutAuthProviderClient, error) { - stream, err := c.cc.NewStream(ctx, &SysAPI_ServiceDesc.Streams[1], SysAPI_UsersWithoutAuthProvider_FullMethodName, opts...) + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &SysAPI_ServiceDesc.Streams[1], SysAPI_UsersWithoutAuthProvider_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &sysAPIUsersWithoutAuthProviderClient{stream} + x := &sysAPIUsersWithoutAuthProviderClient{ClientStream: stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -117,8 +120,9 @@ func (x *sysAPIUsersWithoutAuthProviderClient) Recv() (*UserInfo, error) { } func (c *sysAPIClient) SetAuthSubject(ctx context.Context, in *SetAuthSubjectRequest, opts ...grpc.CallOption) (*SetAuthSubjectResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SetAuthSubjectResponse) - err := c.cc.Invoke(ctx, SysAPI_SetAuthSubject_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, SysAPI_SetAuthSubject_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -170,7 +174,7 @@ func _SysAPI_AuthSubjects_Handler(srv interface{}, stream grpc.ServerStream) err if err := stream.RecvMsg(m); err != nil { return err } - return srv.(SysAPIServer).AuthSubjects(m, &sysAPIAuthSubjectsServer{stream}) + return srv.(SysAPIServer).AuthSubjects(m, &sysAPIAuthSubjectsServer{ServerStream: stream}) } type SysAPI_AuthSubjectsServer interface { @@ -209,7 +213,7 @@ func _SysAPI_UsersWithoutAuthProvider_Handler(srv interface{}, stream grpc.Serve if err := stream.RecvMsg(m); err != nil { return err } - return srv.(SysAPIServer).UsersWithoutAuthProvider(m, &sysAPIUsersWithoutAuthProviderServer{stream}) + return srv.(SysAPIServer).UsersWithoutAuthProvider(m, &sysAPIUsersWithoutAuthProviderServer{ServerStream: stream}) } type SysAPI_UsersWithoutAuthProviderServer interface { diff --git a/sqlc.version b/sqlc.version index ad2191947f..5ff8c4f5d2 100644 --- a/sqlc.version +++ b/sqlc.version @@ -1 +1 @@ -1.25.0 +1.26.0 diff --git a/sqlc.yaml b/sqlc.yaml index 67e6997dda..dc7efa63a0 100644 --- a/sqlc.yaml +++ b/sqlc.yaml @@ -22,10 +22,12 @@ sql: - notice/queries.sql - graphql2/graphqlapp/queries.sql - engine/statusmgr/queries.sql + - engine/message/queries.sql - auth/authlink/queries.sql - alert/alertlog/queries.sql - user/favorite/queries.sql - user/contactmethod/queries.sql + - notificationchannel/queries.sql - integrationkey/queries.sql - apikey/queries.sql - override/queries.sql @@ -35,4 +37,15 @@ sql: gen: go: out: gadb - sql_package: stdlib + sql_package: database/sql + overrides: + - column: public.user_contact_methods.dest + go_type: + # Note: We can't use the nullable/non-nullable types here because + # sqlc doesn't support it for column overrides yet. + # + # Since it's common to have NULL (i.e., when scanning contact methods and notificaiton channels at once) we use the nullable type. + type: NullDestV1 + - column: public.notification_channels.dest + go_type: + type: NullDestV1 diff --git a/swo/swodb/db.go b/swo/swodb/db.go index c8d9adc9a2..ae895ee252 100644 --- a/swo/swodb/db.go +++ b/swo/swodb/db.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.26.0 package swodb diff --git a/swo/swodb/models.go b/swo/swodb/models.go index 806e4d3ba2..6be52c23ac 100644 --- a/swo/swodb/models.go +++ b/swo/swodb/models.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.26.0 package swodb diff --git a/swo/swodb/queries.sql.go b/swo/swodb/queries.sql.go index b5c61ebcd5..6812d34813 100644 --- a/swo/swodb/queries.sql.go +++ b/swo/swodb/queries.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.25.0 +// sqlc v1.26.0 // source: queries.sql package swodb diff --git a/test/integration/email-cm.spec.ts b/test/integration/email-cm.spec.ts index 9cf8cfbc92..2299601460 100644 --- a/test/integration/email-cm.spec.ts +++ b/test/integration/email-cm.spec.ts @@ -1,5 +1,5 @@ import { test, expect } from '@playwright/test' -import { userSessionFile } from './lib' +import { dropdownSelect, pageAction, userSessionFile } from './lib' import Chance from 'chance' const c = new Chance() @@ -7,22 +7,25 @@ test.describe.configure({ mode: 'parallel' }) test.use({ storageState: userSessionFile }) // test create, edit, verify, and delete of an EMAIL contact method -test('EMAIL contact method', async ({ page, browser, isMobile }) => { +test('EMAIL contact method', async ({ page, browser }) => { const name = 'pw-email ' + c.name() const email = 'pw-email-' + c.email() await page.goto('./profile') - if (isMobile) { - await page.click('[aria-label="Add Items"]') - await page.click('[aria-label="Create Contact Method"]') - } else { - await page.click('[title="Create Contact Method"]') - } + await pageAction(page, 'Create Contact Method', 'Create Method') await page.fill('input[name=name]', name) - await page.fill('input[name=type]', 'EMAIL') - await page.fill('input[name=value]', email) + + // ensure disclaimer is shown for voice call + await dropdownSelect(page, 'Destination Type', 'Voice Call') + + await expect( + page.locator('span', { hasText: 'test-disclaimer-text' }), + ).toBeVisible() + + await dropdownSelect(page, 'Destination Type', 'Email') + await page.fill('input[name=email-address]', email) await page.click('[role=dialog] button[type=submit]') const mail = await browser.newPage({ @@ -59,44 +62,63 @@ test('EMAIL contact method', async ({ page, browser, isMobile }) => { await page.fill('input[name=code]', code) await page.click('[role=dialog] button[type=submit]') - await page.locator('[role=dialog]').isHidden() + await expect(page.locator('[role=dialog]')).toBeHidden() // edit name and enable status updates - const updatedName = 'updated name' - await page - .locator('.MuiCard-root', { - has: page.locator('div > div > h2', { hasText: 'Contact Methods' }), - }) - .locator('li', { hasText: email }) - .locator('[aria-label="Other Actions"]') - .click() + const updatedName = 'updated name ' + c.name() + await page.click(`li:has-text("${email}") [aria-label="Other Actions"]`) await page.getByRole('menuitem', { name: 'Edit' }).click() await page.fill('input[name=name]', updatedName) await page.click('input[name=enableStatusUpdates]') await page.click('[role=dialog] button[type=submit]') + // We need to move the mouse, otherwise it will keep it's position over the submit button and activate the speed dial... + await page.mouse.move(0, 0) + await expect(page.locator('[role=dialog]')).toBeHidden() // open edit dialog to verify name change and status updates are enabled - await page - .locator('.MuiCard-root', { - has: page.locator('div > div > h2', { hasText: 'Contact Methods' }), - }) - .locator('li', { hasText: email }) - .locator('[aria-label="Other Actions"]') - .click() + await page.click(`li:has-text("${email}") [aria-label="Other Actions"]`) await page.getByRole('menuitem', { name: 'Edit' }).click() await expect(page.locator('input[name=name]')).toHaveValue(updatedName) await expect(page.locator('input[name=enableStatusUpdates]')).toBeChecked() await page.click('[role=dialog] button[type=submit]') - await page - .locator('.MuiCard-root', { - has: page.locator('div > div > h2', { hasText: 'Contact Methods' }), - }) - .locator('li', { hasText: email }) - .locator('[aria-label="Other Actions"]') - .click() + await page.mouse.move(0, 0) + await expect(page.locator('[role=dialog]')).toBeHidden() + + // verify deleting a notification rule (immediate by default) + await page.click( + `li:has-text("Immediately notify me via Email at ${email}") button`, + ) + + // click confirm + await page.getByRole('button', { name: 'Confirm' }).click() + await expect( + page.locator('li', { + hasText: `Immediately notify me via Email at ${email}`, + }), + ).toBeHidden() + + // verify adding a notification rule (delayed) + await pageAction(page, 'Add Notification Rule', 'Add Rule') + await dropdownSelect(page, 'Contact Method', updatedName) + await page.fill('input[name=delayMinutes]', '5') + await page.click('[role=dialog] button[type=submit]') + + await page.mouse.move(0, 0) + await expect(page.locator('[role=dialog]')).toBeHidden() + + await expect( + page.locator('li', { + hasText: `After 5 minutes notify me via Email at ${email}`, + }), + ).toBeVisible() + + await page.click(`li:has-text("${email}") [aria-label="Other Actions"]`) await page.getByRole('menuitem', { name: 'Delete' }).click() await page.getByRole('button', { name: 'Confirm' }).click() + + await page.mouse.move(0, 0) + await expect(page.locator('[role=dialog]')).toBeHidden() await page .locator('.MuiCard-root', { has: page.locator('div > div > h2', { hasText: 'Contact Methods' }), diff --git a/test/integration/escalation-policies.spec.ts b/test/integration/escalation-policies.spec.ts index 3bdb9d40e7..4eee79eb28 100644 --- a/test/integration/escalation-policies.spec.ts +++ b/test/integration/escalation-policies.spec.ts @@ -1,5 +1,5 @@ import { test, expect } from '@playwright/test' -import { baseURLFromFlags, userSessionFile } from './lib' +import { userSessionFile } from './lib' import Chance from 'chance' const c = new Chance() @@ -17,7 +17,7 @@ let epName: string test.beforeEach(async ({ page }) => { // create rotation rotName = 'rot-' + c.string({ length: 10, alpha: true }) - await page.goto(`${baseURLFromFlags(['dest-types'])}/rotations`) + await page.goto(`/rotations`) await page.getByRole('button', { name: 'Create Rotation' }).click() await page.fill('input[name=name]', rotName) await page.fill('textarea[name=description]', 'test rotation') @@ -27,7 +27,7 @@ test.beforeEach(async ({ page }) => { // create schedule schedName = 'sched-' + c.string({ length: 10, alpha: true }) - await page.goto(`${baseURLFromFlags(['dest-types'])}/schedules`) + await page.goto(`/schedules`) await page.getByRole('button', { name: 'Create Schedule' }).click() await page.fill('input[name=name]', schedName) await page.locator('button[type=submit]').click() @@ -36,7 +36,7 @@ test.beforeEach(async ({ page }) => { // create EP epName = 'ep-' + c.string({ length: 10, alpha: true }) - await page.goto(`${baseURLFromFlags(['dest-types'])}/escalation-policies`) + await page.goto(`/escalation-policies`) await page.getByRole('button', { name: 'Create Escalation Policy' }).click() await page.fill('input[name=name]', epName) await page.locator('button[type=submit]').click() @@ -46,29 +46,64 @@ test.beforeEach(async ({ page }) => { test.afterEach(async ({ page }) => { // delete rotation - await page.goto(`${baseURLFromFlags(['dest-types'])}/rotations/${rotID}`) + await page.goto(`/rotations/${rotID}`) await page.click('[data-testid="DeleteIcon"]') await page.click('button:has-text("Confirm")') // delete schedule - await page.goto(`${baseURLFromFlags(['dest-types'])}/schedules/${schedID}`) + await page.goto(`/schedules/${schedID}`) await page.click('[data-testid="DeleteIcon"]') await page.click('button:has-text("Confirm")') // delete EP - await page.goto( - `${baseURLFromFlags(['dest-types'])}/escalation-policies/${epID}`, - ) + await page.goto(`/escalation-policies/${epID}`) await page.click('[data-testid="DeleteIcon"]') await page.click('button:has-text("Confirm")') }) +test('check caption delay text while creating steps', async ({ page }) => { + await page.goto(`/escalation-policies/${epID}`) + + async function createStep(delayMinutes: string): Promise { + await page.getByRole('button', { name: 'Create Step' }).click() + await page.getByLabel('Destination Type').click() + await page.locator('li', { hasText: 'User' }).click() + await page.getByRole('combobox', { name: 'User', exact: true }).click() + await page + .getByRole('combobox', { name: 'User', exact: true }) + .fill('Admin McIntegrationFace') + await page + .locator('div[role=presentation]') + .locator('li', { hasText: 'Admin McIntegrationFace' }) + .click() + await page.getByRole('button', { name: 'Add Destination' }).click() + await expect( + page + .getByRole('dialog') + .getByTestId('destination-chip') + .filter({ hasText: 'Admin McIntegrationFace' }), + ).toBeVisible() + await page.locator('input[name=delayMinutes]').fill(delayMinutes) + await page.locator('button[type=submit]', { hasText: 'Submit' }).click() + } + + await createStep('5') + await expect( + page.getByText('Go back to step #1 after 5 minutes'), + ).toBeVisible() + await createStep('20') + await expect( + page.getByText('Move on to step #2 after 5 minutes'), + ).toBeVisible() + await expect( + page.getByText('Go back to step #1 after 20 minutes'), + ).toBeVisible() +}) + test('create escalation policy step using destination actions', async ({ page, }) => { - await page.goto( - `${baseURLFromFlags(['dest-types'])}/escalation-policies/${epID}`, - ) + await page.goto(`/escalation-policies/${epID}`) await page.getByRole('button', { name: 'Create Step' }).click() // add rotation @@ -79,7 +114,13 @@ test('create escalation policy step using destination actions', async ({ .getByRole('combobox', { name: 'Rotation', exact: true }) .fill(rotName) await page.locator('li', { hasText: rotName }).click() - await page.getByRole('button', { name: 'Add Action' }).click() + await page.getByRole('button', { name: 'Add Destination' }).click() + await expect( + page + .getByRole('dialog') + .getByTestId('destination-chip') + .filter({ hasText: rotName }), + ).toBeVisible() // add schedule await page.getByLabel('Destination Type').click() @@ -89,7 +130,13 @@ test('create escalation policy step using destination actions', async ({ .getByRole('combobox', { name: 'Schedule', exact: true }) .fill(schedName) await page.locator('li', { hasText: schedName }).click() - await page.getByRole('button', { name: 'Add Action' }).click() + await page.getByRole('button', { name: 'Add Destination' }).click() + await expect( + page + .getByRole('dialog') + .getByTestId('destination-chip') + .filter({ hasText: schedName }), + ).toBeVisible() // add user await page.getByLabel('Destination Type').click() @@ -99,7 +146,13 @@ test('create escalation policy step using destination actions', async ({ .getByRole('combobox', { name: 'User', exact: true }) .fill('Admin McIntegrationFace') await page.locator('li', { hasText: 'Admin McIntegrationFace' }).click() - await page.getByRole('button', { name: 'Add Action' }).click() + await page.getByRole('button', { name: 'Add Destination' }).click() + await expect( + page + .getByRole('dialog') + .getByTestId('destination-chip') + .filter({ hasText: 'Admin McIntegrationFace' }), + ).toBeVisible() await page.locator('button[type=submit]', { hasText: 'Submit' }).click() @@ -109,13 +162,13 @@ test('create escalation policy step using destination actions', async ({ const rotLink = await page.locator('a', { hasText: rotName }) await expect(rotLink).toHaveAttribute( 'href', - `${baseURLFromFlags(['dest-types'])}/rotations/${rotID}`, + new RegExp(`/rotations/${rotID}$`), ) const schedLink = await page.locator('a', { hasText: schedName }) await expect(schedLink).toHaveAttribute( 'href', - `${baseURLFromFlags(['dest-types'])}/schedules/${schedID}`, + new RegExp(`/schedules/${schedID}$`), ) await expect( diff --git a/test/integration/first-login.spec.ts b/test/integration/first-login.spec.ts new file mode 100644 index 0000000000..b501a85225 --- /dev/null +++ b/test/integration/first-login.spec.ts @@ -0,0 +1,43 @@ +import { test, expect } from '@playwright/test' +import { dropdownSelect, userSessionFile } from './lib' +import Chance from 'chance' +const c = new Chance() + +test.describe.configure({ mode: 'parallel' }) +test.use({ storageState: userSessionFile }) + +// test create, edit, verify, and delete of an EMAIL contact method +test('first time setup', async ({ page }) => { + await page.goto('.?isFirstLogin=1') + // ensure dialog is shown + await expect( + page.locator('[role=dialog]', { hasText: 'Welcome to GoAlert' }), + ).toBeVisible() + + const name = 'first-setup-email ' + c.name() + const email = 'first-setup-email-' + c.email() + await page.fill('input[name=name]', name) + await dropdownSelect(page, 'Destination Type', 'Email') + await page.fill('input[name=email-address]', email) + await page.click('[role=dialog] button[type=submit]') + await expect( + page.locator('[role=dialog]', { hasText: 'Verify Contact Method' }), + ).toBeVisible() + + // cancel out + await page.locator('[role=dialog] button', { hasText: 'Cancel' }).click() + + // ensure dialog is not shown + await expect(page.locator('[role=dialog]')).toBeHidden() + + await page.goto('./profile') + await page.click(`li:has-text("${email}") [aria-label="Other Actions"]`) + + await page.getByRole('menuitem', { name: 'Delete' }).click() + await page.getByRole('button', { name: 'Confirm' }).click() + + await expect(page.locator('[role=dialog]')).toBeHidden() + await expect( + page.locator(`li:has-text("${email}") [aria-label="Other Actions"]`), + ).toBeHidden() +}) diff --git a/test/integration/lib/index.ts b/test/integration/lib/index.ts index bd7f5e92ac..232232cdc2 100644 --- a/test/integration/lib/index.ts +++ b/test/integration/lib/index.ts @@ -1,2 +1,3 @@ export * from './login' export * from './flags' +export * from './select' diff --git a/test/integration/lib/integration-key.ts b/test/integration/lib/integration-key.ts index 3fb2fd9d5e..3d2e822ba3 100644 --- a/test/integration/lib/integration-key.ts +++ b/test/integration/lib/integration-key.ts @@ -2,7 +2,7 @@ import { Page, expect } from '@playwright/test' export async function createIntegrationKey( page: Page, - intKey: number, + intKey: string, isMobile: boolean, ): Promise { await page.getByRole('link', { name: 'Integration Keys' }).click() diff --git a/test/integration/lib/label.ts b/test/integration/lib/label.ts index 50994cb855..28218144ec 100644 --- a/test/integration/lib/label.ts +++ b/test/integration/lib/label.ts @@ -3,7 +3,7 @@ import { Page, expect } from '@playwright/test' export async function createLabel( page: Page, key: string, - value: number, + value: string, isMobile: boolean, ): Promise { // Create a label for the service diff --git a/test/integration/lib/select.ts b/test/integration/lib/select.ts new file mode 100644 index 0000000000..0f5e3e4231 --- /dev/null +++ b/test/integration/lib/select.ts @@ -0,0 +1,51 @@ +import { Page, expect } from '@playwright/test' + +export async function dropdownSelect( + page: Page, + fieldLabel: string, + optionLabel: string, +): Promise { + await page + .locator('div', { has: page.locator('label', { hasText: fieldLabel }) }) + .locator('[role=combobox]') + .click() + + await page.locator('[role=option]', { hasText: optionLabel }).click() +} + +export async function pageAction( + page: Page, + mobileAction: string, + wideAction: string = mobileAction, +): Promise { + const vp = page.viewportSize() + const mobile = vp && vp.width < 400 + if (mobile) { + const hasPopup = await page + .locator('button[data-cy="page-fab"]') + .getAttribute('aria-haspopup') + if (hasPopup) { + await page.hover('button[data-cy="page-fab"]') + await expect( + await page.locator('button[data-cy="page-fab"]'), + ).toHaveAttribute('aria-expanded', 'true') + } + + const action = await page.getByLabel(mobileAction) + // click if it's already a button + if ((await action.locator('button').count()) > 0) { + await action.locator('button').click() + } else { + await action.click() + } + + if (hasPopup) { + await expect( + await page.locator('button[data-cy="page-fab"]'), + ).toHaveAttribute('aria-expanded', 'false') + } + return + } + + await page.getByRole('button', { name: wideAction }).click() +} diff --git a/test/integration/lib/service.ts b/test/integration/lib/service.ts index 798a3aee6e..26f91a273c 100644 --- a/test/integration/lib/service.ts +++ b/test/integration/lib/service.ts @@ -4,7 +4,7 @@ export async function createService( page: Page, name: string, description: string, -): Promise { +): Promise { await page.goto('./services') await page.getByRole('button', { name: 'Create Service' }).click() @@ -12,4 +12,7 @@ export async function createService( await page.fill('textarea[name=description]', description) await page.click('[role=dialog] button[type=submit]') + await page.waitForURL(/services\/[0-9a-f]+/) + + return page.url() } diff --git a/test/integration/setup/goalert-config.json b/test/integration/setup/goalert-config.json index 4679552864..512803c258 100644 --- a/test/integration/setup/goalert-config.json +++ b/test/integration/setup/goalert-config.json @@ -1,4 +1,10 @@ { + "General": { + "NotificationDisclaimer": "test-disclaimer-text" + }, + "Twilio": { + "Enable": true + }, "SMTP": { "Enable": true, "From": "goalert@localhost", diff --git a/test/integration/uik.spec.ts b/test/integration/uik.spec.ts new file mode 100644 index 0000000000..27d9293e10 --- /dev/null +++ b/test/integration/uik.spec.ts @@ -0,0 +1,224 @@ +import { test, expect, Page } from '@playwright/test' +import { + baseURLFromFlags, + dropdownSelect, + pageAction, + userSessionFile, +} from './lib' +import Chance from 'chance' +import { createService } from './lib/service' +const c = new Chance() + +test.describe.configure({ mode: 'parallel' }) +test.use({ + storageState: userSessionFile, + baseURL: baseURLFromFlags(['univ-keys']), +}) + +async function setup(page: Page, isMobile: boolean): Promise { + const intKeyName = 'uik-key ' + c.name() + const serviceName = 'uik-service ' + c.name() + const serviceDescription = c.sentence() + const serviceURL = await createService(page, serviceName, serviceDescription) + + await page.getByRole('link', { name: 'Integration Keys' }).click() + + await pageAction(page, 'Create Integration Key') + await page.fill('input[name=name]', intKeyName) + await dropdownSelect(page, 'Type', 'Universal Integration Key') + await page.click('button[type=submit]') + await page.waitForURL(/\/services\/.+\/integration-keys\/.+$/) + + const bread = page.locator('header nav') + await expect(bread.getByRole('link', { name: 'Services' })).toBeVisible() + if (!isMobile) { + // mobile collapses these + await expect(bread.getByRole('link', { name: serviceName })).toBeVisible() + await expect( + bread.getByRole('link', { name: 'Integration Keys' }), + ).toBeVisible() + } + await expect(bread.getByRole('link', { name: intKeyName })).toBeVisible() + + return serviceURL +} + +test('create universal key, add rule with action', async ({ + page, + isMobile, +}) => { + await setup(page, isMobile) + const ruleName = c.name() + const ruleDesc = c.sentence({ words: 5 }) + const ruleNewDesc = c.sentence({ words: 3 }) + + // create a rule + await page.getByRole('button', { name: 'Create Rule' }).click() + await page.fill('input[name=name]', ruleName) + await page.fill('input[name=description]', ruleDesc) + await page.fill('textarea[name=conditionExpr]', 'true') + + // add an action to the rule and submit + await dropdownSelect(page, 'Destination Type', 'Alert') + await expect( + page + .locator('#dialog-form') + .getByTestId('actions-list') + .getByTestId('no-actions'), + ).toBeVisible() + await page.getByRole('button', { name: 'Add Action' }).click() + await expect( + page.getByLabel('Create Rule').getByTestId('no-actions'), + ).toBeHidden() + await expect( + page.locator('span', { hasText: 'Create new alert' }), + ).toBeVisible() + await page.getByRole('button', { name: 'Submit' }).click() + await expect(page.locator('[role=dialog]')).toBeHidden() + + // verify + await expect(page.locator('body')).toContainText(ruleName) + await expect(page.locator('body')).toContainText(ruleDesc) + + // start editing + await page.getByRole('button', { name: 'Other Actions' }).click() + await page.getByRole('menuitem', { name: 'Edit' }).click() + + // update description, delete the action, submit + await page.fill('input[name=description]', ruleNewDesc) + await page + .locator('div', { hasText: 'Create new alert' }) + .locator('[data-testid=CancelIcon]') + .click() + await expect( + page + .locator('#dialog-form') + .getByTestId('actions-list') + .getByTestId('no-actions'), + ).toBeVisible() + await page.getByRole('button', { name: 'Submit' }).click() + + // see warning for no actions- check and submit + await expect(page.getByText('WARNING: No actions')).toBeVisible() + await page + .locator('label', { hasText: 'I acknowledge the impact of this' }) + .locator('input[type=checkbox]') + .click() + await page.getByRole('button', { name: 'Retry' }).click() + await expect(page.locator('[role=dialog]')).toBeHidden() + + // verify name does not change, with new description + await expect(page.locator('body')).toContainText(ruleName) + await expect(page.locator('body')).toContainText(ruleNewDesc) + + // delete the rule + await page.getByRole('button', { name: 'Other Actions' }).click() + await page.getByRole('menuitem', { name: 'Delete' }).click() + expect( + page.locator('[data-cy=dialog-title]', { hasText: 'Are you sure?' }), + ).toBeVisible() + await page.getByRole('button', { name: 'Confirm' }).click() + + // verify + await expect(page.locator('[data-cy=list-empty-message]')).toHaveText( + 'No rules exist for this integration key.', + ) +}) + +test('create primary auth token then promote a second auth token', async ({ + page, + playwright, + isMobile, +}) => { + const serviceURL = await setup(page, isMobile) + + await expect(page.locator('[data-cy=details]')).toContainText( + 'Auth Token: N/A', + ) + + await page.getByRole('button', { name: 'Generate Auth Token' }).click() + await page.getByRole('button', { name: 'Generate' }).click() + + const origPrimaryToken = await page + .getByRole('button', { name: 'Copy' }) + .textContent() + expect(origPrimaryToken).not.toBeNull() + await page.getByRole('button', { name: 'Done' }).click() + + function tokenHint(token: string): string { + return token.slice(0, 2) + '...' + token.slice(-4) + } + + await expect(page.locator('[data-cy=details]')).toContainText( + tokenHint(origPrimaryToken as string), + ) + + const req = await playwright.request.newContext({ + baseURL: baseURLFromFlags(['univ-keys']), + extraHTTPHeaders: { 'Content-Type': 'application/json', Cookie: '' }, + }) + + async function testKey(key: string, status: number): Promise { + const auth = { Authorization: key ? 'Bearer ' + key : '' } + const resp = await req.post('/api/v2/uik', { headers: auth, data: {} }) + expect(resp.status()).toBe(status) + } + + await testKey('', 401) + await testKey(origPrimaryToken as string, 204) + + await page.getByRole('button', { name: 'Generate Secondary Token' }).click() + await page.getByRole('button', { name: 'Generate' }).click() + const firstSecondaryToken = await page + .getByRole('button', { name: 'Copy' }) + .textContent() + expect(origPrimaryToken).not.toBeNull() + await page.getByRole('button', { name: 'Done' }).click() + + await expect(page.locator('[data-cy=details]')).toContainText( + tokenHint(origPrimaryToken as string), + ) + await expect(page.locator('[data-cy=details]')).toContainText( + tokenHint(firstSecondaryToken as string), + ) + + // ensure both work + await testKey(origPrimaryToken as string, 204) + await testKey(firstSecondaryToken as string, 204) + + await page.getByRole('button', { name: 'Delete Secondary Token' }).click() + await page.getByLabel('I acknowledge the impact of this action').click() + await page.getByRole('button', { name: 'Submit' }).click() + await expect(page.locator('[data-cy=details]')).not.toContainText( + tokenHint(firstSecondaryToken as string), + ) + await testKey(origPrimaryToken as string, 204) + await testKey(firstSecondaryToken as string, 401) + + await page.getByRole('button', { name: 'Generate Secondary Token' }).click() + await page.getByRole('button', { name: 'Generate' }).click() + const secondSecondaryToken = await page + .getByRole('button', { name: 'Copy' }) + .textContent() + expect(secondSecondaryToken).not.toBeNull() + await page.getByRole('button', { name: 'Done' }).click() + + await page.getByRole('button', { name: 'Promote Secondary Token' }).click() + await page.getByLabel('I acknowledge the impact of this action').click() + await page.getByRole('button', { name: 'Promote Key' }).click() + + await expect(page.locator('[data-cy=details]')).toContainText( + tokenHint(secondSecondaryToken as string), + ) + await expect(page.locator('[data-cy=details]')).not.toContainText( + tokenHint(origPrimaryToken as string), + ) + + await testKey(origPrimaryToken as string, 401) + await testKey(secondSecondaryToken as string, 204) + + await page.goto(serviceURL) + await page.getByRole('button', { name: 'Delete' }).click() + await page.getByRole('button', { name: 'Confirm' }).click() + await page.waitForURL(/services$/) +}) diff --git a/test/smoke/actionvalidate_test.go b/test/smoke/actionvalidate_test.go new file mode 100644 index 0000000000..19e4997f2d --- /dev/null +++ b/test/smoke/actionvalidate_test.go @@ -0,0 +1,51 @@ +package smoke + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/target/goalert/expflag" + "github.com/target/goalert/graphql2" + "github.com/target/goalert/test/smoke/harness" +) + +const actionValidQuery = ` +query TestActionValid($input: ActionInput!) { + actionInputValidate(input: $input) +} +` + +// TestActionValid tests the action validation query. +func TestActionValid(t *testing.T) { + t.Parallel() + + h := harness.NewHarnessWithFlags(t, "", "", expflag.FlagSet{expflag.UnivKeys}) + defer h.Close() + + type params map[string]string + check := func(destType string, dest, dyn params) harness.QLResponse { + t.Helper() + var vars struct { + Input graphql2.ActionInput `json:"input"` + } + vars.Input.Params = dyn + vars.Input.Dest = &graphql2.DestinationInput{Type: destType, Args: dest} + + return *h.GraphQLQueryUserVarsT(t, harness.DefaultGraphQLAdminUserID, actionValidQuery, "TestActionValid", vars) + } + + res := check("invalid", params{}, params{}) + if assert.Len(t, res.Errors, 1) { + assert.EqualValues(t, "actionInputValidate.input.dest.type", res.Errors[0].Path) + assert.Equal(t, "unsupported destination type: invalid", res.Errors[0].Message) + assert.Equal(t, "INVALID_INPUT_VALUE", res.Errors[0].Extensions.Code) + } + + res = check("builtin-alert", params{}, params{"invalid-expr": `foo+`}) + if assert.Len(t, res.Errors, 1) { + assert.EqualValues(t, "actionInputValidate.input.params", res.Errors[0].Path) + assert.Contains(t, res.Errors[0].Message, "unexpected token") + assert.Equal(t, "INVALID_MAP_FIELD_VALUE", res.Errors[0].Extensions.Code) + assert.Equal(t, "invalid-expr", res.Errors[0].Extensions.Key) + } +} diff --git a/test/smoke/harness/graphql.go b/test/smoke/harness/graphql.go index 6114b77709..fe55a0a010 100644 --- a/test/smoke/harness/graphql.go +++ b/test/smoke/harness/graphql.go @@ -162,9 +162,16 @@ func (h *Harness) GraphQLQueryUserVarsT(t *testing.T, userID, query, opName stri break } defer resp.Body.Close() + + data, err := io.ReadAll(resp.Body) + if err != nil { + t.Fatal("failed to read response body:", err) + } + var r QLResponse - err = json.NewDecoder(resp.Body).Decode(&r) + err = json.Unmarshal(data, &r) if err != nil { + t.Log("Response:", string(data)) t.Fatal("failed to parse GraphQL response:", err) } return &r @@ -173,5 +180,38 @@ func (h *Harness) GraphQLQueryUserVarsT(t *testing.T, userID, query, opName stri // QLResponse is a generic GraphQL response. type QLResponse struct { Data json.RawMessage - Errors []struct{ Message string } + Errors []struct { + Message string + Path QLPath + Extensions struct { + Code string + Key string + FieldID string + } + } +} + +type QLPath string + +func (p *QLPath) UnmarshalJSON(data []byte) error { + var parts []any + err := json.Unmarshal(data, &parts) + if err != nil { + return err + } + + var strParts []string + for _, p := range parts { + switch v := p.(type) { + case string: + strParts = append(strParts, v) + case float64: + strParts = append(strParts, strconv.Itoa(int(v))) + default: + return errors.Errorf("unexpected path part type: %T", p) + } + } + + *p = QLPath(strings.Join(strParts, ".")) + return nil } diff --git a/test/smoke/harness/harness.go b/test/smoke/harness/harness.go index 5ca8d6f940..d264de8b4f 100644 --- a/test/smoke/harness/harness.go +++ b/test/smoke/harness/harness.go @@ -22,7 +22,6 @@ import ( "github.com/google/uuid" "github.com/jackc/pgx/v5" - pgx5 "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/stdlib" "github.com/pkg/errors" "github.com/stretchr/testify/assert" @@ -553,7 +552,7 @@ func (h *Harness) dumpDB() { h.t.Fatalf("failed to create abs dump path: %v", err) } - conn, err := pgx5.Connect(context.Background(), h.dbURL) + conn, err := pgx.Connect(context.Background(), h.dbURL) if err != nil { h.t.Fatalf("failed to get db connection: %v", err) } diff --git a/validation/validate/range.go b/validation/validate/range.go index 1972aee075..6fdc15f728 100644 --- a/validation/validate/range.go +++ b/validation/validate/range.go @@ -1,10 +1,33 @@ package validate import ( - "github.com/target/goalert/validation" "strconv" + + "github.com/target/goalert/validation" ) +// Len will ensure a slice has at least min and at most max items. +func Len[T any](fname string, val []T, min, max int) error { + if len(val) < min { + return validation.NewFieldError(fname, "must have at least "+strconv.Itoa(min)+" items") + } + if len(val) > max { + return validation.NewFieldError(fname, "must have at most "+strconv.Itoa(max)+" items") + } + return nil +} + +// MapLen will ensure a map has at least min and at most max items. +func MapLen[K comparable, V any](fname string, val map[K]V, min, max int) error { + if len(val) < min { + return validation.NewFieldError(fname, "must have at least "+strconv.Itoa(min)+" items") + } + if len(val) > max { + return validation.NewFieldError(fname, "must have at most "+strconv.Itoa(max)+" items") + } + return nil +} + // Range will ensure a value is between min and max (inclusive). // A FieldError is returned otherwise. func Range(fname string, val, min, max int) error { diff --git a/web/src/app/alerts/CreateAlertDialog/StepContent/CreateAlertConfirm.tsx b/web/src/app/alerts/CreateAlertDialog/StepContent/CreateAlertConfirm.tsx index 2fc13843bd..beca0b3e01 100644 --- a/web/src/app/alerts/CreateAlertDialog/StepContent/CreateAlertConfirm.tsx +++ b/web/src/app/alerts/CreateAlertDialog/StepContent/CreateAlertConfirm.tsx @@ -1,7 +1,7 @@ import React, { ReactNode } from 'react' import { Typography, Grid, Divider } from '@mui/material' import makeStyles from '@mui/styles/makeStyles' -import { ServiceChip } from '../../../util/Chips' +import { ServiceChip } from '../../../util/ServiceChip' import { FormField } from '../../../forms' import Markdown from '../../../util/Markdown' diff --git a/web/src/app/alerts/CreateAlertDialog/StepContent/CreateAlertServiceSelect.tsx b/web/src/app/alerts/CreateAlertDialog/StepContent/CreateAlertServiceSelect.tsx index b48b2e1afa..228c09ca27 100644 --- a/web/src/app/alerts/CreateAlertDialog/StepContent/CreateAlertServiceSelect.tsx +++ b/web/src/app/alerts/CreateAlertDialog/StepContent/CreateAlertServiceSelect.tsx @@ -20,7 +20,7 @@ import makeStyles from '@mui/styles/makeStyles' import ServiceLabelFilterContainer from '../../../services/ServiceFilterContainer' import { Search as SearchIcon } from '@mui/icons-material' import { FavoriteIcon } from '../../../util/SetFavoriteButton' -import { ServiceChip } from '../../../util/Chips' +import { ServiceChip } from '../../../util/ServiceChip' import AddIcon from '@mui/icons-material/Add' import _ from 'lodash' import getServiceFilters from '../../../util/getServiceFilters' diff --git a/web/src/app/details/CardActions.tsx b/web/src/app/details/CardActions.tsx index 2b851afab8..9966c6c0f3 100644 --- a/web/src/app/details/CardActions.tsx +++ b/web/src/app/details/CardActions.tsx @@ -4,6 +4,7 @@ import Button, { ButtonProps } from '@mui/material/Button' import MUICardActions from '@mui/material/CardActions' import IconButton from '@mui/material/IconButton' import Tooltip from '@mui/material/Tooltip' +import { Theme } from '@mui/material' interface CardActionProps { primaryActions?: Array @@ -22,18 +23,21 @@ export type Action = { ButtonProps?: ButtonProps } -const useStyles = makeStyles({ +const useStyles = makeStyles((theme: Theme) => ({ cardActions: { alignItems: 'flex-end', // aligns icon buttons to bottom of container }, primaryActionsContainer: { padding: 8, width: '100%', + '& > button:not(:last-child)': { + marginRight: theme.spacing(2), + }, }, autoExpandWidth: { margin: '0 auto', }, -}) +})) export default function CardActions(p: CardActionProps): JSX.Element { const classes = useStyles() diff --git a/web/src/app/dialogs/FormDialog.jsx b/web/src/app/dialogs/FormDialog.jsx index 501e653943..820050d80e 100644 --- a/web/src/app/dialogs/FormDialog.jsx +++ b/web/src/app/dialogs/FormDialog.jsx @@ -26,7 +26,7 @@ const useStyles = makeStyles((theme) => { }, dialogContent: { height: '100%', // parents of form need height set to properly function in Safari - paddingTop: '8px !important', // workaround for https://github.com/mui/material-ui/issues/31185 + paddingTop: '8px', }, formContainer: { width: '100%', @@ -63,6 +63,7 @@ function FormDialog(props) { fullHeight, disableBackdropClose, disablePortal, + disableSubmit, ...dialogProps } = props @@ -169,6 +170,7 @@ function FormDialog(props) { }} attemptCount={attemptCount} buttonText={primaryActionLabel || (confirm ? 'Confirm' : submitText)} + disabled={disableSubmit} loading={loading} type='submit' /> @@ -237,6 +239,8 @@ FormDialog.propTypes = { disablePortal: p.bool, // disable the portal behavior of the dialog + disableSubmit: p.bool, // disables the submit button while true + // overrides any of the main action button titles with this specific text primaryActionLabel: p.string, diff --git a/web/src/app/escalation-policies/PolicyCreateDialog.tsx b/web/src/app/escalation-policies/PolicyCreateDialog.tsx index 538cd71f7e..9732615893 100644 --- a/web/src/app/escalation-policies/PolicyCreateDialog.tsx +++ b/web/src/app/escalation-policies/PolicyCreateDialog.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react' -import { gql, useMutation } from '@apollo/client' +import { gql, useMutation } from 'urql' import { fieldErrors, nonFieldErrors } from '../util/errutil' import FormDialog from '../dialogs/FormDialog' import PolicyForm, { PolicyFormValue } from './PolicyForm' @@ -21,18 +21,9 @@ function PolicyCreateDialog(props: { onClose: () => void }): JSX.Element { favorite: true, } const [value, setValue] = useState(defaultValue) - const [createPolicy, createPolicyStatus] = useMutation(mutation, { - variables: { - input: { - name: value && value.name, - description: value && value.description, - repeat: value && value.repeat.value, - favorite: true, - }, - }, - }) + const [createPolicyStatus, createPolicy] = useMutation(mutation) - const { loading, data, error } = createPolicyStatus + const { fetching, data, error } = createPolicyStatus if (data && data.createEscalationPolicy) { return ( @@ -45,14 +36,26 @@ function PolicyCreateDialog(props: { onClose: () => void }): JSX.Element { return ( createPolicy()} + onSubmit={() => + createPolicy( + { + input: { + name: value && value.name, + description: value && value.description, + repeat: value && value.repeat.value, + favorite: true, + }, + }, + { additionalTypenames: ['EscalationPolicyConnection'] }, + ) + } form={ setValue(value)} /> diff --git a/web/src/app/escalation-policies/PolicyStepCreateDialogDest.stories.tsx b/web/src/app/escalation-policies/PolicyStepCreateDialog.stories.tsx similarity index 85% rename from web/src/app/escalation-policies/PolicyStepCreateDialogDest.stories.tsx rename to web/src/app/escalation-policies/PolicyStepCreateDialog.stories.tsx index 3ec7cdeae8..8421b3be05 100644 --- a/web/src/app/escalation-policies/PolicyStepCreateDialogDest.stories.tsx +++ b/web/src/app/escalation-policies/PolicyStepCreateDialog.stories.tsx @@ -1,16 +1,16 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' -import PolicyStepCreateDialogDest from './PolicyStepCreateDialogDest' +import PolicyStepCreateDialog from './PolicyStepCreateDialog' import { expect, fn, userEvent, waitFor, within } from '@storybook/test' -import { handleDefaultConfig, handleExpFlags } from '../storybook/graphql' +import { handleDefaultConfig } from '../storybook/graphql' import { HttpResponse, graphql } from 'msw' import { DestFieldValueError } from '../util/errtypes' const meta = { title: 'Escalation Policies/Steps/Create Dialog', - component: PolicyStepCreateDialogDest, + component: PolicyStepCreateDialog, render: function Component(args) { - return + return }, tags: ['autodocs'], args: { @@ -26,7 +26,6 @@ const meta = { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('ValidateDestination', ({ variables: vars }) => { return HttpResponse.json({ data: { @@ -35,7 +34,7 @@ const meta = { }) }), graphql.query('DestDisplayInfo', ({ variables: vars }) => { - if (vars.input.values[0].value.length !== 12) { + if (vars.input.args['phone-number'].length !== 12) { return HttpResponse.json({ errors: [ { message: 'generic error' }, @@ -54,7 +53,7 @@ const meta = { return HttpResponse.json({ data: { destinationDisplayInfo: { - text: vars.input.values[0].value, + text: vars.input.args['phone-number'], iconURL: 'builtin://phone-voice', iconAltText: 'Voice Call', }, @@ -81,7 +80,7 @@ const meta = { ], }, }, -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj @@ -98,14 +97,14 @@ export const CreatePolicyStep: Story = { const phoneInput = await canvas.findByLabelText('Phone Number') await userEvent.clear(phoneInput) await userEvent.type(phoneInput, '1222') - await userEvent.click(await canvas.findByText('Add Action')) + await userEvent.click(await canvas.findByText('Add Destination')) await expect(await canvas.findByText('Invalid number')).toBeVisible() await expect(await canvas.findByText('generic error')).toBeVisible() await userEvent.clear(phoneInput) await userEvent.type(phoneInput, '12225550123') - await userEvent.click(await canvas.findByText('Add Action')) + await userEvent.click(await canvas.findByText('Add Destination')) await waitFor(async function Icon() { await userEvent.click(await canvas.findByTestId('destination-chip')) diff --git a/web/src/app/escalation-policies/PolicyStepCreateDialog.tsx b/web/src/app/escalation-policies/PolicyStepCreateDialog.tsx index 2d1732e281..bdd0f03c93 100644 --- a/web/src/app/escalation-policies/PolicyStepCreateDialog.tsx +++ b/web/src/app/escalation-policies/PolicyStepCreateDialog.tsx @@ -1,82 +1,83 @@ -import React, { useState } from 'react' -import { gql, useMutation } from 'urql' -import { fieldErrors, nonFieldErrors } from '../util/errutil' -import PolicyStepForm from './PolicyStepForm' +import React, { useState, useEffect } from 'react' +import { CombinedError, gql, useMutation } from 'urql' import FormDialog from '../dialogs/FormDialog' - -interface Value { - targets?: { - id: string - type: string - name?: null | string - } - delayMinutes: string -} +import PolicyStepForm, { FormValue } from './PolicyStepForm' +import { useErrorConsumer } from '../util/ErrorConsumer' +import { getNotice } from './utils' const mutation = gql` - mutation ($input: CreateEscalationPolicyStepInput!) { + mutation createEscalationPolicyStep( + $input: CreateEscalationPolicyStepInput! + ) { createEscalationPolicyStep(input: $input) { id - delayMinutes - targets { - id - name - type - } } } ` -function PolicyStepCreateDialog(props: { +export default function PolicyStepCreateDialog(props: { escalationPolicyID: string + disablePortal?: boolean onClose: () => void }): JSX.Element { - const [value, setValue] = useState(null) - const defaultValue = { - targets: [], - delayMinutes: '15', - } + const [value, setValue] = useState({ + actions: [], + delayMinutes: 15, + }) const [createStepStatus, createStep] = useMutation(mutation) + const [err, setErr] = useState(null) + + const [hasSubmitted, setHasSubmitted] = useState(false) + const [hasConfirmed, setHasConfirmed] = useState(false) + const noActionsNoConf = value.actions.length === 0 && !hasConfirmed - const { fetching, error } = createStepStatus - const fieldErrs = fieldErrors(error) + useEffect(() => { + setErr(null) + }, [value]) + + useEffect(() => { + setErr(createStepStatus.error || null) + }, [createStepStatus.error]) + const errs = useErrorConsumer(err) return ( + onSubmit={() => { + if (noActionsNoConf) { + setHasSubmitted(true) + return + } + createStep( { input: { escalationPolicyID: props.escalationPolicyID, - delayMinutes: parseInt( - (value && value.delayMinutes) || defaultValue.delayMinutes, - ), - targets: (value && value.targets) || defaultValue.targets, + delayMinutes: +value.delayMinutes, + actions: value.actions, }, }, { additionalTypenames: ['EscalationPolicy'] }, ).then((result) => { - if (!result.error) { - props.onClose() - } + if (result.error) return + + props.onClose() }) - } + }} form={ setValue(value)} + disabled={createStepStatus.fetching} + value={value} + onChange={(value: FormValue) => setValue(value)} /> } + notices={getNotice(hasSubmitted, hasConfirmed, setHasConfirmed)} /> ) } - -export default PolicyStepCreateDialog diff --git a/web/src/app/escalation-policies/PolicyStepCreateDialogDest.tsx b/web/src/app/escalation-policies/PolicyStepCreateDialogDest.tsx deleted file mode 100644 index 170ee05d15..0000000000 --- a/web/src/app/escalation-policies/PolicyStepCreateDialogDest.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import React, { useState, useEffect } from 'react' -import { CombinedError, gql, useMutation } from 'urql' -import { splitErrorsByPath } from '../util/errutil' -import FormDialog from '../dialogs/FormDialog' -import PolicyStepFormDest, { FormValue } from './PolicyStepFormDest' -import { errorPaths } from '../users/UserContactMethodFormDest' - -const mutation = gql` - mutation createEscalationPolicyStep( - $input: CreateEscalationPolicyStepInput! - ) { - createEscalationPolicyStep(input: $input) { - id - } - } -` - -function PolicyStepCreateDialogDest(props: { - escalationPolicyID: string - disablePortal?: boolean - onClose: () => void -}): JSX.Element { - const [value, setValue] = useState({ - actions: [], - delayMinutes: 15, - }) - - const [createStepStatus, createStep] = useMutation(mutation) - const [err, setErr] = useState(null) - - useEffect(() => { - setErr(null) - }, [value]) - - useEffect(() => { - setErr(createStepStatus.error || null) - }, [createStepStatus.error]) - - const [formErrors, otherErrs] = splitErrorsByPath( - err, - errorPaths('destinationDisplayInfo.input'), - ) - - return ( - { - createStep( - { - input: { - escalationPolicyID: props.escalationPolicyID, - delayMinutes: +value.delayMinutes, - actions: value.actions, - }, - }, - { additionalTypenames: ['EscalationPolicy'] }, - ).then((result) => { - if (result.error) return - - props.onClose() - }) - }} - form={ - setValue(value)} - /> - } - /> - ) -} - -export default PolicyStepCreateDialogDest diff --git a/web/src/app/escalation-policies/PolicyStepDeleteDialog.tsx b/web/src/app/escalation-policies/PolicyStepDeleteDialog.tsx index fba2e5879e..c7f388db02 100644 --- a/web/src/app/escalation-policies/PolicyStepDeleteDialog.tsx +++ b/web/src/app/escalation-policies/PolicyStepDeleteDialog.tsx @@ -23,7 +23,7 @@ const mutation = gql` } ` -function PolicyStepDeleteDialog(props: { +export default function PolicyStepDeleteDialog(props: { escalationPolicyID: string stepID: string onClose: () => void @@ -76,5 +76,3 @@ function PolicyStepDeleteDialog(props: { /> ) } - -export default PolicyStepDeleteDialog diff --git a/web/src/app/escalation-policies/PolicyStepEditDialogDest.stories.tsx b/web/src/app/escalation-policies/PolicyStepEditDialog.stories.tsx similarity index 81% rename from web/src/app/escalation-policies/PolicyStepEditDialogDest.stories.tsx rename to web/src/app/escalation-policies/PolicyStepEditDialog.stories.tsx index 82fa931d61..e60fa47ad3 100644 --- a/web/src/app/escalation-policies/PolicyStepEditDialogDest.stories.tsx +++ b/web/src/app/escalation-policies/PolicyStepEditDialog.stories.tsx @@ -1,17 +1,17 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' -import PolicyStepEditDialogDest from './PolicyStepEditDialogDest' +import PolicyStepEditDialog from './PolicyStepEditDialog' import { expect, fn, userEvent, waitFor, within } from '@storybook/test' -import { handleDefaultConfig, handleExpFlags } from '../storybook/graphql' +import { handleDefaultConfig } from '../storybook/graphql' import { HttpResponse, graphql } from 'msw' import { DestFieldValueError } from '../util/errtypes' -import { EscalationPolicyStep } from '../../schema' +import { Destination, EscalationPolicyStep } from '../../schema' const meta = { title: 'Escalation Policies/Steps/Edit Dialog', - component: PolicyStepEditDialogDest, + component: PolicyStepEditDialog, render: function Component(args) { - return + return }, tags: ['autodocs'], args: { @@ -29,7 +29,6 @@ const meta = { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('ValidateDestination', ({ variables: vars }) => { return HttpResponse.json({ data: { @@ -38,7 +37,7 @@ const meta = { }) }), graphql.query('DestDisplayInfo', ({ variables: vars }) => { - if (vars.input.values[0].value.length !== 12) { + if (vars.input.args['phone-number'].length !== 12) { return HttpResponse.json({ errors: [ { message: 'generic error' }, @@ -57,7 +56,7 @@ const meta = { return HttpResponse.json({ data: { destinationDisplayInfo: { - text: vars.input.values[0].value, + text: vars.input.args['phone-number'], iconURL: 'builtin://phone-voice', iconAltText: 'Voice Call', }, @@ -77,10 +76,8 @@ const meta = { actions: [ { type: 'single-field', - values: [ - { fieldID: 'phone-number', value: '+19995550123' }, - ], - }, + args: { 'phone-number': '+19995550123' }, + } as Partial as Destination, ], } as EscalationPolicyStep, ], @@ -105,7 +102,7 @@ const meta = { ], }, }, -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj @@ -134,20 +131,29 @@ export const UpdatePolicyStep: Story = { const phoneInput = await canvas.findByLabelText('Phone Number') await userEvent.clear(phoneInput) await userEvent.type(phoneInput, '1222') - await userEvent.click(await canvas.findByText('Add Action')) + await userEvent.click(await canvas.findByText('Add Destination')) await expect(await canvas.findByText('Invalid number')).toBeVisible() await expect(await canvas.findByText('generic error')).toBeVisible() + await waitFor(async function AddDestFinish() { + await expect(phoneInput).not.toBeDisabled() + }) + await userEvent.clear(phoneInput) await userEvent.type(phoneInput, '12225550123') - await userEvent.click(await canvas.findByText('Add Action')) + await userEvent.click(await canvas.findByText('Add Destination')) await waitFor(async function Icon() { - await userEvent.click(await canvas.findByTestId('destination-chip')) + await expect( + await canvas.findAllByTestId('destination-chip'), + ).toHaveLength(2) }) const delayField = await canvas.findByLabelText('Delay (minutes)') + await waitFor(async function AddDestFinish() { + await expect(delayField).not.toBeDisabled() + }) await userEvent.clear(delayField) await userEvent.type(delayField, '999') await userEvent.click(await canvas.findByText('Submit')) diff --git a/web/src/app/escalation-policies/PolicyStepEditDialog.tsx b/web/src/app/escalation-policies/PolicyStepEditDialog.tsx index ea54d33fb9..466191e77d 100644 --- a/web/src/app/escalation-policies/PolicyStepEditDialog.tsx +++ b/web/src/app/escalation-policies/PolicyStepEditDialog.tsx @@ -1,69 +1,113 @@ import React, { useState } from 'react' -import { gql, useMutation } from 'urql' -import { fieldErrors, nonFieldErrors } from '../util/errutil' -import PolicyStepForm from './PolicyStepForm' +import { gql, useMutation, useQuery } from 'urql' +import { splitErrorsByPath } from '../util/errutil' import FormDialog from '../dialogs/FormDialog' -import { UpdateEscalationPolicyStepInput } from '../../schema' +import PolicyStepForm, { FormValue } from './PolicyStepForm' +import { + Destination, + EscalationPolicy, + UpdateEscalationPolicyStepInput, +} from '../../schema' +import { getNotice } from './utils' interface PolicyStepEditDialogProps { escalationPolicyID: string onClose: () => void - step: UpdateEscalationPolicyStepInput + stepID: string + disablePortal?: boolean } const mutation = gql` - mutation ($input: UpdateEscalationPolicyStepInput!) { + mutation UpdateEPStep($input: UpdateEscalationPolicyStepInput!) { updateEscalationPolicyStep(input: $input) } ` -function PolicyStepEditDialog(props: PolicyStepEditDialogProps): JSX.Element { - const [value, setValue] = useState( - null, +const query = gql` + query GetEPStep($id: ID!) { + escalationPolicy(id: $id) { + id + steps { + id + delayMinutes + actions { + type + args + } + } + } + } +` + +export default function PolicyStepEditDialog( + props: PolicyStepEditDialogProps, +): React.ReactNode { + const [stepQ] = useQuery<{ escalationPolicy: EscalationPolicy }>({ + query, + variables: { id: props.escalationPolicyID }, + }) + const step = stepQ.data?.escalationPolicy.steps.find( + (s) => s.id === props.stepID, ) - const defaultValue = { - targets: props.step?.targets?.map(({ id, type }) => ({ id, type })), - delayMinutes: props.step?.delayMinutes?.toString(), - } + if (!step) throw new Error('Step not found') - const [editStepMutationStatus, editStepMutation] = useMutation(mutation) + const [value, setValue] = useState({ + actions: (step.actions || []).map((a: Destination) => ({ + // remove extraneous fields + type: a.type, + args: a.args, + })), + delayMinutes: step.delayMinutes, + }) - const { fetching, error } = editStepMutationStatus - const fieldErrs = fieldErrors(error) + const [editStepStatus, editStep] = useMutation(mutation) + + const [hasSubmitted, setHasSubmitted] = useState(false) + const [hasConfirmed, setHasConfirmed] = useState(false) + const noActionsNoConf = value.actions.length === 0 && !hasConfirmed + + // Edit dialog has no errors to be handled by the form: + // - actions field has it's own validation + // - errors on existing actions are not handled specially, and just display in the dialog (i.e., duplicates) + // - the delay field has no validation, and is automatically clamped to the min/max values by the backend + const [, errs] = splitErrorsByPath(editStepStatus.error, []) return ( - editStepMutation( + onSubmit={() => { + if (noActionsNoConf) { + setHasSubmitted(true) + return + } + + return editStep( { input: { - id: props.step.id, - delayMinutes: - (value && value.delayMinutes) || defaultValue.delayMinutes, - targets: (value && value.targets) || defaultValue.targets, - }, + id: props.stepID, + delayMinutes: +value.delayMinutes, + actions: value.actions, + } satisfies UpdateEscalationPolicyStepInput, }, { additionalTypenames: ['EscalationPolicy'] }, ).then((result) => { if (!result.error) props.onClose() }) - } + }} form={ setValue(value)} + disabled={editStepStatus.fetching} + value={value} + onChange={(value: FormValue) => setValue(value)} /> } + notices={getNotice(hasSubmitted, hasConfirmed, setHasConfirmed)} /> ) } - -export default PolicyStepEditDialog diff --git a/web/src/app/escalation-policies/PolicyStepEditDialogDest.tsx b/web/src/app/escalation-policies/PolicyStepEditDialogDest.tsx deleted file mode 100644 index 211ac13d9d..0000000000 --- a/web/src/app/escalation-policies/PolicyStepEditDialogDest.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import React, { useState } from 'react' -import { gql, useMutation, useQuery } from 'urql' -import { splitErrorsByPath } from '../util/errutil' -import FormDialog from '../dialogs/FormDialog' -import PolicyStepFormDest, { FormValue } from './PolicyStepFormDest' -import { - Destination, - EscalationPolicy, - FieldValuePair, - UpdateEscalationPolicyStepInput, -} from '../../schema' - -interface PolicyStepEditDialogDestProps { - escalationPolicyID: string - onClose: () => void - stepID: string - disablePortal?: boolean -} - -const mutation = gql` - mutation UpdateEPStep($input: UpdateEscalationPolicyStepInput!) { - updateEscalationPolicyStep(input: $input) - } -` - -const query = gql` - query GetEPStep($id: ID!) { - escalationPolicy(id: $id) { - id - steps { - id - delayMinutes - actions { - type - values { - fieldID - value - } - } - } - } - } -` - -function PolicyStepEditDialogDest( - props: PolicyStepEditDialogDestProps, -): React.ReactNode { - const [stepQ] = useQuery<{ escalationPolicy: EscalationPolicy }>({ - query, - variables: { id: props.escalationPolicyID }, - }) - const step = stepQ.data?.escalationPolicy.steps.find( - (s) => s.id === props.stepID, - ) - - if (!step) throw new Error('Step not found') - - const [value, setValue] = useState({ - actions: (step.actions || []).map((a: Destination) => ({ - // remove extraneous fields - type: a.type, - values: a.values.map((v: FieldValuePair) => ({ - fieldID: v.fieldID, - value: v.value, - })), - })), - delayMinutes: step.delayMinutes, - }) - - const [editStepStatus, editStep] = useMutation(mutation) - - // Edit dialog has no errors to be handled by the form: - // - actions field has it's own validation - // - errors on existing actions are not handled specially, and just display in the dialog (i.e., duplicates) - // - the delay field has no validation, and is automatically clamped to the min/max values by the backend - const [a, errs] = splitErrorsByPath(editStepStatus.error, []) - console.log(a, errs, editStepStatus.error) - - return ( - - editStep( - { - input: { - id: props.stepID, - delayMinutes: +value.delayMinutes, - actions: value.actions, - } satisfies UpdateEscalationPolicyStepInput, - }, - { additionalTypenames: ['EscalationPolicy'] }, - ).then((result) => { - if (!result.error) props.onClose() - }) - } - form={ - setValue(value)} - /> - } - /> - ) -} - -export default PolicyStepEditDialogDest diff --git a/web/src/app/escalation-policies/PolicyStepForm.jsx b/web/src/app/escalation-policies/PolicyStepForm.jsx deleted file mode 100644 index b6c2bee5b7..0000000000 --- a/web/src/app/escalation-policies/PolicyStepForm.jsx +++ /dev/null @@ -1,310 +0,0 @@ -import React, { useState } from 'react' -import { PropTypes as p } from 'prop-types' -import { FormContainer, FormField } from '../forms' -import Badge from '@mui/material/Badge' -import Grid from '@mui/material/Grid' -import Stepper from '@mui/material/Stepper' -import Step from '@mui/material/Step' -import StepButton from '@mui/material/StepButton' -import StepContent from '@mui/material/StepContent' -import Typography from '@mui/material/Typography' -import makeStyles from '@mui/styles/makeStyles' -import { - RotationSelect, - ScheduleSelect, - SlackChannelSelect, - UserSelect, - ChanWebhookSelect, -} from '../selection' - -import { - RotateRight as RotationsIcon, - Today as SchedulesIcon, - Group as UsersIcon, - Webhook as WebhookIcon, -} from '@mui/icons-material' -import { SlackBW as SlackIcon } from '../icons/components/Icons' -import { Config } from '../util/RequireConfig' -import NumberField from '../util/NumberField' -import AppLink from '../util/AppLink' - -const useStyles = makeStyles({ - badge: { - top: -1, - right: -1, - }, - optional: { - float: 'left', - textAlign: 'left', - }, - label: { - paddingRight: '0.4em', - }, -}) - -function PolicyStepForm(props) { - const [step, setStep] = useState(0) - const { disabled, value } = props - const classes = useStyles() - - function handleStepChange(stepChange) { - if (stepChange === step) { - setStep(-1) // close - } else { - setStep(stepChange) // open - } - } - - // takes a list of { id, type } targets and return the ids for a specific type - const getTargetsByType = (type) => (tgts) => - tgts - .filter((t) => t.type === type) // only the list of the current type - .map((t) => t.id) // array of ID strings - - // takes a list of ids and return a list of { id, type } concatted with the new set of specific types - const makeSetTargetType = (curTgts) => (type) => (newTgts) => - curTgts - .filter((t) => t.type !== type) // current targets without any of the current type - .concat(newTgts.map((id) => ({ id, type }))) // add the list of current type to the end - - // then form fields would all point to `targets` but can map values - const setTargetType = makeSetTargetType(value.targets) - - const badgeMeUpScotty = (len, txt) => ( - - {txt} - - ) - - const optionalText = ( - - Optional - - ) - - return ( - - - - - {(cfg) => ( - - - } - optional={optionalText} - onClick={() => handleStepChange(0)} - tabIndex={-1} - > - {badgeMeUpScotty( - getTargetsByType('schedule')(value.targets).length, - 'Add Schedules', - )} - - - - - - {cfg['Slack.Enable'] && ( - - } - optional={optionalText} - onClick={() => handleStepChange(1)} - tabIndex={-1} - > - {badgeMeUpScotty( - getTargetsByType('slackChannel')(value.targets).length, - 'Add Slack Channels', - )} - - - - - - )} - - } - optional={optionalText} - onClick={() => - handleStepChange(cfg['Slack.Enable'] ? 2 : 1) - } - tabIndex={-1} - > - {badgeMeUpScotty( - getTargetsByType('user')(value.targets).length, - 'Add Users', - )} - - - - - - - } - optional={optionalText} - onClick={() => - handleStepChange(cfg['Slack.Enable'] ? 3 : 2) - } - tabIndex={-1} - > - {badgeMeUpScotty( - getTargetsByType('rotation')(value.targets).length, - 'Add Rotations', - )} - - - - - - {cfg['Webhook.Enable'] && ( - - } - optional={optionalText} - onClick={() => - handleStepChange(cfg['Slack.Enable'] ? 4 : 3) - } - tabIndex={-1} - > - {badgeMeUpScotty( - getTargetsByType('chanWebhook')(value.targets).length, - 'Add Webhook', - )} - - - - Webhook Documentation - - } - /> - - - )} - - )} - - - - - - - - ) -} - -PolicyStepForm.propTypes = { - value: p.shape({ - targets: p.arrayOf( - p.shape({ id: p.string.isRequired, type: p.string.isRequired }), - ), - delayMinutes: p.string.isRequired, - }).isRequired, - - errors: p.arrayOf( - p.shape({ - field: p.oneOf(['targets', 'delayMinutes']).isRequired, - message: p.string.isRequired, - }), - ), - - disabled: p.bool, - onChange: p.func, -} - -export default PolicyStepForm diff --git a/web/src/app/escalation-policies/PolicyStepFormDest.stories.tsx b/web/src/app/escalation-policies/PolicyStepForm.stories.tsx similarity index 82% rename from web/src/app/escalation-policies/PolicyStepFormDest.stories.tsx rename to web/src/app/escalation-policies/PolicyStepForm.stories.tsx index 55f231f1ba..96e5cdb5e8 100644 --- a/web/src/app/escalation-policies/PolicyStepFormDest.stories.tsx +++ b/web/src/app/escalation-policies/PolicyStepForm.stories.tsx @@ -1,8 +1,8 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' -import PolicyStepFormDest, { FormValue } from './PolicyStepFormDest' +import PolicyStepForm, { FormValue } from './PolicyStepForm' import { expect, userEvent, waitFor, within, fn } from '@storybook/test' -import { handleDefaultConfig, handleExpFlags } from '../storybook/graphql' +import { handleDefaultConfig } from '../storybook/graphql' import { HttpResponse, graphql } from 'msw' import { useArgs } from '@storybook/preview-api' import { DestFieldValueError } from '../util/errtypes' @@ -13,7 +13,7 @@ const INVALID_PHONE = '+15555' const meta = { title: 'Escalation Policies/Steps/Form', - component: PolicyStepFormDest, + component: PolicyStepForm, args: { onChange: fn(), }, @@ -23,14 +23,13 @@ const meta = { if (args.onChange) args.onChange(newValue) setArgs({ value: newValue }) } - return + return }, tags: ['autodocs'], parameters: { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('ValidateDestination', ({ variables: vars }) => { return HttpResponse.json({ data: { @@ -39,14 +38,14 @@ const meta = { }) }), graphql.query('DestDisplayInfo', ({ variables: vars }) => { - switch (vars.input.values[0].value) { + switch (vars.input.args['phone-number']) { case VALID_PHONE: case VALID_PHONE2: return HttpResponse.json({ data: { destinationDisplayInfo: { text: - vars.input.values[0].value === VALID_PHONE + vars.input.args['phone-number'] === VALID_PHONE ? 'VALID_CHIP_1' : 'VALID_CHIP_2', iconURL: 'builtin://phone-voice', @@ -75,7 +74,7 @@ const meta = { ], }, }, -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj @@ -95,11 +94,11 @@ export const WithExistingActions: Story = { actions: [ { type: 'single-field', - values: [{ fieldID: 'phone-number', value: VALID_PHONE }], + args: { 'phone-number': VALID_PHONE }, }, { type: 'single-field', - values: [{ fieldID: 'phone-number', value: VALID_PHONE2 }], + args: { 'phone-number': VALID_PHONE2 }, }, ], }, @@ -119,7 +118,7 @@ export const ManageActions: Story = { await userEvent.clear(phoneInput) await userEvent.type(phoneInput, INVALID_PHONE) - await userEvent.click(await canvas.findByText('Add Action')) + await userEvent.click(await canvas.findByText('Add Destination')) await waitFor(async () => { await expect(await canvas.findByLabelText('Phone Number')).toBeInvalid() @@ -136,7 +135,7 @@ export const ManageActions: Story = { await userEvent.type(phoneInput, VALID_PHONE) - await userEvent.click(await canvas.findByText('Add Action')) + await userEvent.click(await canvas.findByText('Add Destination')) // should result in chip await expect(await canvas.findByText('VALID_CHIP_1')).toBeVisible() @@ -144,6 +143,6 @@ export const ManageActions: Story = { // Delete the chip await userEvent.click(await canvas.findByTestId('CancelIcon')) - await expect(await canvas.findByText('No actions')).toBeVisible() + await expect(await canvas.findByText('No destinations')).toBeVisible() }, } diff --git a/web/src/app/escalation-policies/PolicyStepFormDest.tsx b/web/src/app/escalation-policies/PolicyStepForm.tsx similarity index 68% rename from web/src/app/escalation-policies/PolicyStepFormDest.tsx rename to web/src/app/escalation-policies/PolicyStepForm.tsx index 56a43c5fd6..df39a17e99 100644 --- a/web/src/app/escalation-policies/PolicyStepFormDest.tsx +++ b/web/src/app/escalation-policies/PolicyStepForm.tsx @@ -3,21 +3,18 @@ import { FormContainer, FormField } from '../forms' import Grid from '@mui/material/Grid' import NumberField from '../util/NumberField' -import { DestinationInput, FieldValueInput } from '../../schema' +import { DestinationInput, StringMap } from '../../schema' import DestinationInputChip from '../util/DestinationInputChip' -import { Button, TextField, Typography } from '@mui/material' +import { TextField, Typography } from '@mui/material' import { renderMenuItem } from '../selection/DisableableMenuItem' import DestinationField from '../selection/DestinationField' import { useEPTargetTypes } from '../util/RequireConfig' import { gql, useClient, CombinedError } from 'urql' -import { - DestFieldValueError, - KnownError, - isDestFieldError, -} from '../util/errtypes' -import { splitErrorsByPath } from '../util/errutil' import DialogContentError from '../dialogs/components/DialogContentError' import makeStyles from '@mui/styles/makeStyles' +import { useErrorConsumer } from '../util/ErrorConsumer' +import { Add } from '../icons' +import LoadingButton from '../loading/components/LoadingButton' const useStyles = makeStyles(() => { return { @@ -33,9 +30,8 @@ export type FormValue = { actions: DestinationInput[] } -export type PolicyStepFormDestProps = { +export type PolicyStepFormProps = { value: FormValue - errors?: (KnownError | DestFieldValueError)[] disabled?: boolean onChange: (value: FormValue) => void } @@ -51,18 +47,15 @@ const query = gql` } ` -export default function PolicyStepFormDest( - props: PolicyStepFormDestProps, -): ReactNode { +export default function PolicyStepForm(props: PolicyStepFormProps): ReactNode { const types = useEPTargetTypes() const classes = useStyles() const [destType, setDestType] = useState(types[0].type) - const [values, setValues] = useState([]) + const [args, setArgs] = useState({}) const validationClient = useClient() const [err, setErr] = useState(null) - const [destErrors, otherErrs] = splitErrorsByPath(err || props.errors, [ - 'destinationDisplayInfo.input', - ]) + const errs = useErrorConsumer(err) + const [validating, setValidating] = useState(false) useEffect(() => { setErr(null) @@ -76,10 +69,10 @@ export default function PolicyStepFormDest( }) } - function renderErrors(): React.JSX.Element[] { + function renderErrors(otherErrs: readonly string[]): React.JSX.Element[] { return otherErrs.map((err, idx) => ( - - {props.value.actions.map((a, idx) => ( - handleDelete(a)} - /> + + {props.value.actions.map((a) => ( + + handleDelete(a)} + /> + ))} {props.value.actions.length === 0 && ( - - No actions - + + + No destinations + + )} setDestType(e.target.value)} > {types.map((t) => @@ -134,48 +130,60 @@ export default function PolicyStepFormDest( { + value={args} + disabled={props.disabled || validating} + onChange={(newValue: StringMap) => { setErr(null) - setValues(newValue) + setArgs(newValue) }} - destFieldErrors={destErrors.filter(isDestFieldError)} + fieldErrors={errs.getErrorMap( + /destinationDisplayInfo\.input(\.args)?/, + )} /> - {otherErrs && renderErrors()} - + Add Destination + + (stepNumParam, false) @@ -121,19 +115,10 @@ export default function PolicyStepsCard( setCreateStep(true)} title='Create Step' /> )} {createStep && ( - - {hasDestTypesFlag ? ( - - ) : ( - - )} - + )} - {step.actions - ? renderChipsDest(step.actions) - : renderChips(step)} + {renderChipsDest(step.actions)} {renderDelayMessage( step, idx, @@ -206,19 +189,11 @@ export default function PolicyStepsCard( {editStep && ( - {hasDestTypesFlag ? ( - - ) : ( - - )} + )} {deleteStep && ( diff --git a/web/src/app/escalation-policies/PolicyStepsQuery.tsx b/web/src/app/escalation-policies/PolicyStepsQuery.tsx index a6f47ab978..01d57b9f22 100644 --- a/web/src/app/escalation-policies/PolicyStepsQuery.tsx +++ b/web/src/app/escalation-policies/PolicyStepsQuery.tsx @@ -2,26 +2,6 @@ import React from 'react' import { gql, useQuery } from 'urql' import PolicyStepsCard from './PolicyStepsCard' import { GenericError, ObjectNotFound } from '../error-pages' -import { useExpFlag } from '../util/useExpFlag' - -export const policyStepsQuery = gql` - query stepsQuery($id: ID!) { - escalationPolicy(id: $id) { - id - repeat - steps { - id - delayMinutes - stepNumber - targets { - id - name - type - } - } - } - } -` export const policyStepsQueryDest = gql` query stepsQueryDest($id: ID!) { @@ -57,10 +37,8 @@ export const policyStepsQueryDest = gql` ` function PolicyStepsQuery(props: { escalationPolicyID: string }): JSX.Element { - const hasDestTypesFlag = useExpFlag('dest-types') - const [{ data, error }] = useQuery({ - query: hasDestTypesFlag ? policyStepsQueryDest : policyStepsQuery, + query: policyStepsQueryDest, variables: { id: props.escalationPolicyID }, }) diff --git a/web/src/app/escalation-policies/stepUtil.tsx b/web/src/app/escalation-policies/stepUtil.tsx index 8cfa3dca04..57a63696fb 100644 --- a/web/src/app/escalation-policies/stepUtil.tsx +++ b/web/src/app/escalation-policies/stepUtil.tsx @@ -1,37 +1,28 @@ -import React, { ComponentType, ReactElement, ReactNode } from 'react' +import React, { ReactElement, ReactNode } from 'react' import { sortBy } from 'lodash' import Chip from '@mui/material/Chip' import Grid from '@mui/material/Grid' import Typography from '@mui/material/Typography' -import { - RotationChip, - ScheduleChip, - UserChip, - SlackChip, - WebhookChip, -} from '../util/Chips' -import { Destination, Target } from '../../schema' +import { Destination } from '../../schema' import DestinationChip from '../util/DestinationChip' - -interface Step { - id: string - delayMinutes: number - targets: Target[] -} - -interface HasID { - id: string -} - -export function getStepNumber(stepID: string, steps: HasID[]): number { - const sids = steps.map((s) => s.id) - return sids.indexOf(stepID) + 1 -} +import { Warning } from '../icons' export function renderChipsDest(_a: Destination[]): ReactElement { const actions = sortBy(_a.slice(), ['type', 'displayInfo.text']) if (!actions || actions.length === 0) { - return + return ( + + + + } + /> + ) } const items = actions.map((a, idx) => { @@ -49,64 +40,12 @@ export function renderChipsDest(_a: Destination[]): ReactElement { ) } -/* - * Renders the mui chips for each target on the step - */ -export function renderChips({ targets: _t }: Step): ReactElement { - // copy and sort by type then name - const targets = sortBy(_t.slice(), ['type', 'name']) - - if (!targets || targets.length === 0) { - return - } - - const items = targets.map((tgt) => { - const tgtChip = ( - Chip: ComponentType<{ id: string; label: string }>, - ): JSX.Element => - - let chip = null - switch (tgt.type) { - case 'user': - chip = tgtChip(UserChip) - break - case 'schedule': - chip = tgtChip(ScheduleChip) - break - case 'rotation': - chip = tgtChip(RotationChip) - break - case 'slackChannel': - case 'notificationChannel': - chip = tgtChip(SlackChip) - break - case 'chanWebhook': - chip = tgtChip(WebhookChip) - break - } - - if (chip) { - return ( - - {chip} - - ) - } - }) - - return ( - - {items} - - ) -} - /* * Renders the delay message, dependent on if the escalation policy * repeats, and if the message is rendering on the last step */ export function renderDelayMessage( - step: Step, + step: { delayMinutes: number }, idx: number, repeat: number, isLastStep: boolean, @@ -119,7 +58,7 @@ export function renderDelayMessage( const pluralizer = (x: number): string => (x === 1 ? '' : 's') let repeatText = `Move on to step #${ - idx + 1 + idx + 2 } after ${step.delayMinutes} minute${pluralizer(step.delayMinutes)}` if (isLastStep && idx === 0) { diff --git a/web/src/app/escalation-policies/utils.tsx b/web/src/app/escalation-policies/utils.tsx new file mode 100644 index 0000000000..8ad3d58fe9 --- /dev/null +++ b/web/src/app/escalation-policies/utils.tsx @@ -0,0 +1,31 @@ +import React from 'react' +import { Notice } from '../details/Notices' +import { FormControlLabel, Checkbox } from '@mui/material' + +export function getNotice( + hasSubmitted: boolean, + hasConfirmed: boolean, + setHasConfirmed: (b: boolean) => void, +): Notice[] { + if (!hasSubmitted) return [] + + return [ + { + type: 'WARNING', + message: 'No destinations', + details: + 'If you submit with no destinations, nothing will happen on this step', + action: ( + setHasConfirmed(!hasConfirmed)} + /> + } + label='I acknowledge the impact of this' + /> + ), + }, + ] +} diff --git a/web/src/app/forms/HelperText.tsx b/web/src/app/forms/HelperText.tsx new file mode 100644 index 0000000000..03603c64d6 --- /dev/null +++ b/web/src/app/forms/HelperText.tsx @@ -0,0 +1,70 @@ +import React from 'react' +import FormHelperText from '@mui/material/FormHelperText' +import AppLink from '../util/AppLink' +import { Grid } from '@mui/material' + +export type HelperTextProps = { + hint?: string + hintURL?: string + error?: string + errorURL?: string + maxLength?: number + value?: string +} + +/** HelperText is a component that displays a hint or error message. + * + * It is intended to be used as the `helperText` prop of a TextField (or other MUI form components). + */ +export function HelperText(props: HelperTextProps): React.ReactNode { + let content + if (props.error) { + const isMultiLine = props.error.includes('\n') + let msg: React.ReactNode = props.error.replace(/^./, (str) => + str.toUpperCase(), + ) + if (isMultiLine) { + msg = ( + + {msg} + + ) + } + content = props.errorURL ? ( + + {msg} + + ) : ( + msg + ) + } else { + content = props.hintURL ? ( + + {props.hint} + + ) : ( + props.hint + ) + } + + if (props.maxLength) { + return ( + + + {content} + + + + {props.value?.length || 0}/{props.maxLength} + + + + ) + } + + return ( + + {content} + + ) +} diff --git a/web/src/app/forms/index.js b/web/src/app/forms/index.js index b923dfe969..0ae258ba05 100644 --- a/web/src/app/forms/index.js +++ b/web/src/app/forms/index.js @@ -1,3 +1,4 @@ export * from './Form' export * from './FormContainer' export * from './FormField' +export * from './HelperText' diff --git a/web/src/app/lists/FlatList.tsx b/web/src/app/lists/FlatList.tsx index 7064353314..141d533f78 100644 --- a/web/src/app/lists/FlatList.tsx +++ b/web/src/app/lists/FlatList.tsx @@ -364,7 +364,7 @@ export default function FlatList({ ) } - return + return }) } diff --git a/web/src/app/lists/FlatListItem.tsx b/web/src/app/lists/FlatListItem.tsx index 090426ab5e..77929009ec 100644 --- a/web/src/app/lists/FlatListItem.tsx +++ b/web/src/app/lists/FlatListItem.tsx @@ -80,7 +80,6 @@ export default function FlatListItem(props: FlatListItemProps): JSX.Element { return ( { disabled={loading || disabled} type={noSubmit ? 'button' : 'submit'} > - {!attemptCount ? buttonText || 'Confirm' : 'Retry'} + {!attemptCount ? props.children || buttonText || 'Confirm' : 'Retry'} {loading && ( ) diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialogDest.stories.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialog.stories.tsx similarity index 87% rename from web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialogDest.stories.tsx rename to web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialog.stories.tsx index 7b6ca15e81..12d3b4c057 100644 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialogDest.stories.tsx +++ b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialog.stories.tsx @@ -1,14 +1,14 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' import { expect, fn, userEvent, waitFor, within } from '@storybook/test' -import ScheduleOnCallNotificationsCreateDialogDest from './ScheduleOnCallNotificationsCreateDialogDest' +import ScheduleOnCallNotificationsCreateDialog from './ScheduleOnCallNotificationsCreateDialog' import { HttpResponse, graphql } from 'msw' -import { handleDefaultConfig, handleExpFlags } from '../../storybook/graphql' +import { handleDefaultConfig } from '../../storybook/graphql' import { BaseError, DestFieldValueError } from '../../util/errtypes' const meta = { title: 'schedules/on-call-notifications/CreateDialogDest', - component: ScheduleOnCallNotificationsCreateDialogDest, + component: ScheduleOnCallNotificationsCreateDialog, argTypes: {}, args: { scheduleID: 'create-test', @@ -24,7 +24,6 @@ const meta = { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('SchedZone', ({ variables }) => { return HttpResponse.json({ data: { @@ -39,7 +38,7 @@ const meta = { HttpResponse.json({ data: { destinationFieldValidate: true } }), ), graphql.mutation('SetRules', ({ variables }) => { - switch (variables.input.rules[0].dest.values[0].value) { + switch (variables.input.rules[0].dest.args['phone-number']) { case '+123': return HttpResponse.json({ errors: [ @@ -87,11 +86,9 @@ const meta = { }, tags: ['autodocs'], render: function Component(args) { - return ( - - ) + return }, -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialog.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialog.tsx index dceb532e2a..142410b020 100644 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialog.tsx +++ b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialog.tsx @@ -1,54 +1,136 @@ -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import FormDialog from '../../dialogs/FormDialog' -import ScheduleOnCallNotificationsForm from './ScheduleOnCallNotificationsForm' -import { useOnCallRulesData, useSetOnCallRulesSubmit } from './hooks' -import { NO_DAY, Value, mapOnCallErrors } from './util' +import ScheduleOnCallNotificationsForm, { + Value, +} from './ScheduleOnCallNotificationsForm' +import { NO_DAY } from './util' +import { useSchedOnCallNotifyTypes } from '../../util/RequireConfig' +import { CombinedError, gql, useMutation, useQuery } from 'urql' +import { + Schedule, + SetScheduleOnCallNotificationRulesInput, +} from '../../../schema' +import { DateTime } from 'luxon' +import { BaseError } from '../../util/errtypes' +import { useErrorConsumer } from '../../util/ErrorConsumer' + +const getRulesQuery = gql` + query GetRules($scheduleID: ID!) { + schedule(id: $scheduleID) { + id + timeZone + onCallNotificationRules { + id + weekdayFilter + time + dest { + type + args + } + } + } + } +` + +const setRulesMut = gql` + mutation SetRules($input: SetScheduleOnCallNotificationRulesInput!) { + setScheduleOnCallNotificationRules(input: $input) + } +` interface ScheduleOnCallNotificationsCreateDialogProps { onClose: () => void scheduleID: string -} - -const defaultValue: Value = { - time: null, - weekdayFilter: NO_DAY, - type: 'slackChannel', - targetID: null, + disablePortal?: boolean } export default function ScheduleOnCallNotificationsCreateDialog( props: ScheduleOnCallNotificationsCreateDialogProps, ): JSX.Element { const { onClose, scheduleID } = props - const [value, setValue] = useState(defaultValue) + const types = useSchedOnCallNotifyTypes() + const [err, setErr] = useState(null) + const [value, setValue] = useState({ + time: null, + weekdayFilter: NO_DAY, + dest: { + type: types[0].type, + args: {}, + }, + }) + useEffect(() => { + setErr(null) + }, [value]) + const [q] = useQuery<{ schedule: Schedule }>({ + query: getRulesQuery, + variables: { scheduleID }, + }) + if (q.error) throw q.error + const sched = q.data?.schedule + if (!sched) throw new Error('no data for schedule ' + scheduleID) + const [m, commit] = useMutation(setRulesMut) + useEffect(() => { + setErr(m.error || null) + }, [m.error]) - const { q, zone, rules } = useOnCallRulesData(scheduleID) + let noDaysSelected: BaseError | null = null + if (value.weekdayFilter.every((val) => !val)) { + noDaysSelected = { + message: 'Please select at least one day', + } + } + const errs = useErrorConsumer(err) - const { m, submit } = useSetOnCallRulesSubmit( - scheduleID, - zone, - value, - ...rules, + const form = ( + ) - const [dialogErrors, fieldErrors] = mapOnCallErrors(m.error, q.error) - const busy = (q.fetching && !zone) || m.fetching - return ( submit().then(onClose)} - form={ - - } + onSubmit={() => { + if (noDaysSelected && value.time !== null) return + + return commit( + { + input: { + scheduleID, + rules: [ + ...sched.onCallNotificationRules, + value.time + ? { + ...value, + time: DateTime.fromISO(value.time) + .setZone(sched.timeZone) + .toFormat('HH:mm'), + } + : { dest: value.dest }, + ], + } satisfies SetScheduleOnCallNotificationRulesInput, + }, + { additionalTypenames: ['Schedule'] }, + ) + .then(onClose) + .catch((err) => { + setErr(err) + }) + }} + form={form} /> ) } diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialogDest.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialogDest.tsx deleted file mode 100644 index e014f98242..0000000000 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsCreateDialogDest.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import React, { useEffect, useState } from 'react' -import FormDialog from '../../dialogs/FormDialog' -import ScheduleOnCallNotificationsForm, { - Value, - errorPaths, -} from './ScheduleOnCallNotificationsFormDest' -import { NO_DAY } from './util' -import { useSchedOnCallNotifyTypes } from '../../util/RequireConfig' -import { splitErrorsByPath } from '../../util/errutil' -import { CombinedError, gql, useMutation, useQuery } from 'urql' -import { - Schedule, - SetScheduleOnCallNotificationRulesInput, -} from '../../../schema' -import { DateTime } from 'luxon' - -const getRulesQuery = gql` - query GetRules($scheduleID: ID!) { - schedule(id: $scheduleID) { - id - onCallNotificationRules { - id - weekdayFilter - time - dest { - type - values { - fieldID - value - } - } - } - } - } -` - -const setRulesMut = gql` - mutation SetRules($input: SetScheduleOnCallNotificationRulesInput!) { - setScheduleOnCallNotificationRules(input: $input) - } -` - -interface ScheduleOnCallNotificationsCreateDialogProps { - onClose: () => void - scheduleID: string - disablePortal?: boolean -} - -export default function ScheduleOnCallNotificationsCreateDialog( - props: ScheduleOnCallNotificationsCreateDialogProps, -): JSX.Element { - const { onClose, scheduleID } = props - const types = useSchedOnCallNotifyTypes() - const [err, setErr] = useState(null) - const [value, setValue] = useState({ - time: null, - weekdayFilter: NO_DAY, - dest: { - type: types[0].type, - values: [], - }, - }) - useEffect(() => { - setErr(null) - }, [value]) - const [q] = useQuery<{ schedule: Schedule }>({ - query: getRulesQuery, - variables: { scheduleID }, - }) - if (q.error) throw q.error - const sched = q.data?.schedule - if (!sched) throw new Error('no data for schedule ' + scheduleID) - const [m, commit] = useMutation(setRulesMut) - useEffect(() => { - setErr(m.error || null) - }, [m.error]) - - const newRulePrefix = [ - 'setScheduleOnCallNotificationRules', - 'input', - 'rules', - sched.onCallNotificationRules.length, - ].join('.') - const [formErrors, otherErrs] = splitErrorsByPath( - err, - errorPaths(newRulePrefix), - ) - - return ( - - commit( - { - input: { - scheduleID, - rules: [ - ...sched.onCallNotificationRules, - value.time - ? { - ...value, - time: DateTime.fromISO(value.time).toFormat('HH:mm'), - } - : { dest: value.dest }, - ], - } satisfies SetScheduleOnCallNotificationRulesInput, - }, - { additionalTypenames: ['Schedule'] }, - ) - .then(onClose) - .catch((err) => { - setErr(err) - }) - } - form={ - - } - /> - ) -} diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialogDest.stories.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialog.stories.tsx similarity index 85% rename from web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialogDest.stories.tsx rename to web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialog.stories.tsx index 305fe32b00..c110931b66 100644 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialogDest.stories.tsx +++ b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialog.stories.tsx @@ -1,14 +1,14 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' import { expect, fn, userEvent, waitFor, within } from '@storybook/test' -import ScheduleOnCallNotificationsEditDialogDest from './ScheduleOnCallNotificationsEditDialogDest' +import ScheduleOnCallNotificationsEditDialog from './ScheduleOnCallNotificationsEditDialog' import { HttpResponse, graphql } from 'msw' -import { handleDefaultConfig, handleExpFlags } from '../../storybook/graphql' +import { handleDefaultConfig } from '../../storybook/graphql' import { BaseError, DestFieldValueError } from '../../util/errtypes' const meta = { title: 'schedules/on-call-notifications/EditDialogDest', - component: ScheduleOnCallNotificationsEditDialogDest, + component: ScheduleOnCallNotificationsEditDialog, argTypes: {}, args: { scheduleID: 'create-test', @@ -25,7 +25,6 @@ const meta = { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('SchedZone', ({ variables }) => { return HttpResponse.json({ data: { @@ -40,7 +39,7 @@ const meta = { HttpResponse.json({ data: { destinationFieldValidate: true } }), ), graphql.mutation('SetRules', ({ variables }) => { - switch (variables.input.rules[0].dest.values[0].value) { + switch (variables.input.rules[0].dest.args['phone-number']) { case '+123': return HttpResponse.json({ errors: [ @@ -83,12 +82,7 @@ const meta = { id: 'existing-id', dest: { type: 'single-field', - values: [ - { - fieldID: 'phone-number', - value: '+1234567890', - }, - ], + args: { 'phone-number': '+1234567890' }, }, }, ], @@ -101,9 +95,9 @@ const meta = { }, tags: ['autodocs'], render: function Component(args) { - return + return }, -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialog.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialog.tsx index 4bc2a4ba07..167feb7353 100644 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialog.tsx +++ b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialog.tsx @@ -1,58 +1,131 @@ -import React, { useState } from 'react' - -import { DateTime } from 'luxon' +import React, { useEffect, useState } from 'react' import FormDialog from '../../dialogs/FormDialog' -import { useOnCallRulesData, useSetOnCallRulesSubmit } from './hooks' -import ScheduleOnCallNotificationsForm from './ScheduleOnCallNotificationsForm' -import { EVERY_DAY, mapOnCallErrors, NO_DAY, Value } from './util' +import ScheduleOnCallNotificationsForm, { + Value, +} from './ScheduleOnCallNotificationsForm' +import { NO_DAY } from './util' +import { CombinedError, gql, useMutation, useQuery } from 'urql' +import { + Schedule, + SetScheduleOnCallNotificationRulesInput, +} from '../../../schema' +import { DateTime } from 'luxon' +import { useErrorConsumer } from '../../util/ErrorConsumer' + +const getRulesQuery = gql` + query GetRules($scheduleID: ID!) { + schedule(id: $scheduleID) { + id + timeZone + onCallNotificationRules { + id + weekdayFilter + time + dest { + type + args + } + } + } + } +` + +const setRulesMut = gql` + mutation SetRules($input: SetScheduleOnCallNotificationRulesInput!) { + setScheduleOnCallNotificationRules(input: $input) + } +` interface ScheduleOnCallNotificationsEditDialogProps { onClose: () => void - scheduleID: string ruleID: string + disablePortal?: boolean } export default function ScheduleOnCallNotificationsEditDialog( - p: ScheduleOnCallNotificationsEditDialogProps, + props: ScheduleOnCallNotificationsEditDialogProps, ): JSX.Element { - const [value, setValue] = useState(null) - - const { q, zone, rules } = useOnCallRulesData(p.scheduleID) - - const rule = rules.find((r) => r.id === p.ruleID) - const newValue: Value = value || { - time: rule?.time - ? DateTime.fromFormat(rule.time, 'HH:mm', { zone }).toISO() - : null, - weekdayFilter: rule?.time ? rule.weekdayFilter || EVERY_DAY : NO_DAY, - type: rule?.target?.type ?? 'slackChannel', - targetID: rule?.target?.id ?? null, - } - const { m, submit } = useSetOnCallRulesSubmit( - p.scheduleID, - zone, - newValue, - ...rules.filter((r) => r.id !== p.ruleID), - ) + const { onClose, scheduleID } = props + const [err, setErr] = useState(null) + const [q] = useQuery<{ schedule: Schedule }>({ + query: getRulesQuery, + variables: { scheduleID }, + }) + if (q.error) throw q.error + const sched = q.data?.schedule + if (!sched) throw new Error('no data for schedule ' + scheduleID) + const rule = sched.onCallNotificationRules.find((r) => r.id === props.ruleID) + if (!rule) throw new Error('no rule for id ' + props.ruleID) + + const [value, setValue] = useState({ + time: rule.time || null, + weekdayFilter: rule.weekdayFilter || NO_DAY, + dest: { + type: rule.dest.type, + args: rule.dest.args, + }, + }) + useEffect(() => { + setErr(null) + }, [value]) - const [dialogErrors, fieldErrors] = mapOnCallErrors(m.error, q.error) + const [m, commit] = useMutation(setRulesMut) + useEffect(() => { + setErr(m.error || null) + }, [m.error]) + + const errs = useErrorConsumer(err) + + const form = ( + + ) return ( p.onClose()} - onSubmit={() => submit().then(p.onClose)} - form={ - + errors={errs.remainingLegacy()} + disablePortal={props.disablePortal} + loading={m.fetching} + onClose={onClose} + onSubmit={() => + commit( + { + input: { + scheduleID, + rules: [ + ...sched.onCallNotificationRules.filter((r) => r !== rule), + value.time + ? { + id: rule.id, + ...value, + time: DateTime.fromISO(value.time) + .setZone(sched.timeZone) + .toFormat('HH:mm'), + } + : { id: rule.id, dest: value.dest }, + ], + } satisfies SetScheduleOnCallNotificationRulesInput, + }, + { additionalTypenames: ['Schedule'] }, + ) + .then(onClose) + .catch((err) => { + setErr(err) + }) } + form={form} /> ) } diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialogDest.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialogDest.tsx deleted file mode 100644 index f8fd93b9c9..0000000000 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsEditDialogDest.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import React, { useEffect, useState } from 'react' -import FormDialog from '../../dialogs/FormDialog' -import ScheduleOnCallNotificationsForm, { - Value, - errorPaths, -} from './ScheduleOnCallNotificationsFormDest' -import { NO_DAY } from './util' -import { splitErrorsByPath } from '../../util/errutil' -import { CombinedError, gql, useMutation, useQuery } from 'urql' -import { - Schedule, - SetScheduleOnCallNotificationRulesInput, -} from '../../../schema' -import { DateTime } from 'luxon' - -const getRulesQuery = gql` - query GetRules($scheduleID: ID!) { - schedule(id: $scheduleID) { - id - onCallNotificationRules { - id - weekdayFilter - time - dest { - type - values { - fieldID - value - } - } - } - } - } -` - -const setRulesMut = gql` - mutation SetRules($input: SetScheduleOnCallNotificationRulesInput!) { - setScheduleOnCallNotificationRules(input: $input) - } -` - -interface ScheduleOnCallNotificationsEditDialogProps { - onClose: () => void - scheduleID: string - ruleID: string - disablePortal?: boolean -} - -export default function ScheduleOnCallNotificationsEditDialog( - props: ScheduleOnCallNotificationsEditDialogProps, -): JSX.Element { - const { onClose, scheduleID } = props - const [err, setErr] = useState(null) - const [q] = useQuery<{ schedule: Schedule }>({ - query: getRulesQuery, - variables: { scheduleID }, - }) - if (q.error) throw q.error - const sched = q.data?.schedule - if (!sched) throw new Error('no data for schedule ' + scheduleID) - const rule = sched.onCallNotificationRules.find((r) => r.id === props.ruleID) - if (!rule) throw new Error('no rule for id ' + props.ruleID) - - const [value, setValue] = useState({ - time: rule.time || null, - weekdayFilter: rule.weekdayFilter || NO_DAY, - dest: { - type: rule.dest.type, - values: rule.dest.values.map((v) => ({ ...v })), - }, - }) - useEffect(() => { - setErr(null) - }, [value]) - - const [m, commit] = useMutation(setRulesMut) - useEffect(() => { - setErr(m.error || null) - }, [m.error]) - - const newRulePrefix = [ - 'setScheduleOnCallNotificationRules', - 'input', - 'rules', - sched.onCallNotificationRules.length - 1, - ].join('.') - const [formErrors, otherErrs] = splitErrorsByPath( - err, - errorPaths(newRulePrefix), - ) - - return ( - - commit( - { - input: { - scheduleID, - rules: [ - ...sched.onCallNotificationRules.filter((r) => r !== rule), - value.time - ? { - id: rule.id, - ...value, - time: DateTime.fromISO(value.time).toFormat('HH:mm'), - } - : { id: rule.id, dest: value.dest }, - ], - } satisfies SetScheduleOnCallNotificationRulesInput, - }, - { additionalTypenames: ['Schedule'] }, - ) - .then(onClose) - .catch((err) => { - setErr(err) - }) - } - form={ - - } - /> - ) -} diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsFormDest.stories.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsForm.stories.tsx similarity index 62% rename from web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsFormDest.stories.tsx rename to web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsForm.stories.tsx index f0250ce0b4..de1f280587 100644 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsFormDest.stories.tsx +++ b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsForm.stories.tsx @@ -1,14 +1,14 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' -import ScheduleOnCallNotificationsFormDest, { +import ScheduleOnCallNotificationsForm, { Value, -} from './ScheduleOnCallNotificationsFormDest' +} from './ScheduleOnCallNotificationsForm' import { useArgs } from '@storybook/preview-api' import { expect, fn, userEvent, within } from '@storybook/test' const meta = { title: 'schedules/on-call-notifications/FormDest', - component: ScheduleOnCallNotificationsFormDest, + component: ScheduleOnCallNotificationsForm, argTypes: {}, args: { scheduleID: '', @@ -18,7 +18,7 @@ const meta = { weekdayFilter: [false, false, false, false, false, false, false], dest: { type: 'single-field', - values: [], + args: {}, }, }, }, @@ -29,9 +29,9 @@ const meta = { if (args.onChange) args.onChange(newValue) setArgs({ value: newValue }) } - return + return }, -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj @@ -42,30 +42,10 @@ export const Empty: Story = { export const ValidationErrors: Story = { args: { - errors: [ - { - path: ['mutation', 'input', 'time'], - message: 'error with time', - extensions: { - code: 'INVALID_INPUT_VALUE', - }, - }, - { - path: ['mutation', 'input', 'dest'], - message: 'error with dest field', - extensions: { - code: 'INVALID_DEST_FIELD_VALUE', - fieldID: 'phone-number', - }, - }, - { - path: ['mutation', 'input', 'dest', 'type'], - message: 'error with dest type', - extensions: { - code: 'INVALID_INPUT_VALUE', - }, - }, - ], + destTypeError: 'error with dest type', + destFieldErrors: { + 'phone-number': 'error with dest field', + }, }, play: async ({ canvasElement }) => { const canvas = within(canvasElement) @@ -83,7 +63,6 @@ export const ValidationErrors: Story = { ).toBeInvalid() await expect(await canvas.findByLabelText('Phone Number')).toBeInvalid() - await expect(await canvas.findByText('Error with time')).toBeVisible() await expect(await canvas.findByText('Error with dest field')).toBeVisible() await expect(await canvas.findByText('Error with dest type')).toBeVisible() }, diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsForm.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsForm.tsx index ca8dac3635..333280eae5 100644 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsForm.tsx +++ b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsForm.tsx @@ -9,28 +9,35 @@ import { } from '@mui/material' import makeStyles from '@mui/styles/makeStyles' import { DateTime } from 'luxon' -import React, { useMemo } from 'react' +import React, { useEffect } from 'react' -import { TargetType } from '../../../schema' import { FormContainer, FormField } from '../../forms' -import { SlackChannelSelect, SlackUserGroupSelect } from '../../selection' -import { - renderMenuItem, - sortDisableableMenuItems, -} from '../../selection/DisableableMenuItem' +import { renderMenuItem } from '../../selection/DisableableMenuItem' import { ISOTimePicker } from '../../util/ISOPickers' -import { useConfigValue } from '../../util/RequireConfig' import { Time } from '../../util/Time' import { useScheduleTZ } from '../useScheduleTZ' -import { EVERY_DAY, NO_DAY, RuleFieldError, Value } from './util' +import { EVERY_DAY, NO_DAY } from './util' +import { useSchedOnCallNotifyTypes } from '../../util/RequireConfig' +import { DestinationInput, WeekdayFilter } from '../../../schema' +import DestinationField from '../../selection/DestinationField' const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] +export type Value = { + time: string | null + weekdayFilter: WeekdayFilter + dest: DestinationInput +} + interface ScheduleOnCallNotificationsFormProps { scheduleID: string value: Value - errors: RuleFieldError[] onChange: (val: Value) => void + disablePortal?: boolean + disabled?: boolean + + destTypeError?: string + destFieldErrors?: Readonly> } const useStyles = makeStyles({ @@ -43,120 +50,63 @@ export default function ScheduleOnCallNotificationsForm( ): JSX.Element { const { scheduleID, ...formProps } = props const classes = useStyles() - const [slackEnabled] = useConfigValue('Slack.Enable') - const [webhookEnabled] = useConfigValue('Webhook.Enable') const { zone } = useScheduleTZ(scheduleID) + const destinationTypes = useSchedOnCallNotifyTypes() + const currentType = destinationTypes.find( + (d) => d.type === props.value.dest.type, + ) + + const [ruleType, setRuleType] = React.useState<'on-change' | 'time-of-day'>( + props.value.time ? 'time-of-day' : 'on-change', + ) + const [lastTime, setLastTime] = React.useState( + props.value.time, + ) + const [lastFilter, setLastFilter] = React.useState( + props.value.weekdayFilter, + ) + useEffect(() => { + if (!props.value.time) return + setLastTime(props.value.time) + setLastFilter(props.value.weekdayFilter) + }, [props.value.time, props.value.weekdayFilter]) + + if (!currentType) throw new Error('invalid destination type') const handleRuleChange = (e: React.ChangeEvent): void => { if (e.target.value === 'on-change') { + setRuleType('on-change') props.onChange({ ...formProps.value, time: null, weekdayFilter: NO_DAY }) return } + + setRuleType('time-of-day') props.onChange({ ...props.value, - weekdayFilter: EVERY_DAY, - time: DateTime.fromObject({ hour: 9 }, { zone }).toISO(), + weekdayFilter: lastTime ? lastFilter : EVERY_DAY, + time: lastTime || DateTime.fromObject({ hour: 9 }, { zone }).toISO(), }) } - const handleTypeChange = (e: React.ChangeEvent): void => { - const newType = e.target.value as TargetType - if (props.value.type !== newType) { - props.onChange({ - ...props.value, - type: newType, - targetID: null, - }) - } - } - - const notificationChannels = useMemo( - () => - [ - { - value: 'slackChannel', - label: 'SLACK CHANNEL', - disabledMessage: 'Slack must be configured by an administrator', - disabled: !slackEnabled, - }, - - { - value: 'slackUserGroup', - label: 'SLACK USER GROUP', - disabledMessage: 'Slack must be configured by an administrator', - disabled: !slackEnabled, - }, - - { - value: 'chanWebhook', - label: 'WEBHOOK', - disabledMessage: 'Webhooks must be enabled by an administrator', - disabled: !webhookEnabled, - }, - ].sort(sortDisableableMenuItems), - [slackEnabled, webhookEnabled], - ) - - function renderTypeFields(type: TargetType): JSX.Element { - switch (type) { - case 'slackUserGroup': - return ( - - - - ) - case 'slackChannel': - return ( - - - - ) - case 'chanWebhook': - return ( - - - - ) - default: - // unsupported type - return - } - } - return ( - + } /> } @@ -210,21 +160,53 @@ export default function ScheduleOnCallNotificationsForm( - + + props.onChange({ + ...props.value, + dest: { type: e.target.value, args: {} }, + }) + } + error={!!props.destTypeError} + helperText={props.destTypeError} > - {notificationChannels.map(renderMenuItem)} + {destinationTypes.map((t) => + renderMenuItem({ + label: t.name, + value: t.type, + disabled: !t.enabled, + disabledMessage: t.enabled ? '' : 'Disabled by administrator.', + }), + )} - {renderTypeFields(formProps.value.type)} + + + props.onChange({ + ...props.value, + dest: { ...props.value.dest, args: newValue }, + }) + } + /> + + + + {currentType?.userDisclaimer} + + ) diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsFormDest.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsFormDest.tsx deleted file mode 100644 index fda1df7d5f..0000000000 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsFormDest.tsx +++ /dev/null @@ -1,222 +0,0 @@ -import { - Checkbox, - FormControlLabel, - Grid, - Radio, - RadioGroup, - TextField, - Typography, -} from '@mui/material' -import makeStyles from '@mui/styles/makeStyles' -import { DateTime } from 'luxon' -import React, { useEffect } from 'react' - -import { FormContainer, FormField } from '../../forms' -import { renderMenuItem } from '../../selection/DisableableMenuItem' -import { ISOTimePicker } from '../../util/ISOPickers' -import { Time } from '../../util/Time' -import { useScheduleTZ } from '../useScheduleTZ' -import { EVERY_DAY, NO_DAY } from './util' -import { useSchedOnCallNotifyTypes } from '../../util/RequireConfig' -import { DestinationInput, WeekdayFilter } from '../../../schema' -import DestinationField from '../../selection/DestinationField' -import { - DestFieldValueError, - KnownError, - isDestFieldError, - isInputFieldError, -} from '../../util/errtypes' - -const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] - -export type Value = { - time: string | null - weekdayFilter: WeekdayFilter - dest: DestinationInput -} - -interface ScheduleOnCallNotificationsFormProps { - scheduleID: string - value: Value - errors?: Array - onChange: (val: Value) => void - disablePortal?: boolean -} - -const useStyles = makeStyles({ - margin0: { margin: 0 }, - tzNote: { fontStyle: 'italic' }, -}) - -export const errorPaths = (prefix = '*'): string[] => [ - `${prefix}.time`, - `${prefix}.weedkayFilter`, - `${prefix}.dest.type`, - `${prefix}.dest`, -] - -export default function ScheduleOnCallNotificationsFormDest( - props: ScheduleOnCallNotificationsFormProps, -): JSX.Element { - const { scheduleID, ...formProps } = props - const classes = useStyles() - const { zone } = useScheduleTZ(scheduleID) - const destinationTypes = useSchedOnCallNotifyTypes() - const currentType = destinationTypes.find( - (d) => d.type === props.value.dest.type, - ) - - const [ruleType, setRuleType] = React.useState<'on-change' | 'time-of-day'>( - props.value.time ? 'time-of-day' : 'on-change', - ) - const [lastTime, setLastTime] = React.useState( - props.value.time, - ) - const [lastFilter, setLastFilter] = React.useState( - props.value.weekdayFilter, - ) - useEffect(() => { - if (!props.value.time) return - setLastTime(props.value.time) - setLastFilter(props.value.weekdayFilter) - }, [props.value.time, props.value.weekdayFilter]) - - if (!currentType) throw new Error('invalid destination type') - - const handleRuleChange = (e: React.ChangeEvent): void => { - if (e.target.value === 'on-change') { - setRuleType('on-change') - props.onChange({ ...formProps.value, time: null, weekdayFilter: NO_DAY }) - return - } - - setRuleType('time-of-day') - props.onChange({ - ...props.value, - weekdayFilter: lastTime ? lastFilter : EVERY_DAY, - time: lastTime || DateTime.fromObject({ hour: 9 }, { zone }).toISO(), - }) - } - - return ( - { - let field = e.path[e.path.length - 1].toString() - if (field === 'type') field = 'dest.type' - return { - // need to convert to FormContainer's error format - message: e.message, - field, - } - })} - optionalLabels - > - - - - } - /> - } - /> - - - {props.value.time && ( - - - Times shown in schedule timezone ({zone}) - - - )} - - - - } - /> - - - - {days.map((day, i) => ( - - } - /> - ))} - - - - - - {destinationTypes.map((t) => - renderMenuItem({ - label: t.name, - value: t.type, - disabled: !t.enabled, - disabledMessage: t.enabled ? '' : 'Disabled by administrator.', - }), - )} - - - - - - - - {currentType?.userDisclaimer} - - - - - ) -} diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsListDest.stories.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsList.stories.tsx similarity index 91% rename from web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsListDest.stories.tsx rename to web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsList.stories.tsx index 02c0377956..4ef6fe1509 100644 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsListDest.stories.tsx +++ b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsList.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react' -import ScheduleOnCallNotificationsListDest from './ScheduleOnCallNotificationsListDest' -import { handleDefaultConfig, handleExpFlags } from '../../storybook/graphql' +import ScheduleOnCallNotificationsList from './ScheduleOnCallNotificationsList' +import { handleDefaultConfig } from '../../storybook/graphql' import { HttpResponse, graphql } from 'msw' const emptyScheduleID = '00000000-0000-0000-0000-000000000000' @@ -9,13 +9,12 @@ const manyNotificationsScheduleID = '22222222-2222-2222-2222-222222222222' const meta = { title: 'schedules/on-call-notifications/ListDest', - component: ScheduleOnCallNotificationsListDest, + component: ScheduleOnCallNotificationsList, argTypes: {}, parameters: { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('ScheduleNotifications', ({ variables }) => { switch (variables.scheduleID) { case emptyScheduleID: @@ -94,7 +93,7 @@ const meta = { }, }, tags: ['autodocs'], -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsList.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsList.tsx index 488935f80d..55f165b474 100644 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsList.tsx +++ b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsList.tsx @@ -1,36 +1,56 @@ -import React, { useState } from 'react' -import { Button, Grid, Card } from '@mui/material' -import Avatar from '@mui/material/Avatar' - +import React, { Suspense, useState } from 'react' +import { Button, Grid, Card, Typography, Tooltip, Theme } from '@mui/material' import FlatList from '../../lists/FlatList' import OtherActions from '../../util/OtherActions' -import { SlackBW, WebhookBW } from '../../icons/components/Icons' -import { useOnCallRulesData } from './hooks' import { onCallRuleSummary } from './util' -import ScheduleOnCallNotificationsCreateDialog from './ScheduleOnCallNotificationsCreateDialog' import ScheduleOnCallNotificationsDeleteDialog from './ScheduleOnCallNotificationsDeleteDialog' import CreateFAB from '../../lists/CreateFAB' -import ScheduleOnCallNotificationsEditDialog from './ScheduleOnCallNotificationsEditDialog' import { useIsWidthDown } from '../../util/useWidth' import { Add } from '@mui/icons-material' -import { useExpFlag } from '../../util/useExpFlag' -import ScheduleOnCallNotificationsListDest from './ScheduleOnCallNotificationsListDest' +import Error from '@mui/icons-material/Error' +import { gql, useQuery } from 'urql' +import { Schedule } from '../../../schema' +import { DestinationAvatar } from '../../util/DestinationAvatar' +import { styles as globalStyles } from '../../styles/materialStyles' +import makeStyles from '@mui/styles/makeStyles' +import ScheduleOnCallNotificationsCreateDialog from './ScheduleOnCallNotificationsCreateDialog' +import ScheduleOnCallNotificationsEditDialog from './ScheduleOnCallNotificationsEditDialog' export type ScheduleOnCallNotificationsListProps = { scheduleID: string } -function getChannelIcon(targetType: string): JSX.Element { - if (targetType === 'slackUserGroup' || targetType === 'slackChannel') { - return +const query = gql` + query ScheduleNotifications($scheduleID: ID!) { + schedule(id: $scheduleID) { + id + timeZone + onCallNotificationRules { + id + time + weekdayFilter + dest { + displayInfo { + ... on DestinationDisplayInfo { + text + iconURL + iconAltText + } + ... on DestinationDisplayInfoError { + error + } + } + } + } + } } - if (targetType === 'chanWebhook') { - return - } - return
-} +` + +const useStyles = makeStyles((theme: Theme) => ({ + ...globalStyles(theme), +})) -function ScheduleOnCallNotificationsList({ +export default function ScheduleOnCallNotificationsList({ scheduleID, }: ScheduleOnCallNotificationsListProps): JSX.Element { const [createRule, setCreateRule] = useState(false) @@ -38,7 +58,44 @@ function ScheduleOnCallNotificationsList({ const [deleteRuleID, setDeleteRuleID] = useState('') const isMobile = useIsWidthDown('md') - const { q, zone, rules } = useOnCallRulesData(scheduleID) + const classes = useStyles() + + const [q] = useQuery<{ schedule: Schedule }>({ + query, + variables: { scheduleID }, + }) + + if (q.error || !q.data) { + return ( + + + + + + + +   + + Error loading notification rules. + + + } + items={[]} + /> + + + + ) + } + + const schedule = q.data.schedule + const timeZone = schedule.timeZone return ( @@ -46,12 +103,8 @@ function ScheduleOnCallNotificationsList({ ) } - items={rules.map((rule) => { + items={q.data.schedule.onCallNotificationRules.map((rule) => { + const display = rule.dest.displayInfo + if ('error' in display) { + return { + icon: , + title: `ERROR: ${display.error}`, + subText: 'Notifies ' + onCallRuleSummary(timeZone, rule), + secondaryAction: ( + setEditRuleID(rule.id), + }, + { + label: 'Delete', + onClick: () => setDeleteRuleID(rule.id), + }, + ]} + /> + ), + } + } + return { - icon: {getChannelIcon(rule.target.type)}, - title: rule.target.name ?? undefined, - subText: 'Notifies ' + onCallRuleSummary(zone, rule), + icon: ( + + ), + title: display.text, + subText: 'Notifies ' + onCallRuleSummary(timeZone, rule), secondaryAction: ( )} - {createRule && ( - setCreateRule(false)} - /> - )} - {editRuleID && ( - setEditRuleID('')} - /> - )} - {deleteRuleID && ( - setDeleteRuleID('')} - /> - )} + + {createRule && ( + setCreateRule(false)} + /> + )} + {editRuleID && ( + setEditRuleID('')} + /> + )} + {deleteRuleID && ( + setDeleteRuleID('')} + /> + )} + ) } - -// Since we are using a feature flag, and cannot conditionally update the router (which always renders the default export of this file), -// we need to create a component that will conditionally render the destination version based on the feature flag. -export default function ScheduleOnCallNotificationsListSwitcher( - props: ScheduleOnCallNotificationsListProps, -): JSX.Element { - const hasDestTypesFlag = useExpFlag('dest-types') - - if (hasDestTypesFlag) { - return - } - - return -} diff --git a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsListDest.tsx b/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsListDest.tsx deleted file mode 100644 index 7a8c43754d..0000000000 --- a/web/src/app/schedules/on-call-notifications/ScheduleOnCallNotificationsListDest.tsx +++ /dev/null @@ -1,202 +0,0 @@ -import React, { Suspense, useState } from 'react' -import { Button, Grid, Card, Typography, Tooltip, Theme } from '@mui/material' -import FlatList from '../../lists/FlatList' -import OtherActions from '../../util/OtherActions' -import { onCallRuleSummary } from './util' -import ScheduleOnCallNotificationsDeleteDialog from './ScheduleOnCallNotificationsDeleteDialog' -import CreateFAB from '../../lists/CreateFAB' -import { useIsWidthDown } from '../../util/useWidth' -import { Add } from '@mui/icons-material' -import Error from '@mui/icons-material/Error' -import { gql, useQuery } from 'urql' -import { Schedule } from '../../../schema' -import { DestinationAvatar } from '../../util/DestinationAvatar' -import { styles as globalStyles } from '../../styles/materialStyles' -import makeStyles from '@mui/styles/makeStyles' -import ScheduleOnCallNotificationsCreateDialogDest from './ScheduleOnCallNotificationsCreateDialogDest' -import ScheduleOnCallNotificationsEditDialogDest from './ScheduleOnCallNotificationsEditDialogDest' - -export type ScheduleOnCallNotificationsListDestProps = { - scheduleID: string -} - -const query = gql` - query ScheduleNotifications($scheduleID: ID!) { - schedule(id: $scheduleID) { - id - timeZone - onCallNotificationRules { - id - time - weekdayFilter - dest { - displayInfo { - ... on DestinationDisplayInfo { - text - iconURL - iconAltText - } - ... on DestinationDisplayInfoError { - error - } - } - } - } - } - } -` - -const useStyles = makeStyles((theme: Theme) => ({ - ...globalStyles(theme), -})) - -export default function ScheduleOnCallNotificationsListDest({ - scheduleID, -}: ScheduleOnCallNotificationsListDestProps): JSX.Element { - const [createRule, setCreateRule] = useState(false) - const [editRuleID, setEditRuleID] = useState('') - const [deleteRuleID, setDeleteRuleID] = useState('') - const isMobile = useIsWidthDown('md') - - const classes = useStyles() - - const [q] = useQuery<{ schedule: Schedule }>({ - query, - variables: { scheduleID }, - }) - - if (q.error || !q.data) { - return ( - - - - - - - -   - - Error loading notification rules. - - - } - items={[]} - /> - - - - ) - } - - const schedule = q.data.schedule - const timeZone = schedule.timeZone - - return ( - - - - - setCreateRule(true)} - startIcon={} - > - Create Notification Rule - - ) - } - items={q.data.schedule.onCallNotificationRules.map((rule) => { - const display = rule.dest.displayInfo - if ('error' in display) { - return { - icon: , - title: `ERROR: ${display.error}`, - subText: 'Notifies ' + onCallRuleSummary(timeZone, rule), - secondaryAction: ( - setEditRuleID(rule.id), - }, - { - label: 'Delete', - onClick: () => setDeleteRuleID(rule.id), - }, - ]} - /> - ), - } - } - - return { - icon: ( - - ), - title: display.text, - subText: 'Notifies ' + onCallRuleSummary(timeZone, rule), - secondaryAction: ( - setEditRuleID(rule.id), - }, - { - label: 'Delete', - onClick: () => setDeleteRuleID(rule.id), - }, - ]} - /> - ), - } - })} - /> - - - - {isMobile && ( - setCreateRule(true)} - title='Create Notification Rule' - /> - )} - - {createRule && ( - setCreateRule(false)} - /> - )} - {editRuleID && ( - setEditRuleID('')} - /> - )} - {deleteRuleID && ( - setDeleteRuleID('')} - /> - )} - - - ) -} diff --git a/web/src/app/selection/ChanWebhookSelect.tsx b/web/src/app/selection/ChanWebhookSelect.tsx deleted file mode 100644 index 1c706078a3..0000000000 --- a/web/src/app/selection/ChanWebhookSelect.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { Add } from '@mui/icons-material' -import { Chip, Grid, TextField } from '@mui/material' -import React, { useState } from 'react' -import { WebhookChip } from '../util/Chips' - -type ChanWebhookSelectProps = { - value: Array - onChange: (value: Array) => void -} - -function isValidURL(str: string): boolean { - try { - // eslint-disable-next-line no-new - new URL(str) - return true - } catch { - return false - } -} - -export const ChanWebhookSelect = ( - props: ChanWebhookSelectProps, -): JSX.Element => { - const [newURL, setNewURL] = useState('') - const { value, onChange } = props - - const selected = props.value.map((v) => { - return ( - - onChange(value.filter((f) => f !== v))} - /> - - ) - }) - - return ( - - - {props.value.length ? selected : ''} - - - { - setNewURL(e.target.value.trim()) - }} - error={ - (!isValidURL(newURL) && newURL.length > 0) || value.includes(newURL) - } - helperText={ - !isValidURL(newURL) && newURL.length > 0 - ? 'Must be a valid URL.' - : value.includes(newURL) - ? 'Must be a new URL.' - : '' - } - placeholder='https://example.com/...' - InputProps={{ - endAdornment: ( - } - onClick={() => { - if ( - !newURL || - !isValidURL(newURL) || - value.indexOf(newURL) > -1 - ) - return - - onChange([...value, newURL]) - setNewURL('') - }} - /> - ), - }} - /> - - - ) -} diff --git a/web/src/app/selection/DestinationField.stories.tsx b/web/src/app/selection/DestinationField.stories.tsx index eb6507c620..7afec821e8 100644 --- a/web/src/app/selection/DestinationField.stories.tsx +++ b/web/src/app/selection/DestinationField.stories.tsx @@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react' import DestinationField from './DestinationField' import { expect, within } from '@storybook/test' import { useArgs } from '@storybook/preview-api' -import { FieldValueInput } from '../../schema' +import { StringMap } from '../../schema' const meta = { title: 'util/DestinationField', @@ -18,7 +18,7 @@ const meta = { render: function Component(args) { const [, setArgs] = useArgs() - const onChange = (newValue: FieldValueInput[]): void => { + const onChange = (newValue: StringMap): void => { if (args.onChange) args.onChange(newValue) setArgs({ value: newValue }) } @@ -32,12 +32,7 @@ type Story = StoryObj export const SingleField: Story = { args: { destType: 'single-field', - value: [ - { - fieldID: 'phone-number', - value: '', - }, - ], + value: { 'phone-number': '' }, disabled: false, }, play: async ({ canvasElement }) => { @@ -58,20 +53,11 @@ export const SingleField: Story = { export const MultiField: Story = { args: { destType: 'triple-field', - value: [ - { - fieldID: 'first-field', - value: '', - }, - { - fieldID: 'second-field', - value: 'test@example.com', - }, - { - fieldID: 'third-field', - value: '', - }, - ], + value: { + 'first-field': '', + 'second-field': 'test@example.com', + 'third-field': '', + }, disabled: false, }, play: async ({ canvasElement }) => { @@ -98,12 +84,7 @@ export const MultiField: Story = { export const DisabledField: Story = { args: { destType: 'disabled-destination', - value: [ - { - fieldID: 'disabled', - value: '', - }, - ], + value: { disabled: '' }, }, play: async ({ canvasElement }) => { const canvas = within(canvasElement) @@ -118,20 +99,11 @@ export const DisabledField: Story = { export const FieldError: Story = { args: { destType: 'triple-field', - value: [ - { - fieldID: 'first-field', - value: '', - }, - { - fieldID: 'second-field', - value: 'test@example.com', - }, - { - fieldID: 'third-field', - value: '', - }, - ], + value: { + 'first-field': '', + 'second-field': 'test@example.com', + 'third-field': '', + }, disabled: false, destFieldErrors: [ { diff --git a/web/src/app/selection/DestinationField.tsx b/web/src/app/selection/DestinationField.tsx index c4176c4f2d..9a4d480e4c 100644 --- a/web/src/app/selection/DestinationField.tsx +++ b/web/src/app/selection/DestinationField.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { DestinationType, FieldValueInput } from '../../schema' +import { DestinationType, StringMap } from '../../schema' import DestinationInputDirect from './DestinationInputDirect' import { useDestinationType } from '../util/RequireConfig' import DestinationSearchSelect from './DestinationSearchSelect' @@ -7,13 +7,21 @@ import { Grid } from '@mui/material' import { DestFieldValueError } from '../util/errtypes' export type DestinationFieldProps = { - value: FieldValueInput[] - onChange?: (value: FieldValueInput[]) => void + value: StringMap + onChange?: (value: StringMap) => void destType: DestinationType disabled?: boolean + /** Deprecated, use fieldErrors instead. */ destFieldErrors?: DestFieldValueError[] + + fieldErrors?: Readonly> +} + +export interface DestFieldError { + fieldID: string + message: string } function capFirstLetter(s: string): string { @@ -26,31 +34,28 @@ export default function DestinationField( ): React.ReactNode { const dest = useDestinationType(props.destType) + let fieldErrors = props.fieldErrors + // TODO: remove this block after removing destFieldErrors + if (!props.fieldErrors && props.destFieldErrors) { + const newErrs: Record = {} + for (const err of props.destFieldErrors) { + newErrs[err.extensions.fieldID] = err.message + } + fieldErrors = newErrs + } + return ( {dest.requiredFields.map((field) => { - const fieldValue = - (props.value || []).find((v) => v.fieldID === field.fieldID)?.value || - '' + const fieldValue = props.value[field.fieldID] || '' function handleChange(newValue: string): void { if (!props.onChange) return - const newValues = (props.value || []) - .filter((v) => v.fieldID !== field.fieldID) - .concat({ - fieldID: field.fieldID, - value: newValue, - }) - - props.onChange(newValues) + props.onChange({ ...props.value, [field.fieldID]: newValue }) } - const fieldErrMsg = capFirstLetter( - props.destFieldErrors?.find( - (err) => err.extensions.fieldID === field.fieldID, - )?.message || '', - ) + const fieldErrMsg = capFirstLetter(fieldErrors?.[field.fieldID] || '') if (field.supportsSearch) return ( @@ -61,9 +66,7 @@ export default function DestinationField( destType={props.destType} disabled={props.disabled || !dest.enabled} onChange={(val) => handleChange(val)} - error={!!fieldErrMsg} - hint={fieldErrMsg || field.hint} - hintURL={fieldErrMsg ? '' : field.hintURL} + error={fieldErrMsg} /> ) @@ -76,9 +79,7 @@ export default function DestinationField( destType={props.destType} disabled={props.disabled || !dest.enabled} onChange={(e) => handleChange(e.target.value)} - error={!!fieldErrMsg} - hint={fieldErrMsg || field.hint} - hintURL={fieldErrMsg ? '' : field.hintURL} + error={fieldErrMsg} /> ) diff --git a/web/src/app/selection/DestinationInputDirect.stories.tsx b/web/src/app/selection/DestinationInputDirect.stories.tsx index 3672a070e7..8e4be6eef0 100644 --- a/web/src/app/selection/DestinationInputDirect.stories.tsx +++ b/web/src/app/selection/DestinationInputDirect.stories.tsx @@ -2,7 +2,7 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' import DestinationInputDirect from './DestinationInputDirect' import { expect, within, userEvent } from '@storybook/test' -import { handleDefaultConfig, handleExpFlags } from '../storybook/graphql' +import { handleDefaultConfig } from '../storybook/graphql' import { HttpResponse, graphql } from 'msw' import { useArgs } from '@storybook/preview-api' @@ -21,7 +21,6 @@ const meta = { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('ValidateDestination', ({ variables: vars }) => { return HttpResponse.json({ data: { diff --git a/web/src/app/selection/DestinationInputDirect.tsx b/web/src/app/selection/DestinationInputDirect.tsx index f8825a6e2a..a62ec5c9ac 100644 --- a/web/src/app/selection/DestinationInputDirect.tsx +++ b/web/src/app/selection/DestinationInputDirect.tsx @@ -6,8 +6,8 @@ import { Check, Close } from '@mui/icons-material' import InputAdornment from '@mui/material/InputAdornment' import { DEBOUNCE_DELAY } from '../config' import { DestinationFieldConfig, DestinationType } from '../../schema' -import AppLink from '../util/AppLink' import { green, red } from '@mui/material/colors' +import { HelperText } from '../forms' const isValidValue = gql` query ValidateDestination($input: DestinationFieldValidateInput!) { @@ -26,13 +26,13 @@ function trimPrefix(value: string, prefix: string): string { return value } -export type DestinationInputDirectProps = DestinationFieldConfig & { +export type DestinationInputDirectProps = Partial & { value: string onChange?: (e: React.ChangeEvent) => void destType: DestinationType disabled?: boolean - error?: boolean + error?: string } /** @@ -126,17 +126,15 @@ export default function DestinationInputDirect( placeholder={props.placeholderText} label={props.label} helperText={ - props.hintURL ? ( - - {props.hint} - - ) : ( - props.hint - ) + } onChange={handleChange} - value={trimPrefix(props.value, props.prefix)} - error={props.error} + value={trimPrefix(props.value, props.prefix || '')} + error={!!props.error} /> ) } diff --git a/web/src/app/selection/DestinationSearchSelect.stories.tsx b/web/src/app/selection/DestinationSearchSelect.stories.tsx index 8214d6dce3..62a4602650 100644 --- a/web/src/app/selection/DestinationSearchSelect.stories.tsx +++ b/web/src/app/selection/DestinationSearchSelect.stories.tsx @@ -2,7 +2,7 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' import DestinationSearchSelect from './DestinationSearchSelect' import { expect, userEvent, within } from '@storybook/test' -import { handleDefaultConfig, handleExpFlags } from '../storybook/graphql' +import { handleDefaultConfig } from '../storybook/graphql' import { HttpResponse, graphql } from 'msw' import { useArgs } from '@storybook/preview-api' import { FieldSearchConnection } from '../../schema' @@ -30,7 +30,6 @@ const meta = { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('DestinationFieldSearch', ({ variables: vars }) => { if (vars.input.search === 'query-error') { return HttpResponse.json({ diff --git a/web/src/app/selection/DestinationSearchSelect.tsx b/web/src/app/selection/DestinationSearchSelect.tsx index 892d3ebaf4..1a9dde0714 100644 --- a/web/src/app/selection/DestinationSearchSelect.tsx +++ b/web/src/app/selection/DestinationSearchSelect.tsx @@ -7,7 +7,7 @@ import { } from '../../schema' import MaterialSelect from './MaterialSelect' import { FavoriteIcon } from '../util/SetFavoriteButton' -import AppLink from '../util/AppLink' +import { HelperText } from '../forms' const searchOptionsQuery = gql` query DestinationFieldSearch($input: DestinationFieldSearchInput!) { @@ -35,7 +35,7 @@ export type DestinationSearchSelectProps = DestinationFieldConfig & { destType: DestinationType disabled?: boolean - error?: boolean + error?: string } const cacheByJSON: Record = {} @@ -131,18 +131,16 @@ export default function DestinationSearchSelect( noOptionsText='No options' disabled={props.disabled} noOptionsError={error} - error={props.error} + error={!!props.error} onInputChange={(val) => setInputValue(val)} value={value as unknown as SelectOption} label={props.label} helperText={ - props.hintURL ? ( - - {props.hint} - - ) : ( - props.hint - ) + } options={options .map((opt) => ({ diff --git a/web/src/app/selection/DynamicActionForm.stories.tsx b/web/src/app/selection/DynamicActionForm.stories.tsx new file mode 100644 index 0000000000..3a61e50275 --- /dev/null +++ b/web/src/app/selection/DynamicActionForm.stories.tsx @@ -0,0 +1,142 @@ +import React from 'react' +import type { Meta, StoryObj } from '@storybook/react' + +import DynamicActionForm, { Value } from './DynamicActionForm' +import { DestinationTypeInfo } from '../../schema' +import { fn } from '@storybook/test' +import { useArgs } from '@storybook/preview-api' + +const meta = { + title: 'util/Destination/DynamicActionForm', + component: DynamicActionForm, + args: { + onChange: fn(), + }, + parameters: { + graphql: { + RequireConfig: { + data: { + destinationTypes: [ + { + type: 'action-type', + name: 'Action Type', + enabled: true, + userDisclaimer: '', + isContactMethod: false, + isEPTarget: false, + isSchedOnCallNotify: false, + isDynamicAction: true, + iconURL: '', + iconAltText: '', + supportsStatusUpdates: false, + statusUpdatesRequired: false, + dynamicParams: [ + { + paramID: 'dynamic-param', + label: 'Dynamic Param', + hint: 'Param Hint', + hintURL: 'http://example.com/hint', + }, + ], + requiredFields: [ + { + fieldID: 'required-field', + label: 'Required Field', + hint: 'Field Hint', + hintURL: '', + placeholderText: '', + prefix: '', + inputType: 'text', + supportsSearch: false, + supportsValidation: false, + }, + ], + }, + { + type: 'action-type-2', + name: 'Action Type 2', + enabled: true, + userDisclaimer: '', + isContactMethod: false, + isEPTarget: false, + isSchedOnCallNotify: false, + isDynamicAction: true, + iconURL: '', + iconAltText: '', + supportsStatusUpdates: false, + statusUpdatesRequired: false, + dynamicParams: [ + { + paramID: 'dynamic-param-2', + label: 'Dynamic Param 2', + hint: 'Param Hint 2', + hintURL: 'http://example.com/hint2', + }, + ], + requiredFields: [ + { + fieldID: 'required-field-2', + label: 'Required Field 2', + hint: 'Field Hint 2', + hintURL: '', + placeholderText: '', + prefix: '', + inputType: 'text', + supportsSearch: false, + supportsValidation: false, + }, + ], + }, + ] satisfies DestinationTypeInfo[], + }, + }, + }, + }, + tags: ['autodocs'], +} satisfies Meta + +export default meta +type Story = StoryObj + +export const Interactive: Story = { + args: { + value: null, + }, + render: function Component(args) { + const [, setArgs] = useArgs() + const onChange = (value: Value): void => { + if (args.onChange) args.onChange(value) + setArgs({ value }) + } + return + }, +} + +export const NullValue: Story = { + args: { + value: null, + }, +} + +export const Values: Story = { + args: { + value: { + destType: 'action-type', + staticParams: { 'required-field': 'value' }, + dynamicParams: { 'dynamic-param': 'req.body.dynamic-param' }, + }, + }, +} + +export const Errors: Story = { + args: { + value: { + destType: 'action-type', + staticParams: {}, + dynamicParams: {}, + }, + destTypeError: 'Dest type validation error', + staticParamErrors: { 'required-field': 'Required field validation error' }, + dynamicParamErrors: { 'dynamic-param': 'Dynamic param validation error' }, + }, +} diff --git a/web/src/app/selection/DynamicActionForm.tsx b/web/src/app/selection/DynamicActionForm.tsx new file mode 100644 index 0000000000..bd913b7f49 --- /dev/null +++ b/web/src/app/selection/DynamicActionForm.tsx @@ -0,0 +1,172 @@ +import React from 'react' +import { + ActionInput, + DestinationType, + DestinationTypeInfo, + ExprStringExpression, +} from '../../schema' +import { useDynamicActionTypes } from '../util/RequireConfig' +import { Grid, TextField } from '@mui/material' +import DestinationField from './DestinationField' +import { renderMenuItem } from './DisableableMenuItem' +import { HelperText } from '../forms' + +export type StaticParams = Readonly> +export type DynamicParams = Readonly> + +export type Value = { + destType: DestinationType + staticParams: StaticParams + dynamicParams: DynamicParams +} + +export function valueToActionInput(value: Value | null): ActionInput { + if (!value) { + return { dest: { type: '', args: {} }, params: {} } + } + + return { + dest: { + type: value.destType, + args: value.staticParams, + }, + params: value.dynamicParams, + } +} + +export function actionInputToValue(action: ActionInput): Value { + return { + destType: action.dest.type, + staticParams: action.dest.args || {}, + dynamicParams: { ...action.params }, + } +} + +export type DynamicActionErrors = { + destTypeError?: string + staticParamErrors?: Readonly> + dynamicParamErrors?: Readonly> +} +export type DynamicActionFormProps = { + value: Value | null + onChange: (value: Value) => void + + disabled?: boolean + + destTypeError?: string + staticParamErrors?: Readonly> + dynamicParamErrors?: Readonly> + + disablePortal?: boolean +} + +export function defaults(destTypeInfo: DestinationTypeInfo): Value { + const staticParams = Object.fromEntries( + destTypeInfo.requiredFields.map((f) => [f.fieldID, '']), + ) + + const dynamicParams = Object.fromEntries( + destTypeInfo.dynamicParams.map((p) => [ + p.paramID, + `req.body['${p.paramID}']`, + ]), + ) + + return { + destType: destTypeInfo.type, + staticParams, + dynamicParams, + } +} + +export default function DynamicActionForm( + props: DynamicActionFormProps, +): React.ReactNode { + const types = useDynamicActionTypes() + const selectedDest = types.find((t) => t.type === props.value?.destType) + + return ( + + + { + const newType = types.find((t) => t.type === e.target.value) + if (!newType) return + props.onChange(defaults(newType)) + }} + > + {types.map((t) => + renderMenuItem({ + label: t.name, + value: t.type, + disabled: !t.enabled, + disabledMessage: t.enabled ? '' : 'Disabled by administrator.', + }), + )} + + + {props.value && ( + + { + if (!props.value) return + props.onChange({ + ...props.value, + staticParams: vals, + }) + }} + destType={props.value.destType} + disabled={props.disabled} + fieldErrors={props.staticParamErrors} + /> + + )} + {props.value && + (selectedDest?.dynamicParams || []).map((p) => { + const fieldValue = props.value?.dynamicParams[p.paramID] || '' + + function handleChange(newValue: string): void { + if (!props.value) return + + const newParams = { + ...props.value.dynamicParams, + [p.paramID]: newValue as ExprStringExpression, + } + + props.onChange({ ...props.value, dynamicParams: newParams }) + } + + return ( + + + } + onChange={(e) => handleChange(e.target.value)} + value={fieldValue} + /> + + ) + })} + + ) +} diff --git a/web/src/app/selection/index.js b/web/src/app/selection/index.js index fc33eb3753..a260bf159a 100644 --- a/web/src/app/selection/index.js +++ b/web/src/app/selection/index.js @@ -7,4 +7,3 @@ export * from './SlackChannelSelect' export * from './SlackUserGroupSelect' export * from './TimeZoneSelect' export * from './UserSelect' -export * from './ChanWebhookSelect' diff --git a/web/src/app/services/UniversalKey/DefaultActionEditDialog.tsx b/web/src/app/services/UniversalKey/DefaultActionEditDialog.tsx new file mode 100644 index 0000000000..d5a6bb519c --- /dev/null +++ b/web/src/app/services/UniversalKey/DefaultActionEditDialog.tsx @@ -0,0 +1,95 @@ +import React, { useState } from 'react' +import { gql, useMutation, useQuery } from 'urql' +import FormDialog from '../../dialogs/FormDialog' +import { ActionInput, IntegrationKey } from '../../../schema' +import { getNotice } from './utils' +import UniversalKeyActionsForm from './UniversalKeyActionsForm' +import { useErrorConsumer } from '../../util/ErrorConsumer' + +interface DefaultActionEditDialogProps { + keyID: string + onClose: () => void +} + +const query = gql` + query UniversalKeyPage($keyID: ID!) { + integrationKey(id: $keyID) { + id + config { + defaultActions { + dest { + type + args + } + params + } + } + } + } +` + +const mutation = gql` + mutation ($input: UpdateKeyConfigInput!) { + updateKeyConfig(input: $input) + } +` + +export default function DefaultActionEditDialog( + props: DefaultActionEditDialogProps, +): JSX.Element { + const [keyResult] = useQuery<{ + integrationKey: IntegrationKey + }>({ + query, + variables: { + keyID: props.keyID, + }, + }) + + const [value, setValue] = useState( + keyResult.data?.integrationKey.config.defaultActions ?? [], + ) + const [updateKeyResult, commit] = useMutation(mutation) + + const [hasConfirmed, setHasConfirmed] = useState(false) + const [hasSubmitted, setHasSubmitted] = useState(false) + const noActionsNoConf = value.length === 0 && !hasConfirmed + const errs = useErrorConsumer(updateKeyResult.error) + const [editAction, setEditAction] = useState('') + + return ( + { + if (noActionsNoConf) { + setHasSubmitted(true) + return + } + + return commit( + { + input: { + keyID: props.keyID, + defaultActions: value, + }, + }, + { additionalTypenames: ['KeyConfig'] }, + ).then((res) => { + if (!res.error) props.onClose() + }) + }} + form={ + setEditAction(action.dest.type)} + showList + /> + } + errors={errs.remainingLegacy()} + notices={getNotice(hasSubmitted, hasConfirmed, setHasConfirmed)} + /> + ) +} diff --git a/web/src/app/services/UniversalKey/DeleteSecondaryTokenDialog.tsx b/web/src/app/services/UniversalKey/DeleteSecondaryTokenDialog.tsx new file mode 100644 index 0000000000..590e8c5c38 --- /dev/null +++ b/web/src/app/services/UniversalKey/DeleteSecondaryTokenDialog.tsx @@ -0,0 +1,62 @@ +import React, { useState } from 'react' +import { Checkbox, FormControlLabel, Typography } from '@mui/material' +import { gql, useMutation } from 'urql' +import FormDialog from '../../dialogs/FormDialog' +import { nonFieldErrors } from '../../util/errutil' + +interface DeleteSecondaryTokenDialogProps { + keyID: string + onClose: () => void +} + +const mutation = gql` + mutation ($id: ID!) { + deleteSecondaryToken(id: $id) + } +` + +export default function DeleteSecondaryTokenDialog({ + keyID, + onClose, +}: DeleteSecondaryTokenDialogProps): JSX.Element { + const [status, commit] = useMutation(mutation) + const [hasConfirmed, setHasConfirmed] = useState(false) + + return ( + + Important note: Deleting the secondary authentication token + will cause any future API requests using this token to fail. + + } + form={ + setHasConfirmed(!hasConfirmed)} + /> + } + label='I acknowledge the impact of this action' + /> + } + disableSubmit={!hasConfirmed} + onSubmit={() => + commit( + { + id: keyID, + }, + { additionalTypenames: ['IntegrationKey', 'Service'] }, + ).then((res) => { + if (!res.error) { + onClose() + } + }) + } + /> + ) +} diff --git a/web/src/app/services/UniversalKey/GenTokenDialog.tsx b/web/src/app/services/UniversalKey/GenTokenDialog.tsx new file mode 100644 index 0000000000..26546fcb3c --- /dev/null +++ b/web/src/app/services/UniversalKey/GenTokenDialog.tsx @@ -0,0 +1,70 @@ +import React from 'react' +import { FormHelperText, Grid, Typography } from '@mui/material' +import CopyText from '../../util/CopyText' +import { gql, useMutation } from 'urql' +import FormDialog from '../../dialogs/FormDialog' +import { nonFieldErrors } from '../../util/errutil' + +interface TokenCopyDialogProps { + keyID: string + onClose: () => void +} + +const mutation = gql` + mutation ($id: ID!) { + generateKeyToken(id: $id) + } +` + +function GenerateTokenText(): JSX.Element { + return ( + + Generates an auth bearer token that can immediately be used for this + integration. + + ) +} + +function CopyTokenText({ token }: { token: string }): JSX.Element { + return ( + + + + + Please copy and save the token as this is the only time you'll be able + to view it. + + + + ) +} + +export default function GenTokenDialog({ + keyID, + onClose, +}: TokenCopyDialogProps): JSX.Element { + const [status, commit] = useMutation(mutation) + const token = status.data?.generateKeyToken + + return ( + : } + onSubmit={() => + !token + ? commit( + { + id: keyID, + }, + { additionalTypenames: ['IntegrationKey', 'Service'] }, + ) + : onClose() + } + /> + ) +} diff --git a/web/src/app/services/UniversalKey/PromoteTokenDialog.tsx b/web/src/app/services/UniversalKey/PromoteTokenDialog.tsx new file mode 100644 index 0000000000..0fc3df3e25 --- /dev/null +++ b/web/src/app/services/UniversalKey/PromoteTokenDialog.tsx @@ -0,0 +1,64 @@ +import React, { useState } from 'react' +import { Checkbox, FormControlLabel, Typography } from '@mui/material' +import { gql, useMutation } from 'urql' +import FormDialog from '../../dialogs/FormDialog' +import { nonFieldErrors } from '../../util/errutil' + +interface PromoteTokenDialogProps { + keyID: string + onClose: () => void +} + +const mutation = gql` + mutation ($id: ID!) { + promoteSecondaryToken(id: $id) + } +` + +export default function PromoteTokenDialog({ + keyID, + onClose, +}: PromoteTokenDialogProps): JSX.Element { + const [status, commit] = useMutation(mutation) + const [hasConfirmed, setHasConfirmed] = useState(false) + + return ( + + Important note: Promoting the secondary token will + delete/replace the existing primary token. Any future API requests + using the existing primary token will fail. + + } + primaryActionLabel='Promote Key' + form={ + setHasConfirmed(!hasConfirmed)} + /> + } + label='I acknowledge the impact of this action' + /> + } + disableSubmit={!hasConfirmed} + onSubmit={() => + commit( + { + id: keyID, + }, + { additionalTypenames: ['IntegrationKey', 'Service'] }, + ).then((res) => { + if (!res.error) { + onClose() + } + }) + } + /> + ) +} diff --git a/web/src/app/services/UniversalKey/UniversalKeyActionsForm.tsx b/web/src/app/services/UniversalKey/UniversalKeyActionsForm.tsx new file mode 100644 index 0000000000..46be58394d --- /dev/null +++ b/web/src/app/services/UniversalKey/UniversalKeyActionsForm.tsx @@ -0,0 +1,167 @@ +import React, { useEffect, useState } from 'react' +import { Add } from '@mui/icons-material' +import { Button, Grid, Typography } from '@mui/material' +import { ActionInput } from '../../../schema' +import DynamicActionForm, { + actionInputToValue, + valueToActionInput, +} from '../../selection/DynamicActionForm' +import { CombinedError, gql, useClient } from 'urql' +import { useErrorConsumer } from '../../util/ErrorConsumer' +import UniversalKeyActionsList from './UniversalKeyActionsList' + +type FormValue = React.ComponentProps['value'] + +export type UniversalKeyActionsFormProps = { + value: Array + onChange: (value: Array) => void + + showList?: boolean + editActionId?: string + onChipClick?: (action: ActionInput) => void + + disablePortal?: boolean +} + +const query = gql` + query ValidateActionInput($input: ActionInput!) { + actionInputValidate(input: $input) + } +` + +const getAction = (actions: ActionInput[], id: string): FormValue => { + let input + if ((input = actions.find((v) => v.dest.type === id))) { + return actionInputToValue(input) + } + return null +} + +/** Manages a set of actions. */ +export default function UniversalKeyActionsForm( + props: UniversalKeyActionsFormProps, +): React.ReactNode { + const [currentAction, setCurrentAction] = useState( + props.editActionId ? getAction(props.value, props.editActionId) : null, + ) + const [addError, setAddError] = useState(null) + const valClient = useClient() + const errs = useErrorConsumer(addError) + let actions = props.value + + useEffect(() => { + if (props.editActionId) { + setCurrentAction(getAction(props.value, props.editActionId)) + } + }, [props.editActionId]) + + return ( + + {props.showList && ( + props.onChange(props.value.filter((v) => v !== a))} + onChipClick={(a) => { + if (props.onChipClick) { + props.onChipClick(a) + } + setCurrentAction(getAction(props.value, a.dest.type)) + }} + /> + )} + + + + + {errs.hasErrors() && ( + + {errs.remainingLegacy().map((e) => ( + + {e.message} + + ))} + + )} + + + + + + + ) +} diff --git a/web/src/app/services/UniversalKey/UniversalKeyActionsList.tsx b/web/src/app/services/UniversalKey/UniversalKeyActionsList.tsx new file mode 100644 index 0000000000..d2e63e9cee --- /dev/null +++ b/web/src/app/services/UniversalKey/UniversalKeyActionsList.tsx @@ -0,0 +1,65 @@ +import React from 'react' +import { ActionInput } from '../../../schema' +import DestinationInputChip from '../../util/DestinationInputChip' +import { Grid, Typography } from '@mui/material' + +export type UniversalKeyActionsListProps = { + actions: ReadonlyArray + + noHeader?: boolean + onDelete?: (action: ActionInput) => void + onChipClick?: (action: ActionInput) => void +} + +export default function UniversalKeyActionsList( + props: UniversalKeyActionsListProps, +): React.ReactNode { + return ( + + {!props.noHeader && ( + + + Actions + + + )} + + {props.actions.map((a) => ( + + props.onDelete && props.onDelete(a) + : undefined + } + onChipClick={ + props.onChipClick + ? () => props.onChipClick && props.onChipClick(a) + : undefined + } + /> + + ))} + {props.actions.length === 0 && ( + + + No actions + + + )} + + + ) +} diff --git a/web/src/app/services/UniversalKey/UniversalKeyDefaultActions.tsx b/web/src/app/services/UniversalKey/UniversalKeyDefaultActions.tsx new file mode 100644 index 0000000000..334edd8d73 --- /dev/null +++ b/web/src/app/services/UniversalKey/UniversalKeyDefaultActions.tsx @@ -0,0 +1,78 @@ +import { Button, Card } from '@mui/material' +import React, { Suspense, useState } from 'react' +import FlatList from '../../lists/FlatList' +import { Edit } from '@mui/icons-material' +import DefaultActionEditDialog from './DefaultActionEditDialog' +import UniversalKeyActionsList from './UniversalKeyActionsList' +import { gql, useQuery } from 'urql' +import { IntegrationKey } from '../../../schema' + +interface UniversalKeyDefaultActionProps { + serviceID: string + keyID: string +} + +const query = gql` + query UniversalKeyPage($keyID: ID!) { + integrationKey(id: $keyID) { + id + config { + defaultActions { + dest { + type + args + } + params + } + } + } + } +` + +export default function UniversalKeyDefaultActions( + props: UniversalKeyDefaultActionProps, +): React.ReactNode { + const [edit, setEdit] = useState(false) + const [q] = useQuery<{ integrationKey: IntegrationKey }>({ + query, + variables: { keyID: props.keyID }, + }) + + return ( + + + } + onClick={() => setEdit(true)} + > + Edit Default Action + + } + headerNote='Default actions are performed when zero rules match.' + items={[ + { + title: ( + + ), + }, + ]} + /> + + + {edit && ( + setEdit(false)} + keyID={props.keyID} + /> + )} + + + ) +} diff --git a/web/src/app/services/UniversalKey/UniversalKeyPage.tsx b/web/src/app/services/UniversalKey/UniversalKeyPage.tsx index 760674c3e1..2979601053 100644 --- a/web/src/app/services/UniversalKey/UniversalKeyPage.tsx +++ b/web/src/app/services/UniversalKey/UniversalKeyPage.tsx @@ -1,16 +1,152 @@ -import React from 'react' +import React, { useState } from 'react' +import { gql, useQuery } from 'urql' +import { Redirect } from 'wouter' +import { GenericError, ObjectNotFound } from '../../error-pages' +import { IntegrationKey, Service } from '../../../schema' +import UniversalKeyRuleList from './UniversalKeyRuleConfig' +import DetailsPage from '../../details/DetailsPage' +import { Action } from '../../details/CardActions' +import GenTokenDialog from './GenTokenDialog' +import PromoteTokenDialog from './PromoteTokenDialog' +import DeleteSecondaryTokenDialog from './DeleteSecondaryTokenDialog' +import UniversalKeyDefaultActions from './UniversalKeyDefaultActions' +import { Grid } from '@mui/material' interface UniversalKeyPageProps { serviceID: string - keyName: string + keyID: string } -export default function UniversalKeyPage({ - serviceID, - keyName, -}: UniversalKeyPageProps): JSX.Element { - if (serviceID && keyName) { - return
+const query = gql` + query UniversalKeyPage($keyID: ID!, $serviceID: ID!) { + integrationKey(id: $keyID) { + id + name + serviceID + tokenInfo { + primaryHint + secondaryHint + } + } + service(id: $serviceID) { + id + name + } } - return
+` + +export default function UniversalKeyPage( + props: UniversalKeyPageProps, +): React.ReactNode { + const [genDialogOpen, setGenDialogOpen] = useState(false) + const [promoteDialogOpen, setPromoteDialogOpen] = useState(false) + const [deleteDialogOpen, setDeleteDialogOpen] = useState(false) + + const [q] = useQuery<{ + integrationKey: IntegrationKey + service: Service + }>({ + query, + variables: { + keyID: props.keyID, + serviceID: props.serviceID, + }, + }) + + // Redirect to the correct service if the key is not in the service + if (q.data?.integrationKey.serviceID !== props.serviceID) { + return ( + + ) + } + + if (q.error) { + return + } + if (!q.data) return + + const primaryHint = q.data.integrationKey.tokenInfo.primaryHint + const secondaryHint = q.data.integrationKey.tokenInfo.secondaryHint + + const desc = secondaryHint + ? `Primary Auth Token: ${primaryHint}\nSecondary Auth Token: ${secondaryHint}` + : `Auth Token: ${primaryHint || 'N/A'}` + + function makeGenerateButtons(): Array { + if (primaryHint && !secondaryHint) { + return [ + { + label: 'Generate Secondary Token', + handleOnClick: () => setGenDialogOpen(true), + }, + ] + } + + if (primaryHint && secondaryHint) { + return [ + { + label: 'Delete Secondary Token', + handleOnClick: () => setDeleteDialogOpen(true), + }, + { + label: 'Promote Secondary Token', + handleOnClick: () => setPromoteDialogOpen(true), + }, + ] + } + + return [ + { + label: 'Generate Auth Token', + handleOnClick: () => setGenDialogOpen(true), + }, + ] + } + + return ( + + + + + + + + + + } + /> + {genDialogOpen && ( + setGenDialogOpen(false)} + /> + )} + {promoteDialogOpen && ( + setPromoteDialogOpen(false)} + /> + )} + {deleteDialogOpen && ( + setDeleteDialogOpen(false)} + /> + )} + + ) } diff --git a/web/src/app/services/UniversalKey/UniversalKeyRuleConfig.tsx b/web/src/app/services/UniversalKey/UniversalKeyRuleConfig.tsx new file mode 100644 index 0000000000..ba0aa6a780 --- /dev/null +++ b/web/src/app/services/UniversalKey/UniversalKeyRuleConfig.tsx @@ -0,0 +1,119 @@ +import React, { Suspense, useState } from 'react' +import { Button, Card } from '@mui/material' +import { Add } from '@mui/icons-material' +import FlatList, { FlatListListItem } from '../../lists/FlatList' +import UniversalKeyRuleCreateDialog from './UniversalKeyRuleCreateDialog' +import UniversalKeyRuleEditDialog from './UniversalKeyRuleEditDialog' +import UniversalKeyRuleRemoveDialog from './UniversalKeyRuleRemoveDialog' +import OtherActions from '../../util/OtherActions' +import { gql, useQuery } from 'urql' +import { IntegrationKey, Service } from '../../../schema' +import Spinner from '../../loading/components/Spinner' +import { GenericError } from '../../error-pages' + +interface UniversalKeyRuleListProps { + serviceID: string + keyID: string +} + +const query = gql` + query UniversalKeyPage($keyID: ID!) { + integrationKey(id: $keyID) { + id + config { + rules { + id + name + description + } + } + } + } +` + +export default function UniversalKeyRuleList( + props: UniversalKeyRuleListProps, +): JSX.Element { + const [create, setCreate] = useState(false) + const [edit, setEdit] = useState('') + const [remove, setRemove] = useState('') + + const [{ data, fetching, error }] = useQuery<{ + integrationKey: IntegrationKey + service: Service + }>({ + query, + variables: { + keyID: props.keyID, + serviceID: props.serviceID, + }, + }) + + if (fetching && !data) return + if (error) return + + const items: FlatListListItem[] = ( + data?.integrationKey.config.rules ?? [] + ).map((rule) => ({ + title: rule.name, + subText: rule.description, + secondaryAction: ( + setEdit(rule.id), + }, + { + label: 'Delete', + onClick: () => setRemove(rule.id), + }, + ]} + /> + ), + })) + + return ( + + + } + onClick={() => setCreate(true)} + > + Create Rule + + } + headerNote='Rules are a set of filters that allow notifications to be sent to a specific destination. ' + items={items} + /> + + + + {create && ( + setCreate(false)} + keyID={props.keyID} + /> + )} + {edit && ( + setEdit('')} + keyID={props.keyID} + ruleID={edit} + /> + )} + {remove && ( + setRemove('')} + keyID={props.keyID} + ruleID={remove} + /> + )} + + + ) +} diff --git a/web/src/app/services/UniversalKey/UniversalKeyRuleCreateDialog.tsx b/web/src/app/services/UniversalKey/UniversalKeyRuleCreateDialog.tsx new file mode 100644 index 0000000000..534525a0fd --- /dev/null +++ b/web/src/app/services/UniversalKey/UniversalKeyRuleCreateDialog.tsx @@ -0,0 +1,78 @@ +import React, { useState } from 'react' +import FormDialog from '../../dialogs/FormDialog' +import UniversalKeyRuleForm from './UniversalKeyRuleForm' +import { gql, useMutation } from 'urql' +import { KeyRuleInput } from '../../../schema' +import { getNotice } from './utils' +import { useErrorConsumer } from '../../util/ErrorConsumer' + +interface UniversalKeyRuleCreateDialogProps { + keyID: string + onClose: () => void +} + +const mutation = gql` + mutation ($input: UpdateKeyConfigInput!) { + updateKeyConfig(input: $input) + } +` + +export default function UniversalKeyRuleCreateDialogProps( + props: UniversalKeyRuleCreateDialogProps, +): JSX.Element { + const [value, setValue] = useState({ + name: '', + description: '', + conditionExpr: '', + continueAfterMatch: false, + actions: [], + }) + const [m, commit] = useMutation(mutation) + const [hasConfirmed, setHasConfirmed] = useState(false) + const [hasSubmitted, setHasSubmitted] = useState(false) + const noActionsNoConf = value.actions.length === 0 && !hasConfirmed + + const errs = useErrorConsumer(m.error) + const form = ( + + ) + + return ( + { + if (noActionsNoConf) { + setHasSubmitted(true) + return + } + + return commit( + { + input: { + keyID: props.keyID, + setRule: value, + }, + }, + { additionalTypenames: ['KeyConfig'] }, + ).then((res) => { + if (res.error) return + + props.onClose() + }) + }} + form={form} + notices={getNotice(hasSubmitted, hasConfirmed, setHasConfirmed)} + /> + ) +} diff --git a/web/src/app/services/UniversalKey/UniversalKeyRuleEditDialog.tsx b/web/src/app/services/UniversalKey/UniversalKeyRuleEditDialog.tsx new file mode 100644 index 0000000000..00bffb396d --- /dev/null +++ b/web/src/app/services/UniversalKey/UniversalKeyRuleEditDialog.tsx @@ -0,0 +1,115 @@ +import React, { useState } from 'react' +import { gql, useMutation, useQuery } from 'urql' +import FormDialog from '../../dialogs/FormDialog' +import UniversalKeyRuleForm from './UniversalKeyRuleForm' +import { IntegrationKey, KeyRuleInput } from '../../../schema' +import { getNotice } from './utils' +import { useErrorConsumer } from '../../util/ErrorConsumer' + +interface UniversalKeyRuleEditDialogProps { + keyID: string + ruleID: string + onClose: () => void + default?: boolean +} + +const query = gql` + query UniversalKeyPage($keyID: ID!, $ruleID: ID!) { + integrationKey(id: $keyID) { + id + config { + oneRule(id: $ruleID) { + id + name + description + conditionExpr + continueAfterMatch + actions { + dest { + type + args + } + params + } + } + } + } + } +` + +const mutation = gql` + mutation ($input: UpdateKeyConfigInput!) { + updateKeyConfig(input: $input) + } +` + +export default function UniversalKeyRuleEditDialog( + props: UniversalKeyRuleEditDialogProps, +): JSX.Element { + const [q] = useQuery<{ + integrationKey: IntegrationKey + }>({ + query, + variables: { + keyID: props.keyID, + ruleID: props.ruleID, + }, + }) + if (q.error) throw q.error + + // shouldn't happen due to suspense + if (!q.data) throw new Error('failed to load data') + + const rule = q.data.integrationKey.config.oneRule + if (!rule) throw new Error('rule not found') + + const [value, setValue] = useState(rule) + const [m, commit] = useMutation(mutation) + + const [hasConfirmed, setHasConfirmed] = useState(false) + const [hasSubmitted, setHasSubmitted] = useState(false) + const noActionsNoConf = value.actions.length === 0 && !hasConfirmed + const errs = useErrorConsumer(m.error) + const form = ( + + ) + + return ( + { + if (noActionsNoConf) { + setHasSubmitted(true) + return + } + + return commit( + { + input: { + keyID: props.keyID, + setRule: value, + }, + }, + { additionalTypenames: ['KeyConfig'] }, + ).then((res) => { + if (res.error) return + + props.onClose() + }) + }} + form={form} + errors={errs.remainingLegacy()} + notices={getNotice(hasSubmitted, hasConfirmed, setHasConfirmed)} + /> + ) +} diff --git a/web/src/app/services/UniversalKey/UniversalKeyRuleForm.tsx b/web/src/app/services/UniversalKey/UniversalKeyRuleForm.tsx new file mode 100644 index 0000000000..0110ef1f13 --- /dev/null +++ b/web/src/app/services/UniversalKey/UniversalKeyRuleForm.tsx @@ -0,0 +1,140 @@ +import React, { useState } from 'react' +import { + Divider, + FormControl, + FormControlLabel, + FormLabel, + Grid, + Radio, + RadioGroup, + TextField, +} from '@mui/material' +import { ActionInput, KeyRuleInput } from '../../../schema' +import UniversalKeyActionsList from './UniversalKeyActionsList' +import UniversalKeyActionsForm from './UniversalKeyActionsForm' + +interface UniversalKeyRuleFormProps { + value: KeyRuleInput + onChange: (val: Readonly) => void + + nameError?: string + descriptionError?: string + conditionError?: string +} + +export default function UniversalKeyRuleForm( + props: UniversalKeyRuleFormProps, +): JSX.Element { + const [editAction, setEditAction] = useState('') + + const handleChipClick = (action: ActionInput): void => { + setEditAction(action.dest.type) + } + + return ( + + + + { + props.onChange({ ...props.value, name: e.target.value }) + }} + error={!!props.nameError} + helperText={props.nameError} + /> + + + { + props.onChange({ ...props.value, description: e.target.value }) + }} + error={!!props.descriptionError} + helperText={props.descriptionError} + /> + + + { + props.onChange({ ...props.value, conditionExpr: e.target.value }) + }} + error={!!props.conditionError} + helperText={props.conditionError} + /> + + + props.onChange({ + ...props.value, + actions: props.value.actions.filter((v) => v !== a), + }) + } + onChipClick={handleChipClick} + /> + + + + After actions complete: + + + + props.onChange({ ...props.value, continueAfterMatch: true }) + } + control={} + label='Continue processing rules' + /> + + props.onChange({ ...props.value, continueAfterMatch: false }) + } + control={} + label='Stop at this rule' + /> + + + + + + + + + + + props.onChange({ ...props.value, actions })} + editActionId={editAction} + onChipClick={handleChipClick} + /> + + + ) +} diff --git a/web/src/app/services/UniversalKey/UniversalKeyRuleRemoveDialog.tsx b/web/src/app/services/UniversalKey/UniversalKeyRuleRemoveDialog.tsx new file mode 100644 index 0000000000..a4e9df9298 --- /dev/null +++ b/web/src/app/services/UniversalKey/UniversalKeyRuleRemoveDialog.tsx @@ -0,0 +1,44 @@ +import React from 'react' +import FormDialog from '../../dialogs/FormDialog' +import { gql, useMutation } from 'urql' +import { nonFieldErrors } from '../../util/errutil' + +interface UniversalKeyRuleCreateDialogProps { + keyID: string + ruleID: string + onClose: () => void +} + +const mutation = gql` + mutation ($input: UpdateKeyConfigInput!) { + updateKeyConfig(input: $input) + } +` + +export default function UniversalKeyRuleCreateDialogProps( + props: UniversalKeyRuleCreateDialogProps, +): JSX.Element { + const [deleteRuleResult, commit] = useMutation(mutation) + + return ( + + commit( + { + input: { + keyID: props.keyID, + deleteRule: props.ruleID, + }, + }, + { additionalTypenames: ['KeyConfig'] }, + ).then((res) => { + if (!res.error) props.onClose() + }) + } + errors={nonFieldErrors(deleteRuleResult.error)} + /> + ) +} diff --git a/web/src/app/services/UniversalKey/UniversalKeysActionsForm.stories.tsx b/web/src/app/services/UniversalKey/UniversalKeysActionsForm.stories.tsx new file mode 100644 index 0000000000..1219b9eb9c --- /dev/null +++ b/web/src/app/services/UniversalKey/UniversalKeysActionsForm.stories.tsx @@ -0,0 +1,105 @@ +import React from 'react' +import type { Meta, StoryObj } from '@storybook/react' +import { expect, userEvent, waitFor, within, fn } from '@storybook/test' +import { useArgs } from '@storybook/preview-api' +import UniversalKeyActionsForm from './UniversalKeyActionsForm' +import { ActionInput, DestinationDisplayInfo } from '../../../schema' + +const meta = { + title: 'UIK/Actions Form', + component: UniversalKeyActionsForm, + args: { + onChange: fn(), + }, + render: function Component(args) { + const [, setArgs] = useArgs() + const onChange = (newValue: Array): void => { + if (args.onChange) args.onChange(newValue) + setArgs({ value: newValue }) + } + return ( + + ) + }, + tags: ['autodocs'], +} satisfies Meta + +export default meta +type Story = StoryObj +export const Empty: Story = { + args: { + value: [], + }, +} + +export const WithList: Story = { + args: { + showList: true, + value: [{ dest: { type: 'foo', args: {} }, params: {} }], + }, + parameters: { + graphql: { + DestDisplayInfo: { + data: { + destinationDisplayInfo: { + text: 'VALID_CHIP_1', + iconURL: 'builtin://rotation', + linkURL: '', + iconAltText: 'Rotation', + } satisfies DestinationDisplayInfo, + }, + }, + }, + }, +} + +export const ValidationError: Story = { + args: { + showList: true, + value: [], + }, + parameters: { + graphql: { + ValidateActionInput: { + errors: [ + { message: 'generic error' }, + { + path: ['actionInputValidate', 'input', 'dest', 'type'], + message: 'invalid type', + }, + { + path: ['actionInputValidate', 'input', 'dest', 'args'], + extensions: { + key: 'phone-number', + }, + message: 'invalid number', + }, + { + path: ['actionInputValidate', 'input', 'params'], + extensions: { + key: 'example-param', + }, + message: 'invalid param', + }, + ], + }, + }, + }, + + play: async ({ canvasElement }) => { + const canvas = within(canvasElement) + userEvent.click(canvas.getByLabelText('Destination Type')) + userEvent.click(await canvas.findByText('Single Field')) + await canvas.findByLabelText('Phone Number') + userEvent.click(await canvas.findByRole('button', { name: /add/i })) + + waitFor(async () => { + expect(await canvas.getByLabelText('Phone Number')).toBeInvalid() + expect( + await canvas.getByLabelText('Example Param (Expr syntax)'), + ).toBeInvalid() + expect(canvas.getByText('generic error')).toBeVisible() + expect(canvas.getByText('invalid type')).toBeVisible() + }) + }, +} diff --git a/web/src/app/services/UniversalKey/utils.tsx b/web/src/app/services/UniversalKey/utils.tsx new file mode 100644 index 0000000000..ffb3141cd3 --- /dev/null +++ b/web/src/app/services/UniversalKey/utils.tsx @@ -0,0 +1,31 @@ +import React from 'react' +import { Notice } from '../../details/Notices' +import { FormControlLabel, Checkbox } from '@mui/material' + +export function getNotice( + hasSubmitted: boolean, + hasConfirmed: boolean, + setHasConfirmed: (b: boolean) => void, +): Notice[] { + if (!hasSubmitted) return [] + + return [ + { + type: 'WARNING', + message: 'No actions', + details: + 'If you submit with no actions created, nothing will happen on this step', + action: ( + setHasConfirmed(!hasConfirmed)} + /> + } + label='I acknowledge the impact of this' + /> + ), + }, + ] +} diff --git a/web/src/app/storybook/decorators.tsx b/web/src/app/storybook/decorators.tsx index 716b2eefba..1640d9976a 100644 --- a/web/src/app/storybook/decorators.tsx +++ b/web/src/app/storybook/decorators.tsx @@ -1,7 +1,7 @@ import React from 'react' import { ConfigProvider } from '../util/RequireConfig' -import { Provider as URQLProvider } from 'urql' -import { client as urqlClient } from '../urql' +import { Client, Provider as URQLProvider } from 'urql' +import { newClient } from '../urql' import { StyledEngineProvider } from '@mui/material' import { ThemeProvider } from '../theme/themeConfig' import { ErrorBoundary } from 'react-error-boundary' @@ -36,10 +36,16 @@ function fallbackRender({ type Func = DecoratorFunction type FuncParams = Parameters +const clientCache: Record = {} + export default function DefaultDecorator( Story: FuncParams[0], args: FuncParams[1], ): ReturnType { + const client = + clientCache[args.id] || + newClient('/' + encodeURIComponent(args.id) + '/api/graphql') + clientCache[args.id] = client return ( - + diff --git a/web/src/app/storybook/defaultDestTypes.ts b/web/src/app/storybook/defaultDestTypes.ts index a4fcaaa576..bebdcd3aea 100644 --- a/web/src/app/storybook/defaultDestTypes.ts +++ b/web/src/app/storybook/defaultDestTypes.ts @@ -9,10 +9,19 @@ export const destTypes: DestinationTypeInfo[] = [ isContactMethod: true, isEPTarget: true, isSchedOnCallNotify: true, + isDynamicAction: true, iconURL: '', iconAltText: '', supportsStatusUpdates: false, statusUpdatesRequired: false, + dynamicParams: [ + { + paramID: 'example-param', + label: 'Example Param', + hint: 'Some hint text', + hintURL: '', + }, + ], requiredFields: [ { fieldID: 'phone-number', @@ -35,10 +44,12 @@ export const destTypes: DestinationTypeInfo[] = [ isContactMethod: true, isEPTarget: true, isSchedOnCallNotify: true, + isDynamicAction: false, iconURL: '', iconAltText: '', supportsStatusUpdates: true, statusUpdatesRequired: false, + dynamicParams: [], requiredFields: [ { fieldID: 'first-field', @@ -83,10 +94,12 @@ export const destTypes: DestinationTypeInfo[] = [ isContactMethod: true, isEPTarget: false, isSchedOnCallNotify: false, + isDynamicAction: false, iconURL: '', iconAltText: '', supportsStatusUpdates: true, statusUpdatesRequired: false, + dynamicParams: [], requiredFields: [ { fieldID: 'phone-number', @@ -109,10 +122,12 @@ export const destTypes: DestinationTypeInfo[] = [ isContactMethod: true, isEPTarget: false, isSchedOnCallNotify: false, + isDynamicAction: false, iconURL: '', iconAltText: '', supportsStatusUpdates: false, statusUpdatesRequired: true, + dynamicParams: [], requiredFields: [ { fieldID: 'phone-number', @@ -135,10 +150,12 @@ export const destTypes: DestinationTypeInfo[] = [ isContactMethod: true, isEPTarget: true, isSchedOnCallNotify: true, + isDynamicAction: true, iconURL: '', iconAltText: '', supportsStatusUpdates: false, statusUpdatesRequired: false, + dynamicParams: [], requiredFields: [ { fieldID: 'disabled', diff --git a/web/src/app/theme/themeConfig.tsx b/web/src/app/theme/themeConfig.tsx index c52848e3df..1686f6599f 100644 --- a/web/src/app/theme/themeConfig.tsx +++ b/web/src/app/theme/themeConfig.tsx @@ -116,6 +116,11 @@ function makeTheme(mode: MUIThemeMode, sourceColor: string): Theme { color: 'primary', }, }, + MuiTextField: { + defaultProps: { + margin: 'dense', + }, + }, MuiBreadcrumbs: { styleOverrides: { separator: { diff --git a/web/src/app/urql.ts b/web/src/app/urql.ts index e76a9f002b..98c52a7639 100644 --- a/web/src/app/urql.ts +++ b/web/src/app/urql.ts @@ -5,6 +5,7 @@ import { fetchExchange, Exchange, Operation, + Client, } from 'urql' import { pipe, tap } from 'wonka' import { GraphQLClient, GraphQLClientWithErrors } from './apollo' @@ -104,15 +105,19 @@ const apolloRefetchExchange: Exchange = ({ forward }) => { } } -export const client = createClient({ - url: pathPrefix + '/api/graphql', - suspense: true, - exchanges: [ - refetchExchange(), - cacheExchange, - apolloRefetchExchange, - retryExchange({}) as Exchange, - fetchExchange, - ], - requestPolicy: 'cache-and-network', -}) +export function newClient(url: string): Client { + return createClient({ + url, + suspense: true, + exchanges: [ + refetchExchange(), + cacheExchange, + apolloRefetchExchange, + retryExchange({}) as Exchange, + fetchExchange, + ], + requestPolicy: 'cache-and-network', + }) +} + +export const client = newClient(pathPrefix + '/api/graphql') diff --git a/web/src/app/users/UserContactMethodCreateDialogDest.stories.tsx b/web/src/app/users/UserContactMethodCreateDialog.stories.tsx similarity index 94% rename from web/src/app/users/UserContactMethodCreateDialogDest.stories.tsx rename to web/src/app/users/UserContactMethodCreateDialog.stories.tsx index 928e5c2132..137da422e6 100644 --- a/web/src/app/users/UserContactMethodCreateDialogDest.stories.tsx +++ b/web/src/app/users/UserContactMethodCreateDialog.stories.tsx @@ -1,19 +1,15 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' -import UserContactMethodCreateDialogDest from './UserContactMethodCreateDialogDest' +import UserContactMethodCreateDialog from './UserContactMethodCreateDialog' import { expect, fn, userEvent, waitFor, within } from '@storybook/test' -import { - handleDefaultConfig, - defaultConfig, - handleExpFlags, -} from '../storybook/graphql' +import { handleDefaultConfig, defaultConfig } from '../storybook/graphql' import { useArgs } from '@storybook/preview-api' import { HttpResponse, graphql } from 'msw' import { DestFieldValueError, InputFieldError } from '../util/errtypes' const meta = { - title: 'users/UserContactMethodCreateDialogDest', - component: UserContactMethodCreateDialogDest, + title: 'users/UserContactMethodCreateDialog', + component: UserContactMethodCreateDialog, tags: ['autodocs'], args: { onClose: fn(), @@ -28,7 +24,6 @@ const meta = { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.mutation( 'CreateUserContactMethodInput', ({ variables: vars }) => { @@ -93,14 +88,14 @@ const meta = { setArgs({ value: contactMethodID }) } return ( - ) }, -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj diff --git a/web/src/app/users/UserContactMethodCreateDialog.tsx b/web/src/app/users/UserContactMethodCreateDialog.tsx index 43252f7c21..fcfca725dc 100644 --- a/web/src/app/users/UserContactMethodCreateDialog.tsx +++ b/web/src/app/users/UserContactMethodCreateDialog.tsx @@ -1,94 +1,70 @@ -import React, { useState } from 'react' -import { useMutation, useQuery, gql } from 'urql' +import React, { useEffect, useState } from 'react' +import { useMutation, gql, CombinedError } from 'urql' -import { fieldErrors, nonFieldErrors } from '../util/errutil' import FormDialog from '../dialogs/FormDialog' import UserContactMethodForm from './UserContactMethodForm' -import { useConfigValue } from '../util/RequireConfig' +import { useContactMethodTypes } from '../util/RequireConfig' import { Dialog, DialogTitle, DialogActions, Button } from '@mui/material' import DialogContentError from '../dialogs/components/DialogContentError' -import { ContactMethodType } from '../../schema' -import { useExpFlag } from '../util/useExpFlag' -import UserContactMethodCreateDialogDest from './UserContactMethodCreateDialogDest' +import { DestinationInput } from '../../schema' +import { useErrorConsumer } from '../util/ErrorConsumer' type Value = { name: string - type: ContactMethodType - value: string + dest: DestinationInput + statusUpdates: boolean } const createMutation = gql` - mutation ($input: CreateUserContactMethodInput!) { + mutation CreateUserContactMethodInput($input: CreateUserContactMethodInput!) { createUserContactMethod(input: $input) { id } } ` -const userConflictQuery = gql` - query ($input: UserSearchOptions) { - users(input: $input) { - nodes { - id - name - } - } - } -` - -const noSuspense = { suspense: false } - -type UserContactMethodCreateDialogProps = { +export default function UserContactMethodCreateDialog(props: { userID: string onClose: (contactMethodID?: string) => void title?: string subtitle?: string -} - -function UserContactMethodCreateDialog( - props: UserContactMethodCreateDialogProps, -): React.ReactNode { - const [allowSV, allowE, allowW, allowS] = useConfigValue( - 'Twilio.Enable', - 'SMTP.Enable', - 'Webhook.Enable', - 'Slack.Enable', - ) - let typeVal: ContactMethodType = 'VOICE' - if (allowSV) { - typeVal = 'SMS' - } else if (allowE) { - typeVal = 'EMAIL' - } else if (allowW) { - typeVal = 'WEBHOOK' - } else if (allowS) { - typeVal = 'SLACK_DM' - } + disablePortal?: boolean +}): React.ReactNode { + const defaultType = useContactMethodTypes()[0] // will be sorted by priority, and enabled first // values for contact method form - const [CMValue, setCMValue] = useState({ + const [CMValue, _setCMValue] = useState({ name: '', - type: typeVal, - value: '', - }) - - const [{ data, fetching: queryLoading }] = useQuery({ - query: userConflictQuery, - variables: { - input: { - CMValue: CMValue.value, - CMType: CMValue.type, - }, + dest: { + type: defaultType.type, + args: {}, }, - context: noSuspense, + statusUpdates: false, }) + const [createErr, setCreateErr] = useState(null) + const setCMValue = (newValue: Value): void => { + _setCMValue(newValue) + setCreateErr(null) + } + + // TODO: useQuery for userConflictQuery const [createCMStatus, createCM] = useMutation(createMutation) + useEffect(() => { + setCreateErr(createCMStatus.error || null) + }, [createCMStatus.error]) + + const errs = useErrorConsumer(createErr) - if (!typeVal) { + if (!defaultType.enabled) { + // default type will be the first enabled type, so if it's not enabled, none are enabled return ( - props.onClose()}> + props.onClose()} + > No Contact Types Available @@ -100,48 +76,41 @@ function UserContactMethodCreateDialog( ) } - const { fetching, error } = createCMStatus const { title = 'Create New Contact Method', subtitle } = props - let fieldErrs = fieldErrors(error) - if (!queryLoading && data?.users?.nodes?.length > 0) { - fieldErrs = fieldErrs.map((err) => { - if ( - err.message === 'contact method already exists for that type and value' - ) { - return { - ...err, - message: `${err.message}: ${data.users.nodes[0].name}`, - helpLink: `/users/${data.users.nodes[0].id}`, - } - } - return err - }) - } - const form = ( setCMValue(CMValue)} value={CMValue} + disablePortal={props.disablePortal} /> ) return ( createCM( { input: { - ...CMValue, + name: CMValue.name, + dest: CMValue.dest, + enableStatusUpdates: CMValue.statusUpdates, userID: props.userID, newUserNotificationRule: { delayMinutes: 0, @@ -160,15 +129,3 @@ function UserContactMethodCreateDialog( /> ) } - -export default function UserContactMethodCreateDialogSwitch( - props: UserContactMethodCreateDialogProps, -): React.ReactNode { - const isDestTypesSet = useExpFlag('dest-types') - - if (isDestTypesSet) { - return - } - - return -} diff --git a/web/src/app/users/UserContactMethodCreateDialogDest.tsx b/web/src/app/users/UserContactMethodCreateDialogDest.tsx deleted file mode 100644 index 1a7e6019cb..0000000000 --- a/web/src/app/users/UserContactMethodCreateDialogDest.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { useMutation, gql, CombinedError } from 'urql' - -import { splitErrorsByPath } from '../util/errutil' -import FormDialog from '../dialogs/FormDialog' -import UserContactMethodForm, { errorPaths } from './UserContactMethodFormDest' -import { useContactMethodTypes } from '../util/RequireConfig' -import { Dialog, DialogTitle, DialogActions, Button } from '@mui/material' -import DialogContentError from '../dialogs/components/DialogContentError' -import { DestinationInput } from '../../schema' - -type Value = { - name: string - dest: DestinationInput - statusUpdates: boolean -} - -const createMutation = gql` - mutation CreateUserContactMethodInput($input: CreateUserContactMethodInput!) { - createUserContactMethod(input: $input) { - id - } - } -` - -export default function UserContactMethodCreateDialogDest(props: { - userID: string - onClose: (contactMethodID?: string) => void - title?: string - subtitle?: string - - disablePortal?: boolean -}): React.ReactNode { - const defaultType = useContactMethodTypes()[0] // will be sorted by priority, and enabled first - - // values for contact method form - const [CMValue, _setCMValue] = useState({ - name: '', - dest: { - type: defaultType.type, - values: [], - }, - statusUpdates: false, - }) - const [createErr, setCreateErr] = useState(null) - const setCMValue = (newValue: Value): void => { - _setCMValue(newValue) - setCreateErr(null) - } - - // TODO: useQuery for userConflictQuery - - const [createCMStatus, createCM] = useMutation(createMutation) - useEffect(() => { - setCreateErr(createCMStatus.error || null) - }, [createCMStatus.error]) - - const [formErrors, otherErrs] = splitErrorsByPath( - createErr, - errorPaths('createUserContactMethod.input'), - ) - - if (!defaultType.enabled) { - // default type will be the first enabled type, so if it's not enabled, none are enabled - return ( - props.onClose()} - > - No Contact Types Available - - - - - - ) - } - - const { title = 'Create New Contact Method', subtitle } = props - - const form = ( - setCMValue(CMValue)} - value={CMValue} - disablePortal={props.disablePortal} - /> - ) - - return ( - - createCM( - { - input: { - name: CMValue.name, - dest: CMValue.dest, - enableStatusUpdates: CMValue.statusUpdates, - userID: props.userID, - newUserNotificationRule: { - delayMinutes: 0, - }, - }, - }, - { additionalTypenames: ['UserContactMethod', 'User'] }, - ).then((result) => { - if (result.error) { - return - } - props.onClose(result.data.createUserContactMethod.id) - }) - } - form={form} - /> - ) -} diff --git a/web/src/app/users/UserContactMethodDeleteDialog.tsx b/web/src/app/users/UserContactMethodDeleteDialog.tsx index 67f0d5a87a..c42e89f011 100644 --- a/web/src/app/users/UserContactMethodDeleteDialog.tsx +++ b/web/src/app/users/UserContactMethodDeleteDialog.tsx @@ -29,7 +29,7 @@ function UserContactMethodDeleteDialog(props: { { id: contactMethodID, }, - { additionalTypenames: ['UserContactMethod'] }, + { additionalTypenames: ['UserContactMethod', 'User'] }, ).then((res) => { if (res.error) return diff --git a/web/src/app/users/UserContactMethodEditDialogDest.stories.tsx b/web/src/app/users/UserContactMethodEditDialog.stories.tsx similarity index 91% rename from web/src/app/users/UserContactMethodEditDialogDest.stories.tsx rename to web/src/app/users/UserContactMethodEditDialog.stories.tsx index 3137e5c217..3fc17919ea 100644 --- a/web/src/app/users/UserContactMethodEditDialogDest.stories.tsx +++ b/web/src/app/users/UserContactMethodEditDialog.stories.tsx @@ -1,16 +1,16 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' -import UserContactMethodEditDialogDest from './UserContactMethodEditDialogDest' +import UserContactMethodEditDialog from './UserContactMethodEditDialog' import { expect, fn, userEvent, waitFor, within } from '@storybook/test' -import { handleDefaultConfig, handleExpFlags } from '../storybook/graphql' +import { handleDefaultConfig } from '../storybook/graphql' import { useArgs } from '@storybook/preview-api' import { HttpResponse, graphql } from 'msw' import { DestFieldValueError, InputFieldError } from '../util/errtypes' import { Destination } from '../../schema' const meta = { - title: 'users/UserContactMethodEditDialogDest', - component: UserContactMethodEditDialogDest, + title: 'users/UserContactMethodEditDialog', + component: UserContactMethodEditDialog, tags: ['autodocs'], args: { onClose: fn(), @@ -25,7 +25,6 @@ const meta = { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('userCm', ({ variables: vars }) => { return HttpResponse.json({ data: { @@ -42,13 +41,14 @@ const meta = { value: '+15555555555', }, ], + args: { 'phone-number': '+15555555555' }, displayInfo: { text: '+1 555-555-5555', iconAltText: 'Voice Call', iconURL: '', linkURL: '', }, - } satisfies Destination, + } satisfies Partial, value: 'http://localhost:8080', statusUpdates: 'DISABLED', disabled: false, @@ -73,13 +73,18 @@ const meta = { value: 'slack', }, ], + args: { + 'first-field': '+11235550123', + 'second-field': 'foobar@example.com', + 'third-field': 'slack', + }, displayInfo: { text: '11235550123', iconAltText: 'Mulitple Fields Example', iconURL: '', linkURL: '', }, - } satisfies Destination, + } satisfies Partial, statusUpdates: 'ENABLED', disabled: false, pending: false, @@ -148,14 +153,10 @@ const meta = { setArgs({ value: contactMethodID }) } return ( - + ) }, -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj diff --git a/web/src/app/users/UserContactMethodEditDialog.tsx b/web/src/app/users/UserContactMethodEditDialog.tsx index 9fbd9e113b..b5473d2a38 100644 --- a/web/src/app/users/UserContactMethodEditDialog.tsx +++ b/web/src/app/users/UserContactMethodEditDialog.tsx @@ -1,116 +1,105 @@ -import React, { useState } from 'react' -import { gql, useMutation } from '@apollo/client' -import { fieldErrors, nonFieldErrors } from '../util/errutil' +import React, { useEffect, useState } from 'react' +import { useMutation, gql, CombinedError, useQuery } from 'urql' + import FormDialog from '../dialogs/FormDialog' import UserContactMethodForm from './UserContactMethodForm' -import { pick } from 'lodash' -import { useQuery } from 'urql' -import { useExpFlag } from '../util/useExpFlag' -import { ContactMethodType, StatusUpdateState } from '../../schema' -import UserContactMethodEditDialogDest from './UserContactMethodEditDialogDest' +import { DestinationInput } from '../../schema' +import { useErrorConsumer } from '../util/ErrorConsumer' + +type Value = { + name: string + dest: DestinationInput + statusUpdates: boolean +} const query = gql` - query ($id: ID!) { + query userCm($id: ID!) { userContactMethod(id: $id) { id name - type - value + dest { + type + args + } statusUpdates } } ` const mutation = gql` - mutation ($input: UpdateUserContactMethodInput!) { + mutation UpdateUserContactMethod($input: UpdateUserContactMethodInput!) { updateUserContactMethod(input: $input) } ` -type Value = { - name: string - type: ContactMethodType - value: string - statusUpdates?: StatusUpdateState -} -type UserContactMethodEditDialogProps = { - onClose: () => void +export default function UserContactMethodEditDialog(props: { + onClose: (contactMethodID?: string) => void contactMethodID: string -} -function UserContactMethodEditDialog({ - onClose, - contactMethodID, -}: { - onClose: () => void - contactMethodID: string + disablePortal?: boolean }): React.ReactNode { - const [value, setValue] = useState(null) const [{ data, fetching }] = useQuery({ query, - variables: { id: contactMethodID }, + variables: { id: props.contactMethodID }, + }) + const statusUpdates = + data?.userContactMethod?.statusUpdates?.includes('ENABLED') + // values for contact method form + const [CMValue, _setCMValue] = useState({ + ...data?.userContactMethod, + statusUpdates, }) - const [commit, status] = useMutation(mutation) - const { error } = status - const defaultValue = { - name: data.userContactMethod.name, - type: data.userContactMethod.type, - value: data.userContactMethod.value, - statusUpdates: data.userContactMethod.statusUpdates, + const [updateErr, setUpdateErr] = useState(null) + const setCMValue = (newValue: Value): void => { + _setCMValue(newValue) + setUpdateErr(null) } - const fieldErrs = fieldErrors(error) + const [updateCMStatus, updateCM] = useMutation(mutation) + useEffect(() => { + setUpdateErr(updateCMStatus.error || null) + }, [updateCMStatus.error]) + const errs = useErrorConsumer(updateErr) + + const form = ( + setCMValue(CMValue)} + value={CMValue} + /> + ) return ( { - const updates = pick(value, 'name', 'statusUpdates') - // the form uses the 'statusUpdates' enum but the mutation simply - // needs to know if the status updates should be enabled or not via - // the 'enableStatusUpdates' boolean - if ('statusUpdates' in updates) { - delete Object.assign(updates, { - enableStatusUpdates: updates.statusUpdates === 'ENABLED', - }).statusUpdates - } - commit({ - variables: { + updateCM( + { input: { - ...updates, - id: contactMethodID, + id: props.contactMethodID, + name: CMValue.name, + enableStatusUpdates: Boolean(CMValue.statusUpdates), }, }, - }).then((result) => { - if (result.errors) return - onClose() + { additionalTypenames: ['UserContactMethod'] }, + ).then((result) => { + if (result.error) { + return + } + props.onClose() }) }} - form={ - setValue(value)} - /> - } + form={form} /> ) } - -export default function UserContactMethodEditDialogSwitch( - props: UserContactMethodEditDialogProps, -): React.ReactNode { - const isDestTypesSet = useExpFlag('dest-types') - - if (isDestTypesSet) { - return - } - - return -} diff --git a/web/src/app/users/UserContactMethodEditDialogDest.tsx b/web/src/app/users/UserContactMethodEditDialogDest.tsx deleted file mode 100644 index fb8d934e71..0000000000 --- a/web/src/app/users/UserContactMethodEditDialogDest.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { useMutation, gql, CombinedError, useQuery } from 'urql' - -import { splitErrorsByPath } from '../util/errutil' -import FormDialog from '../dialogs/FormDialog' -import UserContactMethodForm, { errorPaths } from './UserContactMethodFormDest' -import { DestinationInput } from '../../schema' - -type Value = { - name: string - dest: DestinationInput - statusUpdates: boolean -} - -const query = gql` - query userCm($id: ID!) { - userContactMethod(id: $id) { - id - name - dest { - type - values { - fieldID - value - } - } - statusUpdates - } - } -` - -const mutation = gql` - mutation UpdateUserContactMethod($input: UpdateUserContactMethodInput!) { - updateUserContactMethod(input: $input) - } -` - -export default function UserContactMethodEditDialogDest(props: { - onClose: (contactMethodID?: string) => void - contactMethodID: string - - disablePortal?: boolean -}): React.ReactNode { - const [{ data, fetching }] = useQuery({ - query, - variables: { id: props.contactMethodID }, - }) - const statusUpdates = - data?.userContactMethod?.statusUpdates?.includes('ENABLED') - // values for contact method form - const [CMValue, _setCMValue] = useState({ - ...data?.userContactMethod, - statusUpdates, - }) - - const [updateErr, setUpdateErr] = useState(null) - const setCMValue = (newValue: Value): void => { - _setCMValue(newValue) - setUpdateErr(null) - } - - const [updateCMStatus, updateCM] = useMutation(mutation) - useEffect(() => { - setUpdateErr(updateCMStatus.error || null) - }, [updateCMStatus.error]) - - const [formErrors, otherErrs] = splitErrorsByPath( - updateErr, - errorPaths('updateUserContactMethod.input'), - ) - - const form = ( - setCMValue(CMValue)} - value={CMValue} - /> - ) - - return ( - { - updateCM( - { - input: { - id: props.contactMethodID, - name: CMValue.name, - enableStatusUpdates: Boolean(CMValue.statusUpdates), - }, - }, - { additionalTypenames: ['UserContactMethod'] }, - ).then((result) => { - if (result.error) { - return - } - props.onClose() - }) - }} - form={form} - /> - ) -} diff --git a/web/src/app/users/UserContactMethodFormDest.stories.tsx b/web/src/app/users/UserContactMethodForm.stories.tsx similarity index 72% rename from web/src/app/users/UserContactMethodFormDest.stories.tsx rename to web/src/app/users/UserContactMethodForm.stories.tsx index 7edc8e1dbe..685866a937 100644 --- a/web/src/app/users/UserContactMethodFormDest.stories.tsx +++ b/web/src/app/users/UserContactMethodForm.stories.tsx @@ -1,20 +1,19 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' -import UserContactMethodFormDest, { Value } from './UserContactMethodFormDest' +import UserContactMethodForm, { Value } from './UserContactMethodForm' import { expect, within, userEvent, waitFor } from '@storybook/test' -import { handleDefaultConfig, handleExpFlags } from '../storybook/graphql' +import { handleDefaultConfig } from '../storybook/graphql' import { useArgs } from '@storybook/preview-api' import { HttpResponse, graphql } from 'msw' const meta = { - title: 'users/UserContactMethodFormDest', - component: UserContactMethodFormDest, + title: 'users/UserContactMethodForm', + component: UserContactMethodForm, tags: ['autodocs'], parameters: { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('ValidateDestination', ({ variables: vars }) => { return HttpResponse.json({ data: { @@ -31,9 +30,9 @@ const meta = { if (args.onChange) args.onChange(newValue) setArgs({ value: newValue }) } - return + return }, -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj @@ -44,12 +43,7 @@ export const SupportStatusUpdates: Story = { name: 'supports status', dest: { type: 'supports-status', - values: [ - { - fieldID: 'phone-number', - value: '+15555555555', - }, - ], + args: { 'phone-number': '+15555555555' }, }, statusUpdates: false, }, @@ -71,12 +65,7 @@ export const RequiredStatusUpdates: Story = { name: 'required status', dest: { type: 'required-status', - values: [ - { - fieldID: 'phone-number', - value: '+15555555555', - }, - ], + args: { 'phone-number': '+15555555555' }, }, statusUpdates: false, }, @@ -100,26 +89,12 @@ export const ErrorSingleField: Story = { name: '-notvalid', dest: { type: 'single-field', - values: [ - { - fieldID: 'phone-number', - value: '+', - }, - ], + args: { 'phone-number': '+15555555555' }, }, statusUpdates: false, }, disabled: false, - errors: [ - { - message: 'number is too short', // note: the 'n' is lowercase - path: ['input', 'dest'], - extensions: { - code: 'INVALID_DEST_FIELD_VALUE', - fieldID: 'phone-number', - }, - }, - ], + destFieldErrors: { 'phone-number': 'number is too short' }, }, play: async ({ canvasElement }) => { const canvas = within(canvasElement) @@ -139,33 +114,16 @@ export const ErrorMultiField: Story = { name: '-notvalid', dest: { type: 'triple-field', - values: [ - { - fieldID: 'first-field', - value: '+', - }, - { - fieldID: 'second-field', - value: 'notAnEmail', - }, - { - fieldID: 'third-field', - value: '-', - }, - ], + args: { + 'first-field': '+', + 'second-field': 'notAnEmail', + 'third-field': '-', + }, }, statusUpdates: false, }, disabled: false, - errors: [ - { - path: ['input', 'name'], - message: 'must begin with a letter', - extensions: { - code: 'INVALID_INPUT_VALUE', - }, - }, - ], + nameError: 'must begin with a letter', }, play: async ({ canvasElement }) => { const canvas = within(canvasElement) @@ -188,7 +146,7 @@ export const Disabled: Story = { name: 'disabled dest', dest: { type: 'triple-field', - values: [], + args: {}, }, statusUpdates: false, }, diff --git a/web/src/app/users/UserContactMethodForm.tsx b/web/src/app/users/UserContactMethodForm.tsx index 29523a2adc..0d237bbaff 100644 --- a/web/src/app/users/UserContactMethodForm.tsx +++ b/web/src/app/users/UserContactMethodForm.tsx @@ -1,257 +1,173 @@ import { Checkbox, FormControlLabel, Typography } from '@mui/material' import Grid from '@mui/material/Grid' import TextField from '@mui/material/TextField' -import React, { useMemo } from 'react' -import { ContactMethodType, StatusUpdateState } from '../../schema' -import { FormContainer, FormField } from '../forms' -import { - renderMenuItem, - sortDisableableMenuItems, -} from '../selection/DisableableMenuItem' -import { useConfigValue } from '../util/RequireConfig' -import TelTextField from '../util/TelTextField' -import { FieldError } from '../util/errutil' -import AppLink from '../util/AppLink' - -type Value = { +import React from 'react' +import { DestinationInput } from '../../schema' +import { FormContainer } from '../forms' +import { renderMenuItem } from '../selection/DisableableMenuItem' +import DestinationField from '../selection/DestinationField' +import { useContactMethodTypes } from '../util/RequireConfig' + +export type Value = { name: string - type: ContactMethodType - value: string - statusUpdates?: StatusUpdateState + dest: DestinationInput + statusUpdates: boolean } export type UserContactMethodFormProps = { value: Value - errors?: Array + nameError?: string + destTypeError?: string + destFieldErrors?: Readonly> disabled?: boolean edit?: boolean - onChange?: (CMValue: Value) => void -} - -function renderEmailField(edit: boolean): JSX.Element { - return ( - - ) -} - -function renderPhoneField(edit: boolean): JSX.Element { - return ( - - - - ) -} - -function renderURLField(edit: boolean): JSX.Element { - return ( - - Webhook Documentation - - } - /> - ) -} + disablePortal?: boolean // for testing, disable portal on select menu -function renderSlackField(edit: boolean): JSX.Element { - return ( - - ) -} - -function renderTypeField(type: ContactMethodType, edit: boolean): JSX.Element { - switch (type) { - case 'SMS': - case 'VOICE': - return renderPhoneField(edit) - case 'EMAIL': - return renderEmailField(edit) - case 'WEBHOOK': - return renderURLField(edit) - case 'SLACK_DM': - return renderSlackField(edit) - default: - } - - // fallback to generic - return ( - - ) + onChange?: (CMValue: Value) => void } -const isPhoneType = (val: Value): boolean => - val.type === 'SMS' || val.type === 'VOICE' - export default function UserContactMethodForm( props: UserContactMethodFormProps, ): JSX.Element { const { value, edit = false, ...other } = props - const [ - smsVoiceEnabled, - emailEnabled, - webhookEnabled, - slackEnabled, - disclaimer, - ] = useConfigValue( - 'Twilio.Enable', - 'SMTP.Enable', - 'Webhook.Enable', - 'Slack.Enable', - 'General.NotificationDisclaimer', - ) + const destinationTypes = useContactMethodTypes() + const currentType = destinationTypes.find((d) => d.type === value.dest.type) - const statusUpdateChecked = - value.statusUpdates === 'ENABLED' || - value.statusUpdates === 'ENABLED_FORCED' || - false + if (!currentType) throw new Error('invalid destination type') - const contactMethods = useMemo( - () => - [ - { - value: 'SMS', - disabledMessage: 'Twilio must be configured by an administrator', - disabled: !smsVoiceEnabled, - }, - { - value: 'VOICE', - disabledMessage: 'Twilio must be configured by an administrator', - disabled: !smsVoiceEnabled, - }, - { - value: 'EMAIL', - disabledMessage: 'SMTP must be configured by an administrator', - disabled: !emailEnabled, - }, - { - value: 'WEBHOOK', - disabledMessage: 'Webhooks must be enabled by an administrator', - disabled: !webhookEnabled, - }, - { - value: 'SLACK_DM', - label: 'SLACK DM', - disabledMessage: 'Slack must be configured by an administrator', - disabled: !slackEnabled, - }, - ].sort(sortDisableableMenuItems), - [smsVoiceEnabled, emailEnabled, webhookEnabled, slackEnabled], - ) + let statusLabel = 'Send alert status updates' + let statusUpdateChecked = value.statusUpdates + if (currentType.statusUpdatesRequired) { + statusLabel = 'Send alert status updates (cannot be disabled for this type)' + statusUpdateChecked = true + } else if (!currentType.supportsStatusUpdates) { + statusLabel = 'Send alert status updates (not supported for this type)' + statusUpdateChecked = false + } return ( { - // if switching between phone types (or same type), keep the value - if ( - (isPhoneType(value) && isPhoneType(newValue)) || - value.type === newValue.type - ) { + if (newValue.dest.type === value.dest.type) { return newValue } + // reset otherwise return { ...newValue, - value: '', + dest: { + ...newValue.dest, + args: {}, + }, } }} optionalLabels > - + + props.onChange && + props.onChange({ ...value, name: e.target.value }) + } + /> - + props.onChange && + props.onChange({ + ...value, + dest: { + type: v.target.value as string, + args: {}, + }, + }) + } + disabled={props.disabled || edit} > - {contactMethods.map(renderMenuItem)} - - - - {renderTypeField(value.type, edit)} + {destinationTypes.map((t) => + renderMenuItem({ + label: t.name, + value: t.type, + disabled: !t.enabled, + disabledMessage: t.enabled ? '' : 'Disabled by administrator.', + }), + )} + - {disclaimer} + + props.onChange && + props.onChange({ + ...value, + dest: { + ...value.dest, + args: v, + }, + }) + } + /> - {edit && ( + + {currentType?.userDisclaimer !== '' && ( - - props.onChange && - props.onChange({ - ...value, - statusUpdates: v.target.checked ? 'ENABLED' : 'DISABLED', - }) - } - /> - } - /> + + {currentType?.userDisclaimer} + )} + + + + props.onChange && + props.onChange({ + ...value, + statusUpdates: v.target.checked, + }) + } + /> + } + /> + ) diff --git a/web/src/app/users/UserContactMethodFormDest.tsx b/web/src/app/users/UserContactMethodFormDest.tsx deleted file mode 100644 index 00c8c8725a..0000000000 --- a/web/src/app/users/UserContactMethodFormDest.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import { Checkbox, FormControlLabel, Typography } from '@mui/material' -import Grid from '@mui/material/Grid' -import TextField from '@mui/material/TextField' -import React from 'react' -import { DestinationInput } from '../../schema' -import { FormContainer, FormField } from '../forms' -import { renderMenuItem } from '../selection/DisableableMenuItem' -import DestinationField from '../selection/DestinationField' -import { useContactMethodTypes } from '../util/RequireConfig' -import { - isInputFieldError, - isDestFieldError, - KnownError, - DestFieldValueError, -} from '../util/errtypes' - -export type Value = { - name: string - dest: DestinationInput - statusUpdates: boolean -} - -export type UserContactMethodFormProps = { - value: Value - - errors?: Array - - disabled?: boolean - edit?: boolean - - disablePortal?: boolean // for testing, disable portal on select menu - - onChange?: (CMValue: Value) => void -} - -export const errorPaths = (prefix = '*'): string[] => [ - `${prefix}.name`, - `${prefix}.dest.type`, - `${prefix}.dest`, -] - -export default function UserContactMethodFormDest( - props: UserContactMethodFormProps, -): JSX.Element { - const { value, edit = false, errors = [], ...other } = props - - const destinationTypes = useContactMethodTypes() - const currentType = destinationTypes.find((d) => d.type === value.dest.type) - - if (!currentType) throw new Error('invalid destination type') - - let statusLabel = 'Send alert status updates' - let statusUpdateChecked = value.statusUpdates - if (currentType.statusUpdatesRequired) { - statusLabel = 'Send alert status updates (cannot be disabled for this type)' - statusUpdateChecked = true - } else if (!currentType.supportsStatusUpdates) { - statusLabel = 'Send alert status updates (not supported for this type)' - statusUpdateChecked = false - } - - return ( - { - let field = e.path[e.path.length - 1].toString() - if (field === 'type') field = 'dest.type' - return { - // need to convert to FormContainer's error format - message: e.message, - field, - } - })} - value={value} - mapOnChangeValue={(newValue: Value): Value => { - if (newValue.dest.type === value.dest.type) { - return newValue - } - - // reset otherwise - return { - ...newValue, - dest: { - ...newValue.dest, - values: [], - }, - } - }} - optionalLabels - > - - - - - - - {destinationTypes.map((t) => - renderMenuItem({ - label: t.name, - value: t.type, - disabled: !t.enabled, - disabledMessage: t.enabled ? '' : 'Disabled by administrator.', - }), - )} - - - - - - - - {currentType?.userDisclaimer} - - - - - - props.onChange && - props.onChange({ - ...value, - statusUpdates: v.target.checked, - }) - } - /> - } - /> - - - - ) -} diff --git a/web/src/app/users/UserContactMethodListDest.stories.tsx b/web/src/app/users/UserContactMethodList.stories.tsx similarity index 87% rename from web/src/app/users/UserContactMethodListDest.stories.tsx rename to web/src/app/users/UserContactMethodList.stories.tsx index 9c1181db04..c1417d91e4 100644 --- a/web/src/app/users/UserContactMethodListDest.stories.tsx +++ b/web/src/app/users/UserContactMethodList.stories.tsx @@ -1,20 +1,19 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' -import UserContactMethodListDest from './UserContactMethodListDest' +import UserContactMethodList from './UserContactMethodList' import { expect, within, userEvent, screen } from '@storybook/test' -import { handleDefaultConfig, handleExpFlags } from '../storybook/graphql' +import { handleDefaultConfig } from '../storybook/graphql' import { HttpResponse, graphql } from 'msw' import { Destination } from '../../schema' const meta = { - title: 'users/UserContactMethodListDest', - component: UserContactMethodListDest, + title: 'users/UserContactMethodList', + component: UserContactMethodList, tags: ['autodocs'], parameters: { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('cmList', ({ variables: vars }) => { return HttpResponse.json({ data: @@ -34,13 +33,14 @@ const meta = { value: '+15555555555', }, ], + args: { 'phone-number': '+15555555555' }, displayInfo: { text: '+1 555-555-5555', iconAltText: 'Voice Call', iconURL: '', linkURL: '', }, - } satisfies Destination, + } satisfies Partial, disabled: false, pending: false, }, @@ -70,13 +70,18 @@ const meta = { value: 'parameter-2', }, ], + args: { + 'first-field': 'test_user@target.com', + 'second-field': 'parameter-1', + 'third-field': 'parameter-2', + }, displayInfo: { text: 'test_user@target.com', iconAltText: 'Email', iconURL: '', linkURL: '', }, - } satisfies Destination, + } satisfies Partial, disabled: false, pending: false, }, @@ -91,13 +96,14 @@ const meta = { value: '+15555555556', }, ], + args: { 'phone-number': '+15555555556' }, displayInfo: { text: '+1 555-555-5556', iconAltText: 'Voice Call', iconURL: '', linkURL: '', }, - } satisfies Destination, + } satisfies Partial, disabled: false, pending: false, }, @@ -110,9 +116,9 @@ const meta = { }, }, render: function Component(args) { - return + return }, -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj diff --git a/web/src/app/users/UserContactMethodList.tsx b/web/src/app/users/UserContactMethodList.tsx index abf21298ab..d0bf54f7d9 100644 --- a/web/src/app/users/UserContactMethodList.tsx +++ b/web/src/app/users/UserContactMethodList.tsx @@ -8,17 +8,16 @@ import { Add } from '@mui/icons-material' import { sortContactMethods } from './util' import OtherActions from '../util/OtherActions' import UserContactMethodDeleteDialog from './UserContactMethodDeleteDialog' -import UserContactMethodEditDialog from './UserContactMethodEditDialog' import { Warning } from '../icons' import UserContactMethodVerificationDialog from './UserContactMethodVerificationDialog' import { useIsWidthDown } from '../util/useWidth' import { GenericError, ObjectNotFound } from '../error-pages' import SendTestDialog from './SendTestDialog' -import AppLink from '../util/AppLink' import { styles as globalStyles } from '../styles/materialStyles' import { UserContactMethod } from '../../schema' +import { useSessionInfo, useContactMethodTypes } from '../util/RequireConfig' +import UserContactMethodEditDialog from './UserContactMethodEditDialog' import UserContactMethodCreateDialog from './UserContactMethodCreateDialog' -import { useSessionInfo } from '../util/RequireConfig' const query = gql` query cmList($id: ID!) { @@ -27,9 +26,21 @@ const query = gql` contactMethods { id name - type - value - formattedValue + dest { + type + args + displayInfo { + ... on DestinationDisplayInfo { + text + iconURL + iconAltText + linkURL + } + ... on DestinationDisplayInfoError { + error + } + } + } disabled pending } @@ -64,6 +75,7 @@ export default function UserContactMethodList( const [showEditDialogByID, setShowEditDialogByID] = useState('') const [showDeleteDialogByID, setShowDeleteDialogByID] = useState('') const [showSendTestByID, setShowSendTestByID] = useState('') + const destinationTypes = useContactMethodTypes() const [{ error, data }] = useQuery({ query, @@ -161,18 +173,16 @@ export default function UserContactMethodList( ) } - function getSubText(cm: UserContactMethod): JSX.Element | string { - let cmText = cm.formattedValue - if (cm.pending) { - cmText = `${cm.formattedValue} - this contact method will be automatically deleted if not verified` + function getSubText(cm: UserContactMethod): string { + let cmText + if ('error' in cm.dest.displayInfo) { + cmText = `ERROR: ${cm.dest.displayInfo.error}` + } else { + cmText = cm.dest.displayInfo.text } - if (cm.type === 'WEBHOOK') { - return ( - - {`${cmText} (`} - docs) - - ) + + if (cm.pending) { + cmText += ` - this contact method will be automatically deleted if not verified` } return cmText @@ -200,12 +210,21 @@ export default function UserContactMethodList( /> ({ - title: `${cm.name} (${cm.type})${cm.disabled ? ' - Disabled' : ''}`, - subText: getSubText(cm), - secondaryAction: getSecondaryAction(cm), - icon: getIcon(cm), - }))} + items={sortContactMethods(contactMethods).map((cm) => { + const destType = destinationTypes.find( + (d) => d.type === cm.dest.type, + ) + + const label = destType?.name || 'Unknown Type' + + return { + id: cm.id, + title: `${cm.name} (${label})${cm.disabled ? ' - Disabled' : ''}`, + subText: getSubText(cm), + secondaryAction: getSecondaryAction(cm), + icon: getIcon(cm), + } + })} emptyMessage='No contact methods' /> diff --git a/web/src/app/users/UserContactMethodListDest.tsx b/web/src/app/users/UserContactMethodListDest.tsx deleted file mode 100644 index e589553c2a..0000000000 --- a/web/src/app/users/UserContactMethodListDest.tsx +++ /dev/null @@ -1,270 +0,0 @@ -import React, { useState, ReactNode, Suspense } from 'react' -import { gql, useQuery } from 'urql' -import FlatList from '../lists/FlatList' -import { Button, Card, CardHeader, Grid, IconButton } from '@mui/material' -import makeStyles from '@mui/styles/makeStyles' -import { Theme } from '@mui/material/styles' -import { Add } from '@mui/icons-material' -import { sortContactMethods } from './util' -import OtherActions from '../util/OtherActions' -import UserContactMethodDeleteDialog from './UserContactMethodDeleteDialog' -import UserContactMethodEditDialog from './UserContactMethodEditDialog' -import { Warning } from '../icons' -import UserContactMethodVerificationDialog from './UserContactMethodVerificationDialog' -import { useIsWidthDown } from '../util/useWidth' -import { GenericError, ObjectNotFound } from '../error-pages' -import SendTestDialog from './SendTestDialog' -import { styles as globalStyles } from '../styles/materialStyles' -import { UserContactMethod } from '../../schema' -import UserContactMethodCreateDialog from './UserContactMethodCreateDialog' -import { useSessionInfo, useContactMethodTypes } from '../util/RequireConfig' - -const query = gql` - query cmList($id: ID!) { - user(id: $id) { - id - contactMethods { - id - name - dest { - type - values { - fieldID - value - } - displayInfo { - ... on DestinationDisplayInfo { - text - iconURL - iconAltText - linkURL - } - ... on DestinationDisplayInfoError { - error - } - } - } - disabled - pending - } - } - } -` - -interface ListItemAction { - label: string - onClick: () => void - disabled?: boolean - tooltip?: string -} - -interface UserContactMethodListProps { - userID: string - readOnly?: boolean -} - -const useStyles = makeStyles((theme: Theme) => ({ - cardHeader: globalStyles(theme).cardHeader, -})) - -export default function UserContactMethodListDest( - props: UserContactMethodListProps, -): ReactNode { - const classes = useStyles() - const mobile = useIsWidthDown('md') - - const [showAddDialog, setShowAddDialog] = useState(false) - const [showVerifyDialogByID, setShowVerifyDialogByID] = useState('') - const [showEditDialogByID, setShowEditDialogByID] = useState('') - const [showDeleteDialogByID, setShowDeleteDialogByID] = useState('') - const [showSendTestByID, setShowSendTestByID] = useState('') - const destinationTypes = useContactMethodTypes() - - const [{ error, data }] = useQuery({ - query, - variables: { - id: props.userID, - }, - }) - - const { userID: currentUserID } = useSessionInfo() - const isCurrentUser = props.userID === currentUserID - - if (!data?.user) return - if (error) return - - const contactMethods = data.user.contactMethods - - const getIcon = (cm: UserContactMethod): JSX.Element | null => { - if (!cm.disabled) return null - if (props.readOnly) { - return - } - - return ( - setShowVerifyDialogByID(cm.id)} - disabled={props.readOnly} - size='large' - > - - - ) - } - - function getActionMenuItems(cm: UserContactMethod): ListItemAction[] { - const actions = [ - { - label: 'Edit', - onClick: () => setShowEditDialogByID(cm.id), - disabled: false, - tooltip: '', - }, - { - label: 'Delete', - onClick: () => setShowDeleteDialogByID(cm.id), - disabled: false, - tooltip: '', - }, - ] - - // disable send test and reactivate if not current user - if (!cm.disabled) { - actions.push({ - label: 'Send Test', - onClick: () => setShowSendTestByID(cm.id), - disabled: !isCurrentUser, - tooltip: !isCurrentUser - ? 'Send Test only available for your own contact methods' - : '', - }) - } else { - actions.push({ - label: 'Reactivate', - onClick: () => setShowVerifyDialogByID(cm.id), - disabled: !isCurrentUser, - tooltip: !isCurrentUser - ? 'Reactivate only available for your own contact methods' - : '', - }) - } - return actions - } - - function getSecondaryAction(cm: UserContactMethod): JSX.Element { - return ( - - {cm.disabled && !props.readOnly && !mobile && isCurrentUser && ( - - - - )} - {!props.readOnly && ( - - - - )} - - ) - } - - function getSubText(cm: UserContactMethod): string { - let cmText - if ('error' in cm.dest.displayInfo) { - cmText = `ERROR: ${cm.dest.displayInfo.error}` - } else { - cmText = cm.dest.displayInfo.text - } - - if (cm.pending) { - cmText += ` - this contact method will be automatically deleted if not verified` - } - - return cmText - } - - return ( - - - setShowAddDialog(true)} - startIcon={} - > - Create Method - - ) : null - } - /> - { - const destType = destinationTypes.find( - (d) => d.type === cm.dest.type, - ) - - const label = destType?.name || 'Unknown Type' - - return { - title: `${cm.name} (${label})${cm.disabled ? ' - Disabled' : ''}`, - subText: getSubText(cm), - secondaryAction: getSecondaryAction(cm), - icon: getIcon(cm), - } - })} - emptyMessage='No contact methods' - /> - - {showAddDialog && ( - { - setShowAddDialog(false) - setShowVerifyDialogByID(contactMethodID) - }} - /> - )} - {showVerifyDialogByID && ( - setShowVerifyDialogByID('')} - /> - )} - {showEditDialogByID && ( - setShowEditDialogByID('')} - /> - )} - {showDeleteDialogByID && ( - setShowDeleteDialogByID('')} - /> - )} - {showSendTestByID && ( - setShowSendTestByID('')} - /> - )} - - - - ) -} diff --git a/web/src/app/users/UserDetails.tsx b/web/src/app/users/UserDetails.tsx index 38ad309a6c..d7730ef812 100644 --- a/web/src/app/users/UserDetails.tsx +++ b/web/src/app/users/UserDetails.tsx @@ -5,25 +5,21 @@ import LockOpenIcon from '@mui/icons-material/LockOpen' import DetailsPage from '../details/DetailsPage' import { UserAvatar } from '../util/avatars' import UserContactMethodList from './UserContactMethodList' -import UserContactMethodListDest from './UserContactMethodListDest' import { AddAlarm, SettingsPhone } from '@mui/icons-material' import SpeedDial from '../util/SpeedDial' import UserNotificationRuleList from './UserNotificationRuleList' -import UserNotificationRuleListDest from './UserNotificationRuleListDest' import { Grid } from '@mui/material' -import UserContactMethodCreateDialog from './UserContactMethodCreateDialog' import UserNotificationRuleCreateDialog from './UserNotificationRuleCreateDialog' import UserContactMethodVerificationDialog from './UserContactMethodVerificationDialog' -import _ from 'lodash' import { GenericError, ObjectNotFound } from '../error-pages' import { useSessionInfo } from '../util/RequireConfig' import UserEditDialog from './UserEditDialog' import UserDeleteDialog from './UserDeleteDialog' import { QuerySetFavoriteButton } from '../util/QuerySetFavoriteButton' -import { EscalationPolicyStep } from '../../schema' +import { User } from '../../schema' import { useIsWidthDown } from '../util/useWidth' import UserShiftsCalendar from './UserShiftsCalendar' -import { useExpFlag } from '../util/useExpFlag' +import UserContactMethodCreateDialog from './UserContactMethodCreateDialog' const userQuery = gql` query userInfo($id: ID!) { @@ -35,15 +31,8 @@ const userQuery = gql` contactMethods { id } - onCallSteps { - id - escalationPolicy { - id - assignedTo { - id - name - } - } + onCallOverview { + serviceCount } } } @@ -59,15 +48,8 @@ const profileQuery = gql` contactMethods { id } - onCallSteps { - id - escalationPolicy { - id - assignedTo { - id - name - } - } + onCallOverview { + serviceCount } sessions { id @@ -76,22 +58,10 @@ const profileQuery = gql` } ` -function serviceCount(onCallSteps: EscalationPolicyStep[] = []): number { - const svcs: { [Key: string]: boolean } = {} - ;(onCallSteps || []).forEach((s) => - (s?.escalationPolicy?.assignedTo || []).forEach( - (svc) => (svcs[svc.id] = true), - ), - ) - - return Object.keys(svcs).length -} - export default function UserDetails(props: { userID: string readOnly: boolean }): JSX.Element { - const hasDestTypesFlag = useExpFlag('dest-types') const userID = props.userID const { userID: currentUserID, isAdmin } = useSessionInfo() @@ -104,16 +74,16 @@ export default function UserDetails(props: { const [showUserDeleteDialog, setShowUserDeleteDialog] = useState(false) const mobile = useIsWidthDown('md') - const [{ data, error }] = useQuery({ + const [{ data, error }] = useQuery<{ user: User }>({ query: isAdmin || userID === currentUserID ? profileQuery : userQuery, variables: { id: userID }, }) + const user = data?.user if (error) return - if (!_.get(data, 'user.id')) return + if (!user) return - const user = _.get(data, 'user') - const svcCount = serviceCount(user.onCallSteps) + const svcCount = user.onCallOverview.serviceCount const sessCount = user?.sessions?.length ?? 0 const disableNR = user.contactMethods.length === 0 @@ -240,28 +210,11 @@ export default function UserDetails(props: { subheader={user.email} pageContent={ - {hasDestTypesFlag ? ( - - ) : ( - - )} - {hasDestTypesFlag ? ( - - ) : ( - - )} + + {!mobile && ( diff --git a/web/src/app/users/UserNotificationRuleCreateDialog.tsx b/web/src/app/users/UserNotificationRuleCreateDialog.tsx index bcc53820c7..f51d0eccb1 100644 --- a/web/src/app/users/UserNotificationRuleCreateDialog.tsx +++ b/web/src/app/users/UserNotificationRuleCreateDialog.tsx @@ -27,13 +27,18 @@ export default function UserNotificationRuleCreateDialog(props: { title='Create New Notification Rule' loading={fetching} errors={nonFieldErrors(error)} + onClose={props.onClose} onSubmit={() => { createNotification( { input: { ...value, userID: props.userID }, }, { - additionalTypenames: ['UserNotificationRule', 'UserContactMethod'], + additionalTypenames: [ + 'UserNotificationRule', + 'UserContactMethod', + 'User', + ], }, ).then((result) => { if (!result.error) props.onClose() diff --git a/web/src/app/users/UserNotificationRuleDeleteDialog.tsx b/web/src/app/users/UserNotificationRuleDeleteDialog.tsx index 5c7be77e41..bee016653f 100644 --- a/web/src/app/users/UserNotificationRuleDeleteDialog.tsx +++ b/web/src/app/users/UserNotificationRuleDeleteDialog.tsx @@ -27,7 +27,11 @@ export default function UserNotificationRuleDeleteDialog(props: { deleteNotification( { id: ruleID }, { - additionalTypenames: ['UserNotificationRule', 'UserContactMethod'], + additionalTypenames: [ + 'UserNotificationRule', + 'UserContactMethod', + 'User', + ], }, ).then((result) => { if (!result.error) props.onClose() diff --git a/web/src/app/users/UserNotificationRuleList.tsx b/web/src/app/users/UserNotificationRuleList.tsx index 9ff8fcad29..9c78206100 100644 --- a/web/src/app/users/UserNotificationRuleList.tsx +++ b/web/src/app/users/UserNotificationRuleList.tsx @@ -31,10 +31,19 @@ const query = gql` delayMinutes contactMethod { id - type name - value - formattedValue + dest { + type + displayInfo { + ... on DestinationDisplayInfo { + text + iconAltText + } + ... on DestinationDisplayInfoError { + error + } + } + } } } } @@ -92,18 +101,29 @@ export default function UserNotificationRuleList(props: { ({ - title: formatNotificationRule(nr.delayMinutes, nr.contactMethod), - secondaryAction: props.readOnly ? null : ( - setDeleteID(nr.id)} - color='secondary' - > - - - ), - }), + (nr) => { + const formattedValue = + nr.contactMethod.dest.displayInfo.text || 'Unknown Label' + const name = nr.contactMethod.name || 'Unknown User' + const type = + nr.contactMethod.dest.displayInfo.iconAltText || 'Unknown Type' + return { + title: formatNotificationRule(nr.delayMinutes, { + type, + name, + formattedValue, + }), + secondaryAction: props.readOnly ? null : ( + setDeleteID(nr.id)} + color='secondary' + > + + + ), + } + }, )} emptyMessage='No notification rules' /> diff --git a/web/src/app/users/UserNotificationRuleListDest.stories.tsx b/web/src/app/users/UserNotificationRuleListDest.stories.tsx index 2026c9cc5d..a20424f0b2 100644 --- a/web/src/app/users/UserNotificationRuleListDest.stories.tsx +++ b/web/src/app/users/UserNotificationRuleListDest.stories.tsx @@ -1,19 +1,18 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' -import UserNotificationRuleListDest from './UserNotificationRuleListDest' +import UserNotificationRuleList from './UserNotificationRuleList' import { expect, within, userEvent, screen } from '@storybook/test' -import { handleDefaultConfig, handleExpFlags } from '../storybook/graphql' +import { handleDefaultConfig } from '../storybook/graphql' import { HttpResponse, graphql } from 'msw' const meta = { - title: 'users/UserNotificationRuleListDest', - component: UserNotificationRuleListDest, + title: 'users/UserNotificationRuleList', + component: UserNotificationRuleList, tags: ['autodocs'], parameters: { msw: { handlers: [ handleDefaultConfig, - handleExpFlags('dest-types'), graphql.query('nrList', ({ variables: vars }) => { return HttpResponse.json({ data: @@ -96,9 +95,9 @@ const meta = { }, }, render: function Component(args) { - return + return }, -} satisfies Meta +} satisfies Meta export default meta type Story = StoryObj diff --git a/web/src/app/users/UserNotificationRuleListDest.tsx b/web/src/app/users/UserNotificationRuleListDest.tsx deleted file mode 100644 index a7314d40d0..0000000000 --- a/web/src/app/users/UserNotificationRuleListDest.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import React, { useState, ReactNode, Suspense } from 'react' -import { gql, useQuery } from 'urql' -import { - Button, - Card, - CardHeader, - Grid, - IconButton, - Theme, -} from '@mui/material' -import makeStyles from '@mui/styles/makeStyles' -import { Add, Delete } from '@mui/icons-material' -import FlatList from '../lists/FlatList' -import { formatNotificationRule, sortNotificationRules } from './util' -import UserNotificationRuleDeleteDialog from './UserNotificationRuleDeleteDialog' -import { styles as globalStyles } from '../styles/materialStyles' -import UserNotificationRuleCreateDialog from './UserNotificationRuleCreateDialog' -import { useIsWidthDown } from '../util/useWidth' -import { ObjectNotFound, GenericError } from '../error-pages' -import { User } from '../../schema' - -const query = gql` - query nrList($id: ID!) { - user(id: $id) { - id - contactMethods { - id - } - notificationRules { - id - delayMinutes - contactMethod { - id - name - dest { - type - displayInfo { - ... on DestinationDisplayInfo { - text - iconAltText - } - ... on DestinationDisplayInfoError { - error - } - } - } - } - } - } - } -` - -const useStyles = makeStyles((theme: Theme) => { - const { cardHeader } = globalStyles(theme) - return { - cardHeader, - } -}) - -export default function UserNotificationRuleListDest(props: { - userID: string - readOnly: boolean -}): ReactNode { - const classes = useStyles() - const mobile = useIsWidthDown('md') - const [showAddDialog, setShowAddDialog] = useState(false) - const [deleteID, setDeleteID] = useState(null) - - const [{ data, error }] = useQuery({ - query, - variables: { id: props.userID }, - }) - - if (data && !data.user) - return - if (error) return - - const { user }: { user: User } = data - - return ( - - - setShowAddDialog(true)} - startIcon={} - disabled={user?.contactMethods.length === 0} - > - Add Rule - - ) : null - } - /> - { - const formattedValue = - nr.contactMethod.dest.displayInfo.text || 'Unknown Label' - const name = nr.contactMethod.name || 'Unknown User' - const type = - nr.contactMethod.dest.displayInfo.iconAltText || 'Unknown Type' - return { - title: formatNotificationRule(nr.delayMinutes, { - type, - name, - formattedValue, - }), - secondaryAction: props.readOnly ? null : ( - setDeleteID(nr.id)} - color='secondary' - > - - - ), - } - }, - )} - emptyMessage='No notification rules' - /> - - - {showAddDialog && ( - setShowAddDialog(false)} - /> - )} - {deleteID && ( - setDeleteID(null)} - /> - )} - - - ) -} diff --git a/web/src/app/users/UserOnCallAssignmentList.tsx b/web/src/app/users/UserOnCallAssignmentList.tsx index 5e51484dbe..aa897ecf44 100644 --- a/web/src/app/users/UserOnCallAssignmentList.tsx +++ b/web/src/app/users/UserOnCallAssignmentList.tsx @@ -4,46 +4,24 @@ import { Card } from '@mui/material' import FlatList from '../lists/FlatList' import { sortBy, values } from 'lodash' import { GenericError, ObjectNotFound } from '../error-pages' +import { OnCallServiceAssignment, User } from '../../schema' const query = gql` query userInfo($id: ID!) { user(id: $id) { id name - onCallSteps { - id - stepNumber - escalationPolicy { - id - name - assignedTo { - id - name - } + onCallOverview { + serviceAssignments { + serviceID + serviceName + escalationPolicyName + stepNumber } } } } ` -interface QueryResult { - user: { - id: string - name: string - onCallSteps: OnCallStep[] - } -} -interface OnCallStep { - id: string - stepNumber: number - escalationPolicy: { - id: string - name: string - assignedTo: { - id: string - name: string - }[] - } -} interface Service { id: string @@ -56,22 +34,20 @@ interface Service { // with policy information mapped in the following structure: // {id: 'svc id', name: 'svc name', policyName: 'policy name', policySteps: [0,1,2]} // -function services(onCallSteps: OnCallStep[] = []): Service[] { +function services(onCallSteps: OnCallServiceAssignment[] = []): Service[] { const svcs: { [index: string]: Service } = {} - ;(onCallSteps || []).forEach((s) => - (s.escalationPolicy.assignedTo || []).forEach((svc) => { - if (!svcs[svc.id]) { - svcs[svc.id] = { - id: svc.id, - name: svc.name, - policyName: s.escalationPolicy.name, - policySteps: [s.stepNumber], - } - } else { - svcs[svc.id].policySteps.push(s.stepNumber) + ;(onCallSteps || []).forEach((s) => { + if (!svcs[s.serviceID]) { + svcs[s.serviceID] = { + id: s.serviceID, + name: s.serviceName, + policyName: s.escalationPolicyName, + policySteps: [s.stepNumber], } - }), - ) + } else { + svcs[s.serviceID].policySteps.push(s.stepNumber) + } + }) let result = values(svcs) result = sortBy(result, 'name') @@ -84,7 +60,7 @@ export default function UserOnCallAssignmentList(props: { currentUser?: boolean }): JSX.Element { const userID = props.userID - const [{ data, error }] = useQuery({ + const [{ data, error }] = useQuery<{ user: User }>({ query, variables: { id: userID }, }) @@ -96,7 +72,7 @@ export default function UserOnCallAssignmentList(props: { return } - const user = (data as QueryResult).user + const user = data.user return ( @@ -111,7 +87,7 @@ export default function UserOnCallAssignmentList(props: { ? 'You are not currently on-call.' : `${user.name} is not currently on-call.` } - items={services(user.onCallSteps).map((svc) => ({ + items={services(user.onCallOverview.serviceAssignments).map((svc) => ({ title: svc.name, url: '/services/' + svc.id, subText: `${svc.policyName}: ${svc.policySteps diff --git a/web/src/app/util/Chips.tsx b/web/src/app/util/Chips.tsx deleted file mode 100644 index c83b9764d2..0000000000 --- a/web/src/app/util/Chips.tsx +++ /dev/null @@ -1,169 +0,0 @@ -import React from 'react' -import Chip, { ChipProps } from '@mui/material/Chip' -import { useLocation } from 'wouter' -import { useQuery, gql } from 'urql' -import { - RotateRight as RotationIcon, - Today as ScheduleIcon, - Webhook as WebhookIcon, -} from '@mui/icons-material' -import Avatar from '@mui/material/Avatar' - -import { UserAvatar, ServiceAvatar } from './avatars' -import { SlackBW } from '../icons' -import { Query } from '../../schema' - -const serviceQuery = gql` - query service($id: ID!) { - service(id: $id) { - id - name - } - } -` - -type WithID = { id: string } & T - -export function ServiceChip(props: WithID): JSX.Element { - const { id, label, ...rest } = props - const [, navigate] = useLocation() - - const [{ data, fetching, error }] = useQuery({ - query: serviceQuery, - variables: { - id, - }, - pause: Boolean(label), - requestPolicy: 'cache-first', - }) - - const getLabel = (): typeof label => { - if (label) return label - if (!data && fetching) return 'Loading...' - if (error) return `Error: ${error.message}` - return data.service.name - } - - return ( - } - onClick={() => navigate(`/services/${id}`)} - label={getLabel()} - {...rest} - /> - ) -} - -export function UserChip(props: WithID): JSX.Element { - const { id, ...rest } = props - const [, navigate] = useLocation() - - return ( - } - onClick={() => navigate(`/users/${id}`)} - {...rest} - /> - ) -} - -export function RotationChip(props: WithID): JSX.Element { - const { id, ...rest } = props - const [, navigate] = useLocation() - - return ( - - - - } - onClick={() => navigate(`/rotations/${id}`)} - {...rest} - /> - ) -} - -export function ScheduleChip(props: WithID): JSX.Element { - const { id, ...rest } = props - const [, navigate] = useLocation() - - return ( - - - - } - onClick={() => navigate(`/schedules/${id}`)} - {...rest} - /> - ) -} - -export function SlackChip(props: WithID): JSX.Element { - const { id: channelID, ...rest } = props - - const query = gql` - query ($id: ID!) { - slackChannel(id: $id) { - id - teamID - } - } - ` - - const [{ data, error }] = useQuery({ - query, - variables: { id: channelID }, - requestPolicy: 'cache-first', - }) - const teamID = data?.slackChannel?.teamID - - if (error) { - console.error(`Error querying slackChannel ${channelID}:`, error) - } - - const clickable = Boolean(channelID && teamID) - if (clickable) { - rest.onClick = () => - window.open( - `https://slack.com/app_redirect?channel=${channelID}&team=${teamID}`, - ) - } - - return ( - - - - } - {...rest} - /> - ) -} - -export function WebhookChip(props: WithID): JSX.Element { - const { id: urlStr, ...rest } = props - - const url = new URL(urlStr) - return ( - - - - } - label={url.hostname} - {...rest} - /> - ) -} diff --git a/web/src/app/util/DestinationAvatar.tsx b/web/src/app/util/DestinationAvatar.tsx index 81e02d4af4..b9728799f6 100644 --- a/web/src/app/util/DestinationAvatar.tsx +++ b/web/src/app/util/DestinationAvatar.tsx @@ -3,12 +3,14 @@ import { Avatar, CircularProgress } from '@mui/material' import { BrokenImage, + Notifications as AlertIcon, RotateRight as RotationIcon, Today as ScheduleIcon, Webhook as WebhookIcon, } from '@mui/icons-material' const builtInIcons: { [key: string]: React.ReactNode } = { + 'builtin://alert': , 'builtin://rotation': , 'builtin://schedule': , 'builtin://webhook': , diff --git a/web/src/app/util/DestinationChip.tsx b/web/src/app/util/DestinationChip.tsx index 15db9b209c..bc61610f78 100644 --- a/web/src/app/util/DestinationChip.tsx +++ b/web/src/app/util/DestinationChip.tsx @@ -6,6 +6,7 @@ import { DestinationAvatar } from './DestinationAvatar' export type DestinationChipProps = InlineDisplayInfo & { // If onDelete is provided, a delete icon will be shown. onDelete?: () => void + onChipClick?: () => void } /** @@ -54,7 +55,7 @@ export default function DestinationChip( } const opts: { [key: string]: unknown } = {} - if (props.linkURL) { + if (props.linkURL && !props.onChipClick) { opts.href = props.linkURL opts.target = '_blank' opts.component = 'a' @@ -64,7 +65,8 @@ export default function DestinationChip( return ( { return HttpResponse.json({ data: { @@ -44,12 +43,9 @@ export const Render: Story = { args: { value: { type: 'builtin-rotation', - values: [ - { - fieldID: 'rotation-id', - value: 'bf227047-18b8-4de3-881c-24b9dd345670', - }, - ], + args: { + 'rotation-id': 'bf227047-18b8-4de3-881c-24b9dd345670', + }, }, }, play: async ({ canvasElement, args }) => { diff --git a/web/src/app/util/DestinationInputChip.tsx b/web/src/app/util/DestinationInputChip.tsx index e4573ccbb4..10f5471bb3 100644 --- a/web/src/app/util/DestinationInputChip.tsx +++ b/web/src/app/util/DestinationInputChip.tsx @@ -6,6 +6,7 @@ import DestinationChip from './DestinationChip' export type DestinationInputChipProps = { value: DestinationInput onDelete?: () => void + onChipClick?: () => void } const query = gql` @@ -51,6 +52,7 @@ export default function DestinationInputChip( linkURL={data?.destinationDisplayInfo.linkURL || ''} text={data?.destinationDisplayInfo.text || ''} onDelete={props.onDelete} + onChipClick={props.onChipClick} /> ) } diff --git a/web/src/app/util/ErrorConsumer.ts b/web/src/app/util/ErrorConsumer.ts new file mode 100644 index 0000000000..3d6e6674f4 --- /dev/null +++ b/web/src/app/util/ErrorConsumer.ts @@ -0,0 +1,210 @@ +import type { CombinedError } from 'urql' + +type ErrorConsumerError = { + path: string + code: string + fieldID: string + message: string +} +type ErrorStore = { + errors: Set +} + +/** ErrorConsumer is a utility class for consuming and handling errors from a CombinedError. */ +export class ErrorConsumer { + constructor(e?: CombinedError | null | undefined) { + if (!e) return + + if (e.networkError) { + this.store.errors.add({ + message: e.networkError.message, + code: '', + path: '', + fieldID: '', + }) + } + + e.graphQLErrors?.forEach((e) => { + const path = e.path?.join('.') || '' + + if (e.extensions.isFieldError) { + this.store.errors.add({ + message: e.message, + code: '_LEGACY_FIELD_ERROR', + fieldID: e.extensions.fieldName?.toString() || '', + path, + }) + return + } + + if (e.extensions.isMultiFieldError) { + type fieldError = { + fieldName: string + message: string + } + const errs = (e.extensions.fieldErrors || []) as Array + errs.forEach((fe: fieldError) => { + this.store.errors.add({ + message: fe.message, + code: '_LEGACY_FIELD_ERROR', + fieldID: fe.fieldName, + path, + }) + }) + return + } + + this.store.errors.add({ + message: e.message, + code: e.extensions?.code?.toString() || '', + path: e.path?.join('.') || '', + fieldID: + e.extensions?.fieldID?.toString() || + e.extensions?.key?.toString() || + '', + }) + }) + + if (!e.graphQLErrors && !e.networkError && e.message) { + this.store.errors.add({ + message: e.message, + code: '', + path: '', + fieldID: '', + }) + } + + this.hadErrors = this.hasErrors() + + // Use FinalizationRegistry if available, this will allow us to raise any errors that are forgotten. + if ( + 'FinalizationRegistry' in window && + typeof window.FinalizationRegistry === 'function' + ) { + // @ts-expect-error FinalizationRegistry is not in the lib + const r = new window.FinalizationRegistry((e: { store: ErrorStore }) => { + if (e.store.errors.size === 0) return + e.store.errors.forEach((e) => console.error(e)) + }) + + r.register(this, { e: this.store }, this) + } + } + + private isDone: boolean = false + private store: ErrorStore = { errors: new Set() } + + /** Whether there were any errors in the original error. */ + public readonly hadErrors: boolean = false + + private doneCheck(): void { + if (!this.isDone) return + + throw new Error( + 'ErrorConsumer is already done, ensure you are not calling this method after calling done() or remaining()', + ) + } + + /** Returns and consumes (if exists) a single error with the given field ID/name. + * + * Name maps to the `fieldName` when using the backend `validate.*` methods. + */ + getErrorByField(field: string | RegExp): string | undefined { + this.doneCheck() + + let result: string | undefined + + this.store.errors.forEach((e) => { + if (result !== undefined) return + if (typeof field === 'string' && e.fieldID !== field) return + if (field instanceof RegExp && !field.test(e.fieldID)) return + + result = e.message + this.store.errors.delete(e) + }) + + return result + } + + /** Returns and consumes (if exists) a single error with the given path. */ + getErrorByPath(path: string | RegExp): string | undefined { + this.doneCheck() + + let result: string | undefined + + // find the first error with the given path + this.store.errors.forEach((e) => { + if (result !== undefined) return + if (typeof path === 'string' && e.path !== path) return + if (path instanceof RegExp && !path.test(e.path)) return + + result = e.message + this.store.errors.delete(e) + }) + + return result + } + + /** Returns and consumes (if exists) all errors at the given path that have a field/key defined. + * + * @param path - Only errors with the given path will be consumed. + */ + getErrorMap(path: string | RegExp): Readonly> { + this.doneCheck() + + const errs: Record = {} + this.store.errors.forEach((e) => { + if (errs[e.fieldID] !== undefined) return + if (e.fieldID === '') return + if (typeof path === 'string' && e.path !== path) return + if (path instanceof RegExp && !path.test(e.path)) return + + errs[e.fieldID] = e.message + this.store.errors.delete(e) + }) + + return errs + } + + /** Returns whether there are any errors remaining. */ + hasErrors(): boolean { + return this.store.errors.size > 0 + } + + /** Returns and consumes all remaining errors. */ + remaining(): Readonly> { + this.doneCheck() + + const errs: string[] = [] + this.store.errors.forEach((e) => { + errs.push(e.message) + this.store.errors.delete(e) + }) + + // mark as done + this.isDone = true + + return errs + } + + /** Returns all remaining errors as an array of objects with a message key. + * + * Suitable for use with FormDialog. + */ + remainingLegacy(): Array<{ message: string }> { + return this.remaining().map((e) => ({ message: e })) + } + + /** Logs and consumes any remaining errors. */ + done(): void { + this.doneCheck() + this.remaining().forEach((e) => console.error(e)) + } +} + +/** useErrorConsumer is a hook for creating an ErrorConsumer. */ +export function useErrorConsumer( + e?: CombinedError | null | undefined, +): ErrorConsumer { + return new ErrorConsumer(e) +} diff --git a/web/src/app/util/OtherActionsDesktop.jsx b/web/src/app/util/OtherActionsDesktop.jsx index 2fdb22654a..3d853f0236 100644 --- a/web/src/app/util/OtherActionsDesktop.jsx +++ b/web/src/app/util/OtherActionsDesktop.jsx @@ -17,7 +17,7 @@ export default function OtherActionsMenuDesktop({ return ( anchorEl} + anchorEl={anchorEl} open={isOpen} onClose={onClose} PaperProps={{ @@ -40,7 +40,6 @@ export default function OtherActionsMenuDesktop({
{ onClose() o.onClick() diff --git a/web/src/app/util/RequireConfig.tsx b/web/src/app/util/RequireConfig.tsx index 526e221496..212314be53 100644 --- a/web/src/app/util/RequireConfig.tsx +++ b/web/src/app/util/RequireConfig.tsx @@ -51,6 +51,7 @@ const query = gql` isContactMethod isEPTarget isSchedOnCallNotify + isDynamicAction requiredFields { fieldID @@ -63,6 +64,13 @@ const query = gql` supportsSearch supportsValidation } + + dynamicParams { + paramID + label + hint + hintURL + } } } ` @@ -195,6 +203,11 @@ export function useEPTargetTypes(): DestinationTypeInfo[] { return cfg.destTypes.filter((t) => t.isEPTarget) } +export function useDynamicActionTypes(): DestinationTypeInfo[] { + const cfg = React.useContext(ConfigContext) + return cfg.destTypes.filter((t) => t.isDynamicAction) +} + /** useSchedOnCallNotifyTypes returns a list of schedule on-call notification destination types. */ export function useSchedOnCallNotifyTypes(): DestinationTypeInfo[] { const cfg = React.useContext(ConfigContext) diff --git a/web/src/app/util/ServiceChip.tsx b/web/src/app/util/ServiceChip.tsx new file mode 100644 index 0000000000..4e3f83a88f --- /dev/null +++ b/web/src/app/util/ServiceChip.tsx @@ -0,0 +1,48 @@ +import React from 'react' +import Chip, { ChipProps } from '@mui/material/Chip' +import { useLocation } from 'wouter' +import { useQuery, gql } from 'urql' + +import { ServiceAvatar } from './avatars' + +const serviceQuery = gql` + query service($id: ID!) { + service(id: $id) { + id + name + } + } +` + +type WithID = { id: string } & T + +export function ServiceChip(props: WithID): JSX.Element { + const { id, label, ...rest } = props + const [, navigate] = useLocation() + + const [{ data, fetching, error }] = useQuery({ + query: serviceQuery, + variables: { + id, + }, + pause: Boolean(label), + requestPolicy: 'cache-first', + }) + + const getLabel = (): typeof label => { + if (label) return label + if (!data && fetching) return 'Loading...' + if (error) return `Error: ${error.message}` + return data.service.name + } + + return ( + } + onClick={() => navigate(`/services/${id}`)} + label={getLabel()} + {...rest} + /> + ) +} diff --git a/web/src/app/util/SpeedDial.tsx b/web/src/app/util/SpeedDial.tsx index 106d301c13..c37b55875f 100644 --- a/web/src/app/util/SpeedDial.tsx +++ b/web/src/app/util/SpeedDial.tsx @@ -83,6 +83,7 @@ export default function CustomSpeedDial( return } action.onClick(e) + setOpen(false) }} /> ))} diff --git a/web/src/app/util/TelTextField.stories.tsx b/web/src/app/util/TelTextField.stories.tsx index 811def6f63..8fe23ad33b 100644 --- a/web/src/app/util/TelTextField.stories.tsx +++ b/web/src/app/util/TelTextField.stories.tsx @@ -1,12 +1,9 @@ import React from 'react' import type { Meta, StoryObj } from '@storybook/react' import TelTextField from './TelTextField' -import { HttpResponse, graphql } from 'msw' import { expect, within } from '@storybook/test' import { useArgs } from '@storybook/preview-api' -import { handleDefaultConfig, handleExpFlags } from '../storybook/graphql' - const meta = { title: 'util/TelTextField', component: TelTextField, @@ -29,21 +26,15 @@ const meta = { }, tags: ['autodocs'], parameters: { - msw: { - handlers: [ - handleDefaultConfig, - handleExpFlags('dest-types'), - graphql.query('PhoneNumberValidate', ({ variables: vars }) => { - return HttpResponse.json({ - data: { - phoneNumberInfo: { - id: vars.number, - valid: vars.number.length === 12, - }, - }, - }) - }), - ], + graphql: { + PhoneNumberValidate: (vars: { number: string }) => ({ + data: { + phoneNumberInfo: { + id: vars.number, + valid: vars.number.length === 12, + }, + }, + }), }, }, } satisfies Meta diff --git a/web/src/app/util/errtypes.ts b/web/src/app/util/errtypes.ts index 44416c77d1..e0b3d086cd 100644 --- a/web/src/app/util/errtypes.ts +++ b/web/src/app/util/errtypes.ts @@ -37,6 +37,8 @@ function isKnownErrorCode(code: ErrorCode): code is ErrorCode { return true case 'EXPR_TOO_COMPLEX': return true + case 'INVALID_MAP_FIELD_VALUE': + return true default: assertNever(code) // ensure we handle all error codes return false diff --git a/web/src/app/wizard/utilTestData.js b/web/src/app/wizard/utilTestData.js index 1725844bab..d49b97734c 100644 --- a/web/src/app/wizard/utilTestData.js +++ b/web/src/app/wizard/utilTestData.js @@ -8,7 +8,7 @@ const keys = [ value: 'generic', }, { - label: 'Grafana Webhook URL', + label: 'Grafana', value: 'grafana', }, { @@ -16,7 +16,7 @@ const keys = [ value: 'site24x7', }, { - label: 'Prometheus Alertmanager Webhook URL', + label: 'Prometheus Alertmanager', value: 'prometheusAlertmanager', }, { diff --git a/web/src/cypress/e2e/escalationPolicies.cy.ts b/web/src/cypress/e2e/escalationPolicies.cy.ts index ffde25d149..c932bbce55 100644 --- a/web/src/cypress/e2e/escalationPolicies.cy.ts +++ b/web/src/cypress/e2e/escalationPolicies.cy.ts @@ -42,7 +42,7 @@ function testEP(screen: ScreenFormat): void { cy.dialogFinish('Cancel') }) - it(`should create an EP when submitted`, () => { + it('should create an EP when submitted', () => { const name = 'SM EP ' + c.word({ length: 8 }) const description = c.word({ length: 10 }) const repeat = c.integer({ min: 0, max: 5 }).toString() @@ -55,9 +55,23 @@ function testEP(screen: ScreenFormat): void { cy.dialogTitle('Create Escalation Policy') cy.dialogForm({ name, description, repeat }) - cy.dialogFinish('Submit') - // should be on details page + // Clear repeat field + cy.dialogForm({ repeat: '' }) + cy.get('[role=dialog] #dialog-form input[name="repeat"]').should( + 'not.have.value', + repeat, + ) + + // Click out of repeat field - last known value is used + cy.get('[role=dialog] #dialog-form').click() + cy.get('[role=dialog] #dialog-form input[name="repeat"]').should( + 'have.value', + repeat, + ) + + // Should be on details page + cy.dialogFinish('Submit') cy.get('body').should('contain', name).should('contain', description) }) }) diff --git a/web/src/cypress/e2e/escalationPolicySteps.cy.ts b/web/src/cypress/e2e/escalationPolicySteps.cy.ts index 03b1207018..47c20f748c 100644 --- a/web/src/cypress/e2e/escalationPolicySteps.cy.ts +++ b/web/src/cypress/e2e/escalationPolicySteps.cy.ts @@ -44,13 +44,44 @@ function testSteps(screen: ScreenFormat): void { cy.get('button').contains('Create Step').click() } cy.dialogTitle('Create Step') - cy.dialogForm({ schedules: [s1.name, s2.name] }) + cy.dialogForm({ 'dest.type': 'Schedule', 'schedule-id': s1.name }) + cy.dialogClick('Add Destination') + cy.get('div[role="dialog"] [data-testid=destination-chip]').should( + 'contain', + s1.name, + ) + cy.dialogForm({ 'schedule-id': s2.name }) + cy.dialogClick('Add Destination') + cy.get('div[role="dialog"] [data-testid=destination-chip]').should( + 'contain', + s2.name, + ) - cy.get('button[data-cy="users-step"]').click() - cy.dialogForm({ users: [u1.name, u2.name] }) + cy.dialogForm({ 'dest.type': 'User', 'user-id': u1.name }) + cy.dialogClick('Add Destination') + cy.get('div[role="dialog"] [data-testid=destination-chip]').should( + 'contain', + u1.name, + ) + cy.dialogForm({ 'user-id': u2.name }) + cy.dialogClick('Add Destination') + cy.get('div[role="dialog"] [data-testid=destination-chip]').should( + 'contain', + u2.name, + ) - cy.get('button[data-cy="rotations-step"]').click() - cy.dialogForm({ rotations: [r1.name, r2.name] }) + cy.dialogForm({ 'dest.type': 'Rotation', 'rotation-id': r1.name }) + cy.dialogClick('Add Destination') + cy.get('div[role="dialog"] [data-testid=destination-chip]').should( + 'contain', + r1.name, + ) + cy.dialogForm({ 'rotation-id': r2.name }) + cy.dialogClick('Add Destination') + cy.get('div[role="dialog"] [data-testid=destination-chip]').should( + 'contain', + r2.name, + ) cy.dialogForm({ delayMinutes: delay.toString() }) cy.dialogFinish('Submit') @@ -58,12 +89,12 @@ function testSteps(screen: ScreenFormat): void { // verify data integrity cy.get('body').should('contain', 'Notify the following:') cy.get('body').should('contain', 'Step #1:') - cy.get('div[data-cy=rotation-chip]').should('contain', r1.name) - cy.get('div[data-cy=rotation-chip]').should('contain', r2.name) - cy.get('div[data-cy=schedule-chip]').should('contain', s1.name) - cy.get('div[data-cy=schedule-chip]').should('contain', s2.name) - cy.get('div[data-cy=user-chip]').should('contain', u1.name) - cy.get('div[data-cy=user-chip]').should('contain', u2.name) + cy.get('[data-testid=destination-chip]').should('contain', r1.name) + cy.get('[data-testid=destination-chip]').should('contain', r2.name) + cy.get('[data-testid=destination-chip]').should('contain', s1.name) + cy.get('[data-testid=destination-chip]').should('contain', s2.name) + cy.get('[data-testid=destination-chip]').should('contain', u1.name) + cy.get('[data-testid=destination-chip]').should('contain', u2.name) cy.get('body').should( 'contain', `Go back to step #1 after ${delay.toString()} minutes`, @@ -82,8 +113,11 @@ function testSteps(screen: ScreenFormat): void { cy.get('button').contains('Create Step').click() } cy.dialogTitle('Create Step') - cy.get('button[data-cy="users-step"]').click() - cy.dialogForm({ users: [u1.name, u2.name] }) + + cy.dialogForm({ 'dest.type': 'User', 'user-id': u1.name }) + cy.dialogClick('Add Destination') + cy.dialogForm({ 'user-id': u2.name }) + cy.dialogClick('Add Destination') }) it('should edit a step', () => { @@ -101,16 +135,22 @@ function testSteps(screen: ScreenFormat): void { cy.dialogTitle('Edit Step') cy.dialogForm({ - schedules: s1.name, + 'dest.type': 'Schedule', + 'schedule-id': s1.name, delayMinutes: delay.toString(), }) + cy.dialogClick('Add Destination') + cy.get('div[role="dialog"] [data-testid=destination-chip]').should( + 'contain', + s1.name, + ) cy.dialogFinish('Submit') // verify data integrity cy.get('body').should('contain', 'Notify the following:') cy.get('body').should('contain', 'Step #1:') - cy.get('div[data-cy=schedule-chip]').should('contain', s1.name) + cy.get('[data-testid=destination-chip]').should('contain', s1.name) cy.get('body').should( 'contain', `Go back to step #1 after ${delay.toString()} minutes`, @@ -129,25 +169,41 @@ function testSteps(screen: ScreenFormat): void { } cy.dialogTitle('Create Step') - // expand slack channels section - cy.get('button[data-cy="slack-channels-step"]').click() - // add slack channels - cy.dialogForm({ slackChannels: ['general', 'foobar'] }) + cy.dialogForm({ + 'dest.type': 'Slack Channel', + 'slack-channel-id': 'general', + }) + cy.dialogClick('Add Destination') + cy.get('div[role="dialog"] [data-testid=destination-chip]').should( + 'contain', + '#general', + ) + + cy.dialogForm({ 'slack-channel-id': 'foobar' }) + cy.dialogClick('Add Destination') + cy.get('div[role="dialog"] [data-testid=destination-chip]').should( + 'contain', + '#foobar', + ) + cy.dialogFinish('Submit') // verify data integrity cy.get('body').should('contain', 'Notify the following:') cy.get('body').should('contain', 'Step #1:') - cy.get('div[data-cy=slack-chip]').should('contain', '#general') - cy.get('div[data-cy=slack-chip]').should('contain', '#foobar') + cy.get('[data-testid=destination-chip]').should('contain', '#general') + cy.get('[data-testid=destination-chip]').should('contain', '#foobar') // verify clickability cy.window().then((win) => { cy.stub(win, 'open').as('slackRedirect') }) - cy.get('div[data-cy=slack-chip][data-clickable=true]').first().click() - cy.get('@slackRedirect').should('be.called') + cy.get('a[data-testid=destination-chip]').should( + 'have.attr', + 'target', + '_blank', + ) // open edit step dialog cy.get('ul[data-cy=steps-list] :nth-child(2) li') @@ -156,19 +212,22 @@ function testSteps(screen: ScreenFormat): void { cy.dialogTitle('Edit Step') - // expand slack channels section - cy.get('button[data-cy="slack-channels-step"]').click() - // delete foobar channel - cy.get('input[name=slackChannels]').multiRemoveByLabel('#foobar') + cy.get('[role=dialog] a[data-testid=destination-chip]') + .contains('a', '#foobar') + .find('[data-testid=CancelIcon]') + .click() + cy.get('div[role="dialog"] [data-testid=destination-chip]') + .contains('#foobar') + .should('not.exist') cy.dialogFinish('Submit') // verify data integrity cy.get('body').should('contain', 'Notify the following:') cy.get('body').should('contain', 'Step #1:') - cy.get('div[data-cy=slack-chip]').should('contain', '#general') - cy.get('div[data-cy=slack-chip]').should('not.contain', '#foobar') + cy.get('[data-testid=destination-chip]').should('contain', '#general') + cy.get('[data-testid=destination-chip]').should('not.contain', '#foobar') }) it('should delete a step', () => { @@ -268,25 +327,33 @@ testScreen('Webhook Support', (screen: ScreenFormat) => { } cy.dialogTitle('Create Step') - // expand webhook section - cy.get('button[data-cy="webhook-step"]').click() - // add webhooks cy.dialogForm({ - webhooks: 'https://webhook.site', + 'dest.type': 'Webhook', + 'webhook-url': 'https://webhook.site', }) - cy.get('button[data-cy="add-webhook"]').click() + cy.dialogClick('Add Destination') + cy.get('div[role="dialog"] [data-testid=destination-chip]').should( + 'contain', + 'webhook.site', + ) + cy.dialogForm({ - webhooks: 'https://example.com', + 'webhook-url': 'https://example.com', }) - cy.get('button[data-cy="add-webhook"]').click() + cy.dialogClick('Add Destination') + cy.get('div[role="dialog"] [data-testid=destination-chip]').should( + 'contain', + 'example.com', + ) + cy.dialogFinish('Submit') // verify data integrity cy.get('body').should('contain', 'Notify the following:') cy.get('body').should('contain', 'Step #1:') - cy.get('div[data-cy=webhook-chip]').should('contain', 'webhook.site') - cy.get('div[data-cy=webhook-chip]').should('contain', 'example.com') + cy.get('[data-testid=destination-chip]').should('contain', 'webhook.site') + cy.get('[data-testid=destination-chip]').should('contain', 'example.com') // open edit step dialog cy.get('ul[data-cy=steps-list] :nth-child(2) li') @@ -295,18 +362,21 @@ testScreen('Webhook Support', (screen: ScreenFormat) => { cy.dialogTitle('Edit Step') - // expand webhook section - cy.get('button[data-cy="webhook-step"]').click() - // delete webhook.site webhook - cy.get('[data-testid=CancelIcon]').first().click() + cy.get('[role=dialog] [data-testid=destination-chip]') + .contains('[data-testid=destination-chip]', 'webhook.site') + .find('[data-testid=CancelIcon]') + .click() cy.dialogFinish('Submit') // verify data integrity cy.get('body').should('contain', 'Notify the following:') cy.get('body').should('contain', 'Step #1:') - cy.get('div[data-cy=webhook-chip]').should('contain', 'example.com') - cy.get('div[data-cy=webhook-chip]').should('not.contain', 'webhook.site') + cy.get('[data-testid=destination-chip]').should('contain', 'example.com') + cy.get('[data-testid=destination-chip]').should( + 'not.contain', + 'webhook.site', + ) }) }) diff --git a/web/src/cypress/e2e/favorites.cy.ts b/web/src/cypress/e2e/favorites.cy.ts index d6f4ad11d3..fe18bf6467 100644 --- a/web/src/cypress/e2e/favorites.cy.ts +++ b/web/src/cypress/e2e/favorites.cy.ts @@ -114,8 +114,9 @@ function testFavorites(screen: ScreenFormat): void { cy.get('button').contains('Create Step').click() } - cy.get('[data-cy="rotations-step"]').click() - return cy.get('input[name=rotations]') + cy.dialogForm({ 'dest.type': 'Rotation' }) + + return cy.get('input[name=rotation-id]') }, ) @@ -135,7 +136,9 @@ function testFavorites(screen: ScreenFormat): void { } else { cy.get('button').contains('Create Step').click() } - return cy.get('input[name=schedules]') + + cy.dialogForm({ 'dest.type': 'Schedule' }) + return cy.get('input[name=schedule-id]') }, ) @@ -166,8 +169,9 @@ function testFavorites(screen: ScreenFormat): void { } else { cy.get('button').contains('Create Step').click() } - cy.get('[data-cy="users-step"]').click() - return cy.get('input[name=users]') + + cy.dialogForm({ 'dest.type': 'User' }) + return cy.get('input[name=user-id]') }, ) } diff --git a/web/src/cypress/e2e/materialSelect.cy.ts b/web/src/cypress/e2e/materialSelect.cy.ts index 32df6e136f..8097cb0d9e 100644 --- a/web/src/cypress/e2e/materialSelect.cy.ts +++ b/web/src/cypress/e2e/materialSelect.cy.ts @@ -1,132 +1,85 @@ -import { Chance } from 'chance' import { testScreen } from '../support/e2e' import users from '../fixtures/users.json' -const c = new Chance() function testMaterialSelect(screen: ScreenFormat): void { - it('should display options with punctuation', () => { - cy.createRotation().then((r) => { - const u = users[3] - cy.visit(`rotations/${r.id}`) - if (screen === 'mobile') { - cy.pageFab() - } else { - cy.get('button').contains('Add User').click() - } - cy.dialogTitle('Add User') - cy.get('input[name=users]').click() - cy.focused().type(u.name.replace('.', ' ')) - cy.get('div[role=presentation]').contains(u.name) + let rot: Rotation + beforeEach(() => { + cy.createRotation().then((r: Rotation) => { + rot = r }) }) - describe('Clear Optional Fields', () => { - describe('Escalation Policy Steps', () => { - let ep: EP - beforeEach(() => { - cy.createEP().then((e: EP) => { - ep = e - return cy.visit(`escalation-policies/${ep.id}`) - }) - }) - - it('should clear fields and not reset with last values', () => { - const u1 = users[0] - const u2 = users[1] - - if (screen === 'mobile') { - cy.pageFab() - } else { - cy.get('button').contains('Create Step').click() - } - cy.dialogTitle('Create Step') - - // populate users - cy.get('button[data-cy="users-step"]').click() - cy.dialogForm({ users: [u1.name, u2.name] }) - - // clear field - cy.dialogForm({ users: '' }) - cy.get(`input[name="users"]`) - .should('not.contain', u1.name) - .should('not.contain', u2.name) - - // unfocus - cy.get(`input[name="users"]`).blur() - cy.get(`input[name="users"]`) - .should('not.contain', u1.name) - .should('not.contain', u2.name) - - cy.dialogFinish('Submit') - }) - }) + it('should display options with punctuation', () => { + const u = users[3] + cy.visit(`rotations/${rot.id}`) + + if (screen === 'mobile') { + cy.pageFab() + } else { + cy.get('button').contains('Add User').click() + } + + cy.dialogTitle('Add User') + cy.get('input[name=users]').click() + cy.focused().type(u.name.replace('.', ' ')) + cy.get('div[role=presentation]').contains(u.name) }) - describe('Clear Required Fields', () => { - describe('Escalation Policy', () => { - it('should clear EP repeat count, reset with default value', () => { - const defaultVal = '3' - cy.visit('escalation-policies') - - if (screen === 'mobile') { - cy.pageFab() - } else { - cy.get('button').contains('Create Escalation Policy').click() - } - - cy.dialogTitle('Create Escalation Policy') - - // Clears field - cy.dialogForm({ repeat: '' }) - cy.get('[role=dialog] #dialog-form input[name="repeat"]') - .should('not.have.value', defaultVal) - .blur() - - // Default value returns - cy.get('[role=dialog] #dialog-form').click() - cy.get('[role=dialog] #dialog-form input[name="repeat"]').should( - 'have.value', - defaultVal, - ) - - cy.dialogFinish('Cancel') - }) - - it('should clear EP repeat count, reset with last value', () => { - const name = 'SM EP ' + c.word({ length: 7 }) - const description = c.word({ length: 9 }) - const repeat = c.integer({ min: 0, max: 5 }).toString() - - cy.visit('escalation-policies') - - if (screen === 'mobile') { - cy.pageFab() - } else { - cy.get('button').contains('Create Escalation Policy').click() - } - - cy.dialogTitle('Create Escalation Policy') - cy.dialogForm({ name, description, repeat }) - - // Clears field - cy.dialogForm({ repeat: '' }) - cy.get('[role=dialog] #dialog-form input[name="repeat"]').should( - 'not.have.value', - repeat, - ) - - // Last value returns - cy.get('[role=dialog] #dialog-form').click() - cy.get('[role=dialog] #dialog-form input[name="repeat"]').should( - 'have.value', - repeat, - ) - - // Should be on details page - cy.dialogFinish('Submit') - cy.get('body').should('contain', name).should('contain', description) - }) - }) + it('should clear optional chips with multiple=true', () => { + const u1 = users[0] + const u2 = users[1] + cy.visit(`rotations/${rot.id}`) + + if (screen === 'mobile') { + cy.pageFab() + } else { + cy.get('button').contains('Add User').click() + } + + cy.dialogTitle('Add User') + + // populate users + cy.dialogForm({ users: [u1.name, u2.name] }) + + // clear field + cy.dialogForm({ users: '' }) + cy.get(`input[name="users"]`) + .should('not.contain', u1.name) + .should('not.contain', u2.name) + + // unfocus + cy.get(`input[name="users"]`).blur() + cy.get(`input[name="users"]`) + .should('not.contain', u1.name) + .should('not.contain', u2.name) + }) + + it('should clear required fields and reset with default value', () => { + const defaultVal = '3' + cy.visit('escalation-policies') + + if (screen === 'mobile') { + cy.pageFab() + } else { + cy.get('button').contains('Create Escalation Policy').click() + } + + cy.dialogTitle('Create Escalation Policy') + + // Clears field + cy.dialogForm({ repeat: '' }) + cy.get('[role=dialog] #dialog-form input[name="repeat"]') + .should('not.have.value', defaultVal) + .blur() + + // Default value returns + cy.get('[role=dialog] #dialog-form').click() + cy.get('[role=dialog] #dialog-form input[name="repeat"]').should( + 'have.value', + defaultVal, + ) + + cy.dialogFinish('Cancel') }) } diff --git a/web/src/cypress/e2e/profile.cy.ts b/web/src/cypress/e2e/profile.cy.ts index 4f50df6e21..2c11a2101b 100644 --- a/web/src/cypress/e2e/profile.cy.ts +++ b/web/src/cypress/e2e/profile.cy.ts @@ -3,43 +3,8 @@ import { testScreen } from '../support/e2e' import profile from '../fixtures/profile.json' const c = new Chance() -function countryCodeCheck( - screen: ScreenFormat, - country: string, - countryCode: string, - value: string, - formattedValue: string, -): void { - it(`should handle ${country} phone number`, () => { - const name = 'CM SM ' + c.word({ length: 8 }) - const type = c.pickone(['SMS', 'VOICE']) - - if (screen === 'mobile') { - cy.pageFab('Create Contact Method') - } else { - cy.get('button[title="Create Contact Method"]').click() - } - - cy.get('input[name=name]').type(name) - cy.get('input[name=type]').selectByLabel(type) - cy.get('input[name=value]').type(countryCode + value) - cy.dialogFinish('Submit') - cy.get('body').should('contain', formattedValue) - }) -} - -function testProfile(screen: ScreenFormat): void { - let cm: ContactMethod - - beforeEach(() => - cy - .resetProfile() - .addNotificationRule() - .then((rule: NotificationRule) => { - cm = rule.contactMethod - return cy.visit('/profile') - }), - ) +function testProfile(): void { + beforeEach(() => cy.resetProfile().visit('/profile')) it('should list and link on-call services', () => { const name = 'SVC ' + c.word({ length: 8 }) @@ -141,316 +106,6 @@ function testProfile(screen: ScreenFormat): void { }) }) }) - - describe('Contact Methods', () => { - function check(name: string, type: string, value: string): void { - if (screen === 'mobile') { - cy.pageFab('Create Contact Method') - } else { - cy.get('button[title="Create Contact Method"]').click() - } - - cy.dialogTitle('Create New Contact Method') - cy.dialogForm({ - name, - type, - value, - }) - cy.dialogFinish('Submit') - - // todo: closing form pending mock server verification - cy.dialogTitle('Verify Contact Method') - cy.dialogFinish('Cancel') - - cy.get('ul[data-cy="contact-methods"]') - .contains('li', `${name} (${type})`) - .find(`button[data-cy='cm-disabled']`) - - cy.get('body').should('contain', `${name} (${type})`) - } - - it('should allow creating sms/voice', () => { - cy.updateConfig({ - Twilio: { - Enable: true, - AccountSID: 'AC' + c.string({ length: 32, pool: '0123456789abcdef' }), - AuthToken: c.string({ length: 32, pool: '0123456789abcdef' }), - FromNumber: '+17633' + c.string({ length: 6, pool: '0123456789' }), - }, - }) - cy.reload() - - const value = '+1763' + c.integer({ min: 3000000, max: 3999999 }) - const name = 'SM CM ' + c.word({ length: 8 }) - const type = c.pickone(['SMS', 'VOICE']) - - check(name, type, value) - }) - - it('should allow creating email', () => { - cy.updateConfig({ - SMTP: { - Enable: true, - }, - }) - cy.reload() - - const name = 'SM CM ' + c.word({ length: 8 }) - const type = c.pickone(['EMAIL']) - const value = c.email() - check(name, type, value) - }) - - it('should allow creating webhook', () => { - cy.updateConfig({ - Webhook: { - Enable: true, - }, - }) - cy.reload() - - const name = 'SM CM ' + c.word({ length: 8 }) - const type = c.pickone(['WEBHOOK']) - const value = c.url() - check(name, type, value) - }) - - it('should return error with link to conflicting user', () => { - cy.addContactMethod({ userID: profile.id }).then( - (contactMethod: ContactMethod) => { - if (screen === 'mobile') { - cy.pageFab('Create Contact Method') - } else { - cy.get('button[title="Create Contact Method"]').click() - } - - cy.dialogTitle('Create New Contact Method') - cy.dialogForm({ - name: c.word({ length: 8 }), - type: contactMethod.type, - value: contactMethod.value, - }) - cy.dialogClick('Submit') - cy.dialog() - .find('a[data-cy=error-help-link]') - .should( - 'contain', - 'Contact method already exists for that type and value: ' + - profile.name, - ) - .should('have.attr', 'href') - .and('include', `/users/${profile.id}`) - }, - ) - }) - - it('should allow editing', () => { - const name = 'SM CM ' + c.word({ length: 8 }) - cy.get('ul[data-cy=contact-methods]') - .contains('li', cm.name) - .find('button[data-cy=other-actions]') - .menu('Edit') - - cy.dialogTitle('Edit Contact Method') - cy.dialogForm({ name }) - cy.dialogFinish('Submit') - - cy.get('ul[data-cy=contact-methods]').should( - 'contain', - `${name} (${cm.type})`, - ) - }) - - it('should allow deleting', () => { - cy.get('ul[data-cy=contact-methods]') - .contains('li', cm.name) - .find('button[data-cy=other-actions]') - .menu('Delete') - cy.dialogTitle('Are you sure?') - cy.dialogFinish('Confirm') - - cy.get('body').should('not.contain', cm.name) - cy.get('body').should('contain', 'No contact methods') - cy.get('body').should('contain', 'No notification rules') - }) - - it('should disable Add Notification Rule if there are no Contact Methods', () => { - cy.get('ul[data-cy=contact-methods]') - .contains('li', cm.name) - .find('button[data-cy=other-actions]') - .menu('Delete') - - cy.dialogTitle('Are you sure?') - cy.dialogFinish('Confirm') - - if (screen === 'mobile') { - cy.get('button[data-cy=page-fab]').should('be.visible').click() - cy.get( - `span[aria-label*=${JSON.stringify( - 'Add Notification Rule', - )}] button[role=menuitem]`, - ).should('be.disabled') - } else { - cy.get('button[title="Add Notification Rule"]').should('be.disabled') - } - }) - - it('should display notification disclaimer when enabled', () => { - const disclaimer = c.sentence() - cy.updateConfig({ - General: { - NotificationDisclaimer: disclaimer, - }, - }) - cy.reload() - - if (screen === 'mobile') { - cy.pageFab('Create Contact Method') - } else { - cy.get('button[title="Create Contact Method"]').click() - } - - cy.dialogTitle('New Contact Method') - cy.dialogContains(disclaimer) - - cy.updateConfig({ - General: { - NotificationDisclaimer: 'new disclaimer', - }, - }) - cy.reload() - - if (screen === 'mobile') { - cy.pageFab('Create Contact Method') - } else { - cy.get('button[title="Create Contact Method"]').click() - } - - cy.dialogTitle('New Contact Method') - cy.dialogContains('new disclaimer') - }) - - countryCodeCheck(screen, 'India', '+91', '1234567890', '+91 1234 567 890') - countryCodeCheck(screen, 'UK', '+44', '7911123456', '+44 7911 123456') - - it('should not allow fake country codes', () => { - const value = '810' + c.integer({ min: 3000000, max: 3999999 }) - const name = 'CM SM ' + c.word({ length: 8 }) - const type = c.pickone(['SMS', 'VOICE']) - - if (screen === 'mobile') { - cy.pageFab('Create Contact Method') - } else { - cy.get('button[title="Create Contact Method"]').click() - } - - cy.dialogTitle('New Contact Method') - cy.dialogForm({ - name, - type, - value, - }) - cy.dialogClick('Submit') - cy.get('[aria-labelledby=countryCodeIndicator]') - .siblings() - .contains('Must be a valid number') - }) - - it('should set and verify contact method on first login', () => { - cy.visit(`/alerts?isFirstLogin=1`) - - const value = '+1763' + c.integer({ min: 3000000, max: 3999999 }) - const name = 'SM CM ' + c.word({ length: 8 }) - - cy.get('body').should('contain', 'Welcome to GoAlert') - - cy.dialogTitle('Welcome to GoAlert') - cy.dialogForm({ - name, - value, - }) - cy.dialogFinish('Submit') - - cy.dialogTitle('Verify') - cy.dialogFinish('Cancel') - }) - }) - - describe('Notification Rules', () => { - it('should allow creating an immediate rule', () => { - // delete existing notification rule - cy.get('ul[data-cy=notification-rules]') - .contains('li', cm.name) - .find('button') - .click() - cy.dialogTitle('Are you sure?') - cy.dialogFinish('Confirm') - - if (screen === 'mobile') { - cy.pageFab('Add Notification Rule') - } else { - cy.get('button[title="Add Notification Rule"]').click() - } - - cy.dialogTitle('New Notification Rule') - cy.dialogForm({ contactMethodID: cm.name }) - cy.dialogFinish('Submit') - - cy.get('ul[data-cy=notification-rules]').should( - 'not.contain', - 'No notification rules', - ) - cy.get('ul[data-cy=notification-rules]').should( - 'contain', - `Immediately notify me via ${cm.type}`, - ) - }) - - it('should allow creating a delayed rule', () => { - // delete default rule - cy.get('ul[data-cy=notification-rules]') - .contains('li', cm.name) - .find('button') - .click() - cy.dialogTitle('Are you sure?') - cy.dialogFinish('Confirm') - - // create new rule - const delay = c.integer({ min: 2, max: 15 }) - - if (screen === 'mobile') { - cy.pageFab('Add Notification Rule') - } else { - cy.get('button[title="Add Notification Rule"]').click() - } - - cy.dialogTitle('New Notification Rule') - cy.dialogForm({ - contactMethodID: cm.name, - delayMinutes: delay.toString(), - }) - cy.dialogFinish('Submit') - - // verify changes - cy.get('body').should('not.contain', 'No notification rules') - cy.get('ul[data-cy=notification-rules]').should( - 'contain', - `After ${delay} minutes notify me via ${cm.type}`, - ) - }) - - it('should allow deleting', () => { - cy.get('ul[data-cy=notification-rules]') - .contains('li', cm.name) - .find('button') - .click() - - cy.dialogTitle('Are you sure?') - cy.dialogFinish('Confirm') - - cy.get('body').should('contain', 'No notification rules') - }) - }) } testScreen('Profile', testProfile) diff --git a/web/src/cypress/e2e/schedules.cy.ts b/web/src/cypress/e2e/schedules.cy.ts index 8ea400c5be..407e1ff816 100644 --- a/web/src/cypress/e2e/schedules.cy.ts +++ b/web/src/cypress/e2e/schedules.cy.ts @@ -1,5 +1,5 @@ import { Chance } from 'chance' -import { testScreen, testScreenWithFlags } from '../support/e2e' +import { testScreen } from '../support/e2e' import { Schedule } from '../../schema' import users from '../fixtures/users.json' @@ -486,7 +486,7 @@ function testSchedules(screen: ScreenFormat): void { cy.dialogTitle('Create Notification Rule') cy.dialogForm({ ruleType: 'on-change', - targetID: 'general', + 'slack-channel-id': 'general', }) cy.dialogFinish('Submit') cy.get('body').should('contain', '#general') @@ -500,7 +500,6 @@ function testSchedules(screen: ScreenFormat): void { } cy.dialogTitle('Create Notification Rule') cy.dialogForm({ - targetID: 'foobar', ruleType: 'time-of-day', time: '00:00', 'weekdayFilter[0]': false, @@ -510,6 +509,7 @@ function testSchedules(screen: ScreenFormat): void { 'weekdayFilter[4]': false, 'weekdayFilter[5]': false, 'weekdayFilter[6]': false, + 'slack-channel-id': 'foobar', }) cy.dialogFinish('Submit') cy.get('#content').should('contain', 'Notifies Mon at 12:00 AM') @@ -598,7 +598,6 @@ function testSchedules(screen: ScreenFormat): void { cy.dialogTitle('Edit Notification Rule') cy.dialogForm({ ruleType: 'time-of-day', - targetID: 'foobar', time: '07:00', 'weekdayFilter[0]': false, 'weekdayFilter[1]': true, @@ -607,6 +606,7 @@ function testSchedules(screen: ScreenFormat): void { 'weekdayFilter[4]': false, 'weekdayFilter[5]': false, 'weekdayFilter[6]': false, + 'slack-channel-id': 'foobar', }) cy.dialogFinish('Submit') cy.get('body').should('contain', 'Notifies Mon at 7:00 AM') @@ -635,13 +635,13 @@ testScreen('Slack User Group Support', (screen: ScreenFormat) => { cy.dialogTitle('Create Notification Rule') cy.dialogForm({ ruleType: 'on-change', - notificationType: 'SLACK USER GROUP', - selectUserGroup: 'foobar', - errorChannel: 'foobar', + 'dest.type': 'Update Slack User Group', + 'slack-usergroup-id': 'foobar', + 'slack-channel-id': 'foobar', }) cy.dialogFinish('Submit') - cy.get('body').should('contain', '#foobar') + cy.get('body').should('contain', '@foobar') cy.get('body').should('contain', 'Notifies when on-call changes') // time of day @@ -652,11 +652,7 @@ testScreen('Slack User Group Support', (screen: ScreenFormat) => { } cy.dialogTitle('Create Notification Rule') cy.dialogForm({ - targetID: 'foobar', ruleType: 'time-of-day', - notificationType: 'SLACK USER GROUP', - selectUserGroup: 'foobar', - errorChannel: 'foobar', time: '00:00', 'weekdayFilter[0]': false, 'weekdayFilter[1]': true, @@ -665,68 +661,62 @@ testScreen('Slack User Group Support', (screen: ScreenFormat) => { 'weekdayFilter[4]': false, 'weekdayFilter[5]': false, 'weekdayFilter[6]': false, + 'dest.type': 'Update Slack User Group', + 'slack-usergroup-id': 'foobar', + 'slack-channel-id': 'foobar', }) cy.dialogFinish('Submit') cy.get('#content').should('contain', 'Notifies Mon at 12:00 AM') }) - }) -}) -testScreenWithFlags( - 'Webhook Support', - (screen: ScreenFormat) => { - describe('Schedule On-Call Notifications', () => { - let sched: Schedule - it('should create notification rules with webhook', () => { - cy.updateConfig({ Webhook: { Enable: true } }) - cy.reload() - cy.createSchedule({ timeZone: 'UTC' }).then((s: Schedule) => { - sched = s - return cy.visit('/schedules/' + sched.id + '/on-call-notifications') - }) + it('should create notification rules with webhook', () => { + cy.updateConfig({ Webhook: { Enable: true } }) + cy.reload() + cy.createSchedule({ timeZone: 'UTC' }).then((s: Schedule) => { + sched = s + return cy.visit('/schedules/' + sched.id + '/on-call-notifications') + }) - // on change - if (screen === 'mobile') { - cy.pageFab() - } else { - cy.get('button').contains('Create Notification Rule').click() - } + // on change + if (screen === 'mobile') { + cy.pageFab() + } else { + cy.get('button').contains('Create Notification Rule').click() + } - cy.dialogTitle('Create Notification Rule') - cy.dialogForm({ - ruleType: 'on-change', - notificationType: 'WEBHOOK', - targetID: 'http://www.example.com', - }) + cy.dialogTitle('Create Notification Rule') + cy.dialogForm({ + ruleType: 'on-change', + 'dest.type': 'Webhook', + 'webhook-url': 'http://www.example.com', + }) - cy.dialogFinish('Submit') - cy.get('body').should('contain', 'http://www.example.com') - cy.get('body').should('contain', 'Notifies when on-call changes') + cy.dialogFinish('Submit') + cy.get('body').should('contain', 'www.example.com') + cy.get('body').should('contain', 'Notifies when on-call changes') - // time of day - if (screen === 'mobile') { - cy.pageFab() - } else { - cy.get('button').contains('Create Notification Rule').click() - } - cy.dialogTitle('Create Notification Rule') - cy.dialogForm({ - ruleType: 'time-of-day', - notificationType: 'WEBHOOK', - targetID: 'http://www.example.com', - time: '00:00', - 'weekdayFilter[0]': false, - 'weekdayFilter[1]': true, - 'weekdayFilter[2]': false, - 'weekdayFilter[3]': false, - 'weekdayFilter[4]': false, - 'weekdayFilter[5]': false, - 'weekdayFilter[6]': false, - }) - cy.dialogFinish('Submit') - cy.get('#content').should('contain', 'Notifies Mon at 12:00 AM') + // time of day + if (screen === 'mobile') { + cy.pageFab() + } else { + cy.get('button').contains('Create Notification Rule').click() + } + cy.dialogTitle('Create Notification Rule') + cy.dialogForm({ + ruleType: 'time-of-day', + 'dest.type': 'Webhook', + 'webhook-url': 'http://www.example.com', + time: '00:00', + 'weekdayFilter[0]': false, + 'weekdayFilter[1]': true, + 'weekdayFilter[2]': false, + 'weekdayFilter[3]': false, + 'weekdayFilter[4]': false, + 'weekdayFilter[5]': false, + 'weekdayFilter[6]': false, }) + cy.dialogFinish('Submit') + cy.get('#content').should('contain', 'Notifies Mon at 12:00 AM') }) - }, - ['chan-webhook'], -) + }) +}) diff --git a/web/src/cypress/e2e/wizard.cy.ts b/web/src/cypress/e2e/wizard.cy.ts index 1d80514283..d91f29c146 100644 --- a/web/src/cypress/e2e/wizard.cy.ts +++ b/web/src/cypress/e2e/wizard.cy.ts @@ -9,7 +9,7 @@ const keys = [ value: 'generic', }, { - label: 'Grafana Webhook URL', + label: 'Grafana', value: 'grafana', }, { @@ -296,6 +296,15 @@ function testWizard(): void { cy.get('body').should('contain', 'cannot be more than 35 characters') cy.get('body').contains('button', 'Close').click() + + // TODO: fix this + // Notes: scrollIntoView is needed to resolve a bug where the search-select input field dropdown button is + // not visible on mobile. This seems to come from an update to themeConfig.tsx (commit a4dbf570f786842fa0eb8db249fa9a7b80a6bd57) + // which makes the multi text field default margin to 'dense'. Somewhere down the line MUI changes the overflow + // property of the button's parent to be hidden resulting in cypress counting it as not visible... + cy.get( + `input[name="secondarySchedule.followTheSunRotation.timeZone"]`, + ).scrollIntoView() cy.get( `input[name="secondarySchedule.followTheSunRotation.timeZone"]`, ).selectByLabel('Asia/Kolkata') @@ -306,6 +315,9 @@ function testWizard(): void { cy.get('body').should('contain', 'cannot be more than 42 characters') cy.get('body').contains('button', 'Close').click() + cy.get( + `input[name="secondarySchedule.followTheSunRotation.timeZone"]`, + ).scrollIntoView() cy.get( `input[name="secondarySchedule.followTheSunRotation.timeZone"]`, ).selectByLabel('America/Chicago') diff --git a/web/src/cypress/support/limits.ts b/web/src/cypress/support/limits.ts index f2bb1463b7..27a224cbb8 100644 --- a/web/src/cypress/support/limits.ts +++ b/web/src/cypress/support/limits.ts @@ -21,7 +21,7 @@ declare global { function getLimits(): Cypress.Chainable { const limits = new Map() - const query = `query getLimits() { + const query = `query getLimits { systemLimits { id description diff --git a/web/src/expflag.d.ts b/web/src/expflag.d.ts index 62176842bf..c8653f268c 100644 --- a/web/src/expflag.d.ts +++ b/web/src/expflag.d.ts @@ -1,3 +1,3 @@ // Code generated by expflag/cmd/tsgen DO NOT EDIT. -type ExpFlag = 'dest-types' | 'example' | 'univ-keys' +type ExpFlag = 'example' | 'univ-keys' diff --git a/web/src/schema.d.ts b/web/src/schema.d.ts index ff029fb9db..a8a3cae0a5 100644 --- a/web/src/schema.d.ts +++ b/web/src/schema.d.ts @@ -2,12 +2,12 @@ export interface Action { dest: Destination - params: DynamicParam[] + params: ExprStringMap } export interface ActionInput { dest: DestinationInput - params: DynamicParamInput[] + params: ExprStringMap } export interface Alert { @@ -394,6 +394,7 @@ export interface DebugSendSMSInput { } export interface Destination { + args: StringMap displayInfo: InlineDisplayInfo type: DestinationType values: FieldValuePair[] @@ -438,17 +439,20 @@ export interface DestinationFieldValidateInput { } export interface DestinationInput { + args?: null | StringMap type: DestinationType - values: FieldValueInput[] + values?: null | FieldValueInput[] } export type DestinationType = string export interface DestinationTypeInfo { + dynamicParams: DynamicParamConfig[] enabled: boolean iconAltText: string iconURL: string isContactMethod: boolean + isDynamicAction: boolean isEPTarget: boolean isSchedOnCallNotify: boolean name: string @@ -459,13 +463,10 @@ export interface DestinationTypeInfo { userDisclaimer: string } -export interface DynamicParam { - expr: ExprStringExpression - paramID: string -} - -export interface DynamicParamInput { - expr: ExprStringExpression +export interface DynamicParamConfig { + hint: string + hintURL: string + label: string paramID: string } @@ -473,6 +474,7 @@ export type ErrorCode = | 'EXPR_TOO_COMPLEX' | 'INVALID_DEST_FIELD_VALUE' | 'INVALID_INPUT_VALUE' + | 'INVALID_MAP_FIELD_VALUE' export interface EscalationPolicy { assignedTo: Target[] @@ -523,6 +525,8 @@ export type ExprOperator = string export type ExprStringExpression = string +export type ExprStringMap = Record + export interface ExprToConditionInput { expr: ExprBooleanExpression } @@ -607,6 +611,7 @@ export interface IntegrationKey { id: string name: string serviceID: string + tokenInfo: TokenInfo type: IntegrationKeyType } @@ -639,13 +644,14 @@ export interface IntegrationKeyTypeInfo { export interface KeyConfig { defaultActions: Action[] + oneRule?: null | KeyRule rules: KeyRule[] - stopAtFirstRule: boolean } export interface KeyRule { actions: Action[] conditionExpr: ExprBooleanExpression + continueAfterMatch: boolean description: string id: string name: string @@ -654,6 +660,7 @@ export interface KeyRule { export interface KeyRuleInput { actions: ActionInput[] conditionExpr: ExprBooleanExpression + continueAfterMatch: boolean description: string id?: null | string name: string @@ -741,9 +748,12 @@ export interface Mutation { deleteAll: boolean deleteAuthSubject: boolean deleteGQLAPIKey: boolean + deleteSecondaryToken: boolean endAllAuthSessionsByCurrentUser: boolean escalateAlerts?: null | Alert[] + generateKeyToken: string linkAccount: boolean + promoteSecondaryToken: boolean sendContactMethodVerification: boolean setAlertNoiseReason: boolean setConfig: boolean @@ -805,6 +815,19 @@ export interface OnCallNotificationRuleInput { weekdayFilter?: null | WeekdayFilter } +export interface OnCallOverview { + serviceAssignments: OnCallServiceAssignment[] + serviceCount: number +} + +export interface OnCallServiceAssignment { + escalationPolicyID: string + escalationPolicyName: string + serviceID: string + serviceName: string + stepNumber: number +} + export interface OnCallShift { end: ISOTimestamp start: ISOTimestamp @@ -830,6 +853,7 @@ export interface PhoneNumberInfo { export interface Query { __schema: __Schema __type?: null | __Type + actionInputValidate: boolean alert?: null | Alert alerts: AlertConnection authSubjectsForProvider: AuthSubjectConnection @@ -1129,6 +1153,8 @@ export interface StringConnection { pageInfo: PageInfo } +export type StringMap = Record + export interface SystemLimit { description: string id: SystemLimitID @@ -1217,6 +1243,11 @@ export interface TimeZoneSearchOptions { search?: null | string } +export interface TokenInfo { + primaryHint: string + secondaryHint: string +} + export interface UpdateAlertsByServiceInput { newStatus: AlertStatus serviceID: string @@ -1264,9 +1295,10 @@ export interface UpdateHeartbeatMonitorInput { export interface UpdateKeyConfigInput { defaultActions?: null | ActionInput[] + deleteRule?: null | string keyID: string rules?: null | KeyRuleInput[] - stopAtFirstRule?: null | boolean + setRule?: null | KeyRuleInput } export interface UpdateRotationInput { @@ -1337,6 +1369,7 @@ export interface User { isFavorite: boolean name: string notificationRules: UserNotificationRule[] + onCallOverview: OnCallOverview onCallSteps: EscalationPolicyStep[] role: UserRole sessions: UserSession[] diff --git a/yarn.lock b/yarn.lock index edf3e25d40..2ccd259347 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1509,7 +1509,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.8, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.23.9 resolution: "@babel/runtime@npm:7.23.9" dependencies: @@ -1621,15 +1621,6 @@ __metadata: languageName: node linkType: hard -"@bundled-es-modules/js-levenshtein@npm:^2.0.1": - version: 2.0.1 - resolution: "@bundled-es-modules/js-levenshtein@npm:2.0.1" - dependencies: - js-levenshtein: ^1.1.6 - checksum: 13d0cbd2b00e563e09a797559dcff8c7e208c1f71e1787535a3d248f7e3d33ef3f0809b9f498d41788ab5fd399882dcca79917d70d97921b7dde94a282c1b7d8 - languageName: node - linkType: hard - "@bundled-es-modules/statuses@npm:^1.0.1": version: 1.0.1 resolution: "@bundled-es-modules/statuses@npm:1.0.1" @@ -1833,12 +1824,12 @@ __metadata: languageName: node linkType: hard -"@emotion/is-prop-valid@npm:^1.2.1": - version: 1.2.1 - resolution: "@emotion/is-prop-valid@npm:1.2.1" +"@emotion/is-prop-valid@npm:^1.2.2": + version: 1.2.2 + resolution: "@emotion/is-prop-valid@npm:1.2.2" dependencies: "@emotion/memoize": ^0.8.1 - checksum: 8f42dc573a3fad79b021479becb639b8fe3b60bdd1081a775d32388bca418ee53074c7602a4c845c5f75fa6831eb1cbdc4d208cc0299f57014ed3a02abcad16a + checksum: 61f6b128ea62b9f76b47955057d5d86fcbe2a6989d2cd1e583daac592901a950475a37d049b9f7a7c6aa8758a33b408735db759fdedfd1f629df0f85ab60ea25 languageName: node linkType: hard @@ -1890,6 +1881,19 @@ __metadata: languageName: node linkType: hard +"@emotion/serialize@npm:^1.1.4": + version: 1.1.4 + resolution: "@emotion/serialize@npm:1.1.4" + dependencies: + "@emotion/hash": ^0.9.1 + "@emotion/memoize": ^0.8.1 + "@emotion/unitless": ^0.8.1 + "@emotion/utils": ^1.2.1 + csstype: ^3.0.2 + checksum: 71b99f816a9c1d61a87c62cf4928da3894bb62213f3aff38b1ea9790b3368f084af98a3e5453b5055c2f36a7d70318d2fa9955b7b5676c2065b868062375df39 + languageName: node + linkType: hard + "@emotion/sheet@npm:^1.2.2": version: 1.2.2 resolution: "@emotion/sheet@npm:1.2.2" @@ -1897,14 +1901,14 @@ __metadata: languageName: node linkType: hard -"@emotion/styled@npm:11.11.0": - version: 11.11.0 - resolution: "@emotion/styled@npm:11.11.0" +"@emotion/styled@npm:11.11.5": + version: 11.11.5 + resolution: "@emotion/styled@npm:11.11.5" dependencies: "@babel/runtime": ^7.18.3 "@emotion/babel-plugin": ^11.11.0 - "@emotion/is-prop-valid": ^1.2.1 - "@emotion/serialize": ^1.1.2 + "@emotion/is-prop-valid": ^1.2.2 + "@emotion/serialize": ^1.1.4 "@emotion/use-insertion-effect-with-fallbacks": ^1.0.1 "@emotion/utils": ^1.2.1 peerDependencies: @@ -1913,7 +1917,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 904f641aad3892c65d7d6c0808b036dae1e6d6dad4861c1c7dc0baa59977047c6cad220691206eba7b4059f1a1c6e6c1ef4ebb8c829089e280fa0f2164a01e6b + checksum: ad5fc42d00e8aa9597f6d9665986036d5ebe0e8f8155af6d95831c5e8fb2319fb837724e6c5cd59e5346f14c3263711b7ce7271d34688e974d1f32ffeecb37ba languageName: node linkType: hard @@ -2652,7 +2656,7 @@ __metadata: languageName: node linkType: hard -"@floating-ui/react-dom@npm:^2.0.0, @floating-ui/react-dom@npm:^2.0.6, @floating-ui/react-dom@npm:^2.0.8": +"@floating-ui/react-dom@npm:^2.0.0, @floating-ui/react-dom@npm:^2.0.8": version: 2.0.8 resolution: "@floating-ui/react-dom@npm:2.0.8" dependencies: @@ -2777,6 +2781,51 @@ __metadata: languageName: node linkType: hard +"@inquirer/confirm@npm:^3.0.0": + version: 3.1.6 + resolution: "@inquirer/confirm@npm:3.1.6" + dependencies: + "@inquirer/core": ^8.1.0 + "@inquirer/type": ^1.3.1 + checksum: 471b9d3dc54575e00595d8f5b48e11948b1c2acddebd29dec00ab4c6809cb63f3409dc4372af076f223be0a64aa01b2f8270b69fc63c27614734efe873387206 + languageName: node + linkType: hard + +"@inquirer/core@npm:^8.1.0": + version: 8.1.0 + resolution: "@inquirer/core@npm:8.1.0" + dependencies: + "@inquirer/figures": ^1.0.1 + "@inquirer/type": ^1.3.1 + "@types/mute-stream": ^0.0.4 + "@types/node": ^20.12.7 + "@types/wrap-ansi": ^3.0.0 + ansi-escapes: ^4.3.2 + chalk: ^4.1.2 + cli-spinners: ^2.9.2 + cli-width: ^4.1.0 + mute-stream: ^1.0.0 + signal-exit: ^4.1.0 + strip-ansi: ^6.0.1 + wrap-ansi: ^6.2.0 + checksum: db959552bd31f4ff6d7e8ce1477041f85eb2e1bf2fc1bf3c94c157c066d334e6e70bb40b9a73944eb650f35b7dd7c6758e2572be43e178264e2983dd3b3ec501 + languageName: node + linkType: hard + +"@inquirer/figures@npm:^1.0.1": + version: 1.0.1 + resolution: "@inquirer/figures@npm:1.0.1" + checksum: e428dac4921c12fa65f1e2f2846f3fdb2c8ea98ef250e8758bc117d67625496bf1f844b67364e69815b6a8d9b2b0857c9864aec5aebb8a92fc3408d16ccdcc39 + languageName: node + linkType: hard + +"@inquirer/type@npm:^1.3.1": + version: 1.3.1 + resolution: "@inquirer/type@npm:1.3.1" + checksum: 171af2cabb1978b87138506b405ffb5a1112f09c04caa5bc32af16aafdb92db0711942f896d2670b27edf680aadc1816e46f42d95c998f5cd0f37bdc86272886 + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -3257,9 +3306,9 @@ __metadata: languageName: node linkType: hard -"@mswjs/interceptors@npm:^0.25.13": - version: 0.25.15 - resolution: "@mswjs/interceptors@npm:0.25.15" +"@mswjs/interceptors@npm:^0.29.0": + version: 0.29.1 + resolution: "@mswjs/interceptors@npm:0.29.1" dependencies: "@open-draft/deferred-promise": ^2.2.0 "@open-draft/logger": ^0.3.0 @@ -3267,29 +3316,7 @@ __metadata: is-node-process: ^1.2.0 outvariant: ^1.2.1 strict-event-emitter: ^0.5.1 - checksum: dbe43f2df398bbe48ee5ea4ecf055144c9c5689218e5955b01378ea084044dab992d1b434d3533e75df044030a976402e53ec65d743c2619e024defd75ffc076 - languageName: node - linkType: hard - -"@mui/base@npm:5.0.0-beta.33": - version: 5.0.0-beta.33 - resolution: "@mui/base@npm:5.0.0-beta.33" - dependencies: - "@babel/runtime": ^7.23.8 - "@floating-ui/react-dom": ^2.0.6 - "@mui/types": ^7.2.13 - "@mui/utils": ^5.15.6 - "@popperjs/core": ^2.11.8 - clsx: ^2.1.0 - prop-types: ^15.8.1 - peerDependencies: - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 5724b2ad6971254944cada34ed06e7bda90c719d01ff5491af71f58e9a1cb6d804dda03bfc16fe5220f817acea18b178ef6b16475e99551ab89348e1e3057bd2 + checksum: c217f922c68024f6a8b526fb7df00bbfccb71e432bfb270322976dd40a9d312698e40bfd105b74df7aeb5a46276531a56ca5b8e3e9b0112f1577eb0d8d289e1f languageName: node linkType: hard @@ -3315,10 +3342,10 @@ __metadata: languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.15.15": - version: 5.15.15 - resolution: "@mui/core-downloads-tracker@npm:5.15.15" - checksum: 3e99a04e03f66d5fa5f0c23cdce0f9fa2331ba08c99a75dc2347ccaa1c6ed520153e04aaeb0d613c9dca099a3e6242558a6284c33d93f95cc65e3243b17860bc +"@mui/core-downloads-tracker@npm:^5.15.19": + version: 5.15.19 + resolution: "@mui/core-downloads-tracker@npm:5.15.19" + checksum: 32dd442d72a4cf4abea0e5c0a325707c3f8aba16b7b40ed674da2c068ed10d686f1941240e527407d685e00ed12931c331d99265e1ed570630c856ffbe291c23 languageName: node linkType: hard @@ -3338,15 +3365,15 @@ __metadata: languageName: node linkType: hard -"@mui/lab@npm:5.0.0-alpha.162": - version: 5.0.0-alpha.162 - resolution: "@mui/lab@npm:5.0.0-alpha.162" +"@mui/lab@npm:5.0.0-alpha.170": + version: 5.0.0-alpha.170 + resolution: "@mui/lab@npm:5.0.0-alpha.170" dependencies: - "@babel/runtime": ^7.23.8 - "@mui/base": 5.0.0-beta.33 - "@mui/system": ^5.15.6 - "@mui/types": ^7.2.13 - "@mui/utils": ^5.15.6 + "@babel/runtime": ^7.23.9 + "@mui/base": 5.0.0-beta.40 + "@mui/system": ^5.15.15 + "@mui/types": ^7.2.14 + "@mui/utils": ^5.15.14 clsx: ^2.1.0 prop-types: ^15.8.1 peerDependencies: @@ -3363,17 +3390,17 @@ __metadata: optional: true "@types/react": optional: true - checksum: eff70cb8916949f46eebcd7554d9e9bc649b73224e511e02afec43fe917b61219027cbea350726915ec5e6c3916da891e8840b5e6308255ff8b8c34c63f2cd5c + checksum: feecaa4691a0efde4d4a7c60fa646c94947bf4124099cfc496829c289515ff77ceaf7dc19bdcbf296eadcfd687a57fade6c4da7df872ed0b0df6df4cada55a92 languageName: node linkType: hard -"@mui/material@npm:5.15.15": - version: 5.15.15 - resolution: "@mui/material@npm:5.15.15" +"@mui/material@npm:5.15.19": + version: 5.15.19 + resolution: "@mui/material@npm:5.15.19" dependencies: "@babel/runtime": ^7.23.9 "@mui/base": 5.0.0-beta.40 - "@mui/core-downloads-tracker": ^5.15.15 + "@mui/core-downloads-tracker": ^5.15.19 "@mui/system": ^5.15.15 "@mui/types": ^7.2.14 "@mui/utils": ^5.15.14 @@ -3396,7 +3423,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: ee0dc22fc4d617f7cf69f2451b6d5139978e6c5319e3056e7719159aff786ee3b80abd07691e230371811d9b5b574aef4559d7855bfe2f8493d596d960a91ab7 + checksum: 001095973c5d8581c97b05bca888d9aae51876684c9bcf7e1841635287c225ac9af94ca13a8baaa410f60b16b1ebb3003efa85a008d7338e23c12272cbf29ecb languageName: node linkType: hard @@ -3417,24 +3444,7 @@ __metadata: languageName: node linkType: hard -"@mui/private-theming@npm:^5.15.6": - version: 5.15.7 - resolution: "@mui/private-theming@npm:5.15.7" - dependencies: - "@babel/runtime": ^7.23.9 - "@mui/utils": ^5.15.7 - prop-types: ^15.8.1 - peerDependencies: - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 09c7f659caa1a784fa6e99e8df6144af6903eb61384d0a5b9217bf71e7480472a5f82a58aabeb62fca41e48754253a653e366201c454ab2c4f202eda2241ad58 - languageName: node - linkType: hard - -"@mui/styled-engine@npm:^5.15.14, @mui/styled-engine@npm:^5.15.6": +"@mui/styled-engine@npm:^5.15.14": version: 5.15.14 resolution: "@mui/styled-engine@npm:5.15.14" dependencies: @@ -3486,35 +3496,7 @@ __metadata: languageName: node linkType: hard -"@mui/system@npm:5.15.6": - version: 5.15.6 - resolution: "@mui/system@npm:5.15.6" - dependencies: - "@babel/runtime": ^7.23.8 - "@mui/private-theming": ^5.15.6 - "@mui/styled-engine": ^5.15.6 - "@mui/types": ^7.2.13 - "@mui/utils": ^5.15.6 - clsx: ^2.1.0 - csstype: ^3.1.2 - prop-types: ^15.8.1 - peerDependencies: - "@emotion/react": ^11.5.0 - "@emotion/styled": ^11.3.0 - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@emotion/react": - optional: true - "@emotion/styled": - optional: true - "@types/react": - optional: true - checksum: c987a75ae3d2cf90895347bebeeff87fecc3c13d2bfde39cddd96cb41a0f4614b3b2c3e489857d75a327c35f5af9de49d6dd15b30c131b53e120c3c58df3b79b - languageName: node - linkType: hard - -"@mui/system@npm:^5.15.15, @mui/system@npm:^5.15.6": +"@mui/system@npm:5.15.15, @mui/system@npm:^5.15.15": version: 5.15.15 resolution: "@mui/system@npm:5.15.15" dependencies: @@ -3542,7 +3524,7 @@ __metadata: languageName: node linkType: hard -"@mui/types@npm:^7.2.13, @mui/types@npm:^7.2.14": +"@mui/types@npm:^7.2.14": version: 7.2.14 resolution: "@mui/types@npm:7.2.14" peerDependencies: @@ -3554,7 +3536,7 @@ __metadata: languageName: node linkType: hard -"@mui/utils@npm:^5.14.16, @mui/utils@npm:^5.15.6, @mui/utils@npm:^5.15.7": +"@mui/utils@npm:^5.14.16": version: 5.15.7 resolution: "@mui/utils@npm:5.15.7" dependencies: @@ -6073,9 +6055,9 @@ __metadata: languageName: node linkType: hard -"@storybook/test-runner@npm:0.17.0": - version: 0.17.0 - resolution: "@storybook/test-runner@npm:0.17.0" +"@storybook/test-runner@npm:0.18.2": + version: 0.18.2 + resolution: "@storybook/test-runner@npm:0.18.2" dependencies: "@babel/core": ^7.22.5 "@babel/generator": ^7.22.5 @@ -6086,7 +6068,7 @@ __metadata: "@storybook/csf": ^0.1.2 "@storybook/csf-tools": ^8.0.0 "@storybook/preview-api": ^8.0.0 - "@swc/core": ^1.3.18 + "@swc/core": 1.5.7 "@swc/jest": ^0.2.23 expect-playwright: ^0.8.0 jest: ^29.6.4 @@ -6097,10 +6079,11 @@ __metadata: jest-runner: ^29.6.4 jest-serializer-html: ^7.1.0 jest-watch-typeahead: ^2.0.0 + nyc: ^15.1.0 playwright: ^1.14.0 bin: test-storybook: dist/test-storybook.js - checksum: 02efe380242b4c60d2e063ac30feb48369aa55d9d4bb5268fb3fcade84bb2e462713bc4829b538ee2e6bf7ffe499f341b9333a729e42de202085a5e8537d304b + checksum: 962b4c7cf04a0693abdcc43eb760bb6a4d4d730fcb40b27a4ef6d6420393727c8483f36cee6219cbfcef1566bd2d0c928744049129af9f307539f7cb8b8ab61c languageName: node linkType: hard @@ -6234,92 +6217,92 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.107": - version: 1.3.107 - resolution: "@swc/core-darwin-arm64@npm:1.3.107" +"@swc/core-darwin-arm64@npm:1.5.7": + version: 1.5.7 + resolution: "@swc/core-darwin-arm64@npm:1.5.7" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.107": - version: 1.3.107 - resolution: "@swc/core-darwin-x64@npm:1.3.107" +"@swc/core-darwin-x64@npm:1.5.7": + version: 1.5.7 + resolution: "@swc/core-darwin-x64@npm:1.5.7" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.107": - version: 1.3.107 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.107" +"@swc/core-linux-arm-gnueabihf@npm:1.5.7": + version: 1.5.7 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.5.7" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.107": - version: 1.3.107 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.107" +"@swc/core-linux-arm64-gnu@npm:1.5.7": + version: 1.5.7 + resolution: "@swc/core-linux-arm64-gnu@npm:1.5.7" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.107": - version: 1.3.107 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.107" +"@swc/core-linux-arm64-musl@npm:1.5.7": + version: 1.5.7 + resolution: "@swc/core-linux-arm64-musl@npm:1.5.7" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.107": - version: 1.3.107 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.107" +"@swc/core-linux-x64-gnu@npm:1.5.7": + version: 1.5.7 + resolution: "@swc/core-linux-x64-gnu@npm:1.5.7" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.107": - version: 1.3.107 - resolution: "@swc/core-linux-x64-musl@npm:1.3.107" +"@swc/core-linux-x64-musl@npm:1.5.7": + version: 1.5.7 + resolution: "@swc/core-linux-x64-musl@npm:1.5.7" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.107": - version: 1.3.107 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.107" +"@swc/core-win32-arm64-msvc@npm:1.5.7": + version: 1.5.7 + resolution: "@swc/core-win32-arm64-msvc@npm:1.5.7" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.107": - version: 1.3.107 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.107" +"@swc/core-win32-ia32-msvc@npm:1.5.7": + version: 1.5.7 + resolution: "@swc/core-win32-ia32-msvc@npm:1.5.7" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.107": - version: 1.3.107 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.107" +"@swc/core-win32-x64-msvc@npm:1.5.7": + version: 1.5.7 + resolution: "@swc/core-win32-x64-msvc@npm:1.5.7" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@swc/core@npm:^1.3.18": - version: 1.3.107 - resolution: "@swc/core@npm:1.3.107" +"@swc/core@npm:1.5.7": + version: 1.5.7 + resolution: "@swc/core@npm:1.5.7" dependencies: - "@swc/core-darwin-arm64": 1.3.107 - "@swc/core-darwin-x64": 1.3.107 - "@swc/core-linux-arm-gnueabihf": 1.3.107 - "@swc/core-linux-arm64-gnu": 1.3.107 - "@swc/core-linux-arm64-musl": 1.3.107 - "@swc/core-linux-x64-gnu": 1.3.107 - "@swc/core-linux-x64-musl": 1.3.107 - "@swc/core-win32-arm64-msvc": 1.3.107 - "@swc/core-win32-ia32-msvc": 1.3.107 - "@swc/core-win32-x64-msvc": 1.3.107 - "@swc/counter": ^0.1.1 - "@swc/types": ^0.1.5 + "@swc/core-darwin-arm64": 1.5.7 + "@swc/core-darwin-x64": 1.5.7 + "@swc/core-linux-arm-gnueabihf": 1.5.7 + "@swc/core-linux-arm64-gnu": 1.5.7 + "@swc/core-linux-arm64-musl": 1.5.7 + "@swc/core-linux-x64-gnu": 1.5.7 + "@swc/core-linux-x64-musl": 1.5.7 + "@swc/core-win32-arm64-msvc": 1.5.7 + "@swc/core-win32-ia32-msvc": 1.5.7 + "@swc/core-win32-x64-msvc": 1.5.7 + "@swc/counter": ^0.1.2 + "@swc/types": 0.1.7 peerDependencies: "@swc/helpers": ^0.5.0 dependenciesMeta: @@ -6346,14 +6329,14 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 0dccff50461fb8c0f4af053b70e555c91386cb07aa7657a7328d58e397d15640723587549416d8fa7dcc073ad11b39318146bd50ec4a82345ce2ce39c7ba4c00 + checksum: 8e11626b782df914ee53dcb3e7f52e4bd2e1a896873c0e76ec674d19d05d87eec06e2223e0958d68ef1e0cdfb4cd505e3b1a297561e9506063738337f0c5409d languageName: node linkType: hard -"@swc/counter@npm:^0.1.1": - version: 0.1.2 - resolution: "@swc/counter@npm:0.1.2" - checksum: 8427c594f1f0cf44b83885e9c8fe1e370c9db44ae96e07a37c117a6260ee97797d0709483efbcc244e77bac578690215f45b23254c4cd8a70fb25ddbb50bf33e +"@swc/counter@npm:^0.1.2, @swc/counter@npm:^0.1.3": + version: 0.1.3 + resolution: "@swc/counter@npm:0.1.3" + checksum: df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 languageName: node linkType: hard @@ -6369,10 +6352,12 @@ __metadata: languageName: node linkType: hard -"@swc/types@npm:^0.1.5": - version: 0.1.5 - resolution: "@swc/types@npm:0.1.5" - checksum: 6aee11f62d3d805a64848e0bd5f0e0e615f958e327a9e1260056c368d7d28764d89e38bd8005a536c9bf18afbcd303edd84099d60df34a2975d62540f61df13b +"@swc/types@npm:0.1.7": + version: 0.1.7 + resolution: "@swc/types@npm:0.1.7" + dependencies: + "@swc/counter": ^0.1.3 + checksum: e251f6994de12a2a81ed79d902a521398feda346022e09567c758eee1cca606743c9bb296de74d6fbe339f953eaf69176202babc8ef9c911d5d538fc0790df28 languageName: node linkType: hard @@ -6545,10 +6530,10 @@ __metadata: languageName: node linkType: hard -"@types/cookie@npm:^0.4.1": - version: 0.4.1 - resolution: "@types/cookie@npm:0.4.1" - checksum: 3275534ed69a76c68eb1a77d547d75f99fedc80befb75a3d1d03662fb08d697e6f8b1274e12af1a74c6896071b11510631ba891f64d30c78528d0ec45a9c1a18 +"@types/cookie@npm:^0.6.0": + version: 0.6.0 + resolution: "@types/cookie@npm:0.6.0" + checksum: 5edce7995775b0b196b142883e4d4f71fd93c294eaec973670f1fa2540b70ea7390408ed513ddefef5fcb12a578100c76596e8f2a714b0c2ae9f70ee773f4510 languageName: node linkType: hard @@ -6653,10 +6638,10 @@ __metadata: languageName: node linkType: hard -"@types/diff@npm:5.0.8": - version: 5.0.8 - resolution: "@types/diff@npm:5.0.8" - checksum: 729c74c408905cb88ae7a8245e8c1d03359f2c01168beee4d90304af1cdf99462e4a1f2c49b3a64e27623baae3ea7a5a8f883b1db5a3ec075770700a14ad0904 +"@types/diff@npm:5.2.1": + version: 5.2.1 + resolution: "@types/diff@npm:5.2.1" + checksum: 5983a323177bd691cb2194f5d55b960cd20a9c8fec653b4b038760c5809627cc9ea3578fdf10119ccbefefef193ea925f2817136eb97b17388f66b16c8480a8a languageName: node linkType: hard @@ -6839,14 +6824,7 @@ __metadata: languageName: node linkType: hard -"@types/js-levenshtein@npm:^1.1.1": - version: 1.1.3 - resolution: "@types/js-levenshtein@npm:1.1.3" - checksum: eb338696da976925ea8448a42d775d7615a14323dceeb08909f187d0b3d3b4c1f67a1c36ef586b1c2318b70ab141bba8fc58311ba1c816711704605aec09db8b - languageName: node - linkType: hard - -"@types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.9": +"@types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98 @@ -6932,6 +6910,15 @@ __metadata: languageName: node linkType: hard +"@types/mute-stream@npm:^0.0.4": + version: 0.0.4 + resolution: "@types/mute-stream@npm:0.0.4" + dependencies: + "@types/node": "*" + checksum: af8d83ad7b68ea05d9357985daf81b6c9b73af4feacb2f5c2693c7fd3e13e5135ef1bd083ce8d5bdc8e97acd28563b61bb32dec4e4508a8067fcd31b8a098632 + languageName: node + linkType: hard + "@types/node-fetch@npm:^2.6.4": version: 2.6.11 resolution: "@types/node-fetch@npm:2.6.11" @@ -6969,6 +6956,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^20.12.7": + version: 20.12.11 + resolution: "@types/node@npm:20.12.11" + dependencies: + undici-types: ~5.26.4 + checksum: 0cc06bb69cd8150e96fcf65fa3d7f2eeebedf110a99e1834a7fa55bd6c04e7b6d73f74321a2acfc569ca300c0b88d8e1b702ce245b3802f6e5f6a8987fef451a + languageName: node + linkType: hard + "@types/normalize-package-data@npm:^2.4.0": version: 2.4.4 resolution: "@types/normalize-package-data@npm:2.4.4" @@ -7011,14 +7007,14 @@ __metadata: languageName: node linkType: hard -"@types/react-big-calendar@npm:1.6.5": - version: 1.6.5 - resolution: "@types/react-big-calendar@npm:1.6.5" +"@types/react-big-calendar@npm:1.8.9": + version: 1.8.9 + resolution: "@types/react-big-calendar@npm:1.8.9" dependencies: "@types/date-arithmetic": "*" "@types/prop-types": "*" "@types/react": "*" - checksum: 32347444abe56f9035d6a12cb684a3acfe07fc45e0111c6adf2218354fb62b9384965adaca36405072c2b02ea5fd8262d40c1c3f823364f0571a1ee27a80cb24 + checksum: 18294e2e0e96997cedd433270695e7023df13eadc3c031381bccff0ba1ca58036bdfb01565264c062091486595d8a2a19d6d3e32dd3c9ba425500082e8a1d66d languageName: node linkType: hard @@ -7103,13 +7099,6 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:^7.5.8": - version: 7.5.8 - resolution: "@types/semver@npm:7.5.8" - checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663 - languageName: node - linkType: hard - "@types/send@npm:*": version: 0.17.4 resolution: "@types/send@npm:0.17.4" @@ -7152,10 +7141,10 @@ __metadata: languageName: node linkType: hard -"@types/statuses@npm:^2.0.1": - version: 2.0.4 - resolution: "@types/statuses@npm:2.0.4" - checksum: 3a806c3b96d1845e3e7441fbf0839037e95f717334760ddb7c29223c9a34a7206b68e2998631f89f1a1e3ef5b67b15652f6e8fa14987ebd7f6d38587c1bffd18 +"@types/statuses@npm:^2.0.4": + version: 2.0.5 + resolution: "@types/statuses@npm:2.0.5" + checksum: 3f2609f660b45a878c6782f2fb2cef9f08bbd4e89194bf7512e747b8a73b056839be1ad6f64b1353765528cd8a5e93adeffc471cde24d0d9f7b528264e7154e5 languageName: node linkType: hard @@ -7212,6 +7201,13 @@ __metadata: languageName: node linkType: hard +"@types/wrap-ansi@npm:^3.0.0": + version: 3.0.0 + resolution: "@types/wrap-ansi@npm:3.0.0" + checksum: 492f0610093b5802f45ca292777679bb9b381f1f32ae939956dd9e00bf81dba7cc99979687620a2817d9a7d8b59928207698166c47a0861c6a2e5c30d4aaf1e9 + languageName: node + linkType: hard + "@types/yargs-parser@npm:*": version: 21.0.3 resolution: "@types/yargs-parser@npm:21.0.3" @@ -7255,20 +7251,18 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:7.7.0": - version: 7.7.0 - resolution: "@typescript-eslint/eslint-plugin@npm:7.7.0" +"@typescript-eslint/eslint-plugin@npm:7.11.0": + version: 7.11.0 + resolution: "@typescript-eslint/eslint-plugin@npm:7.11.0" dependencies: "@eslint-community/regexpp": ^4.10.0 - "@typescript-eslint/scope-manager": 7.7.0 - "@typescript-eslint/type-utils": 7.7.0 - "@typescript-eslint/utils": 7.7.0 - "@typescript-eslint/visitor-keys": 7.7.0 - debug: ^4.3.4 + "@typescript-eslint/scope-manager": 7.11.0 + "@typescript-eslint/type-utils": 7.11.0 + "@typescript-eslint/utils": 7.11.0 + "@typescript-eslint/visitor-keys": 7.11.0 graphemer: ^1.4.0 ignore: ^5.3.1 natural-compare: ^1.4.0 - semver: ^7.6.0 ts-api-utils: ^1.3.0 peerDependencies: "@typescript-eslint/parser": ^7.0.0 @@ -7276,7 +7270,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: f97348425d114282407f4f524cdc618199d0d6d86e4e556709063b07611192068872cbd7f612cbd670617d958ee4519b25eeca0bccbac1b08433ce41511d3825 + checksum: 47c9ff5e02c3ce230eadb2e704ecfff83cc8dd76f0d0da5a077534b2c01eae360ad5fd8ffbff7ddd3e65d156d00b7c64426c4ac1fb2f6c12f7e5f228a6c65ad8 languageName: node linkType: hard @@ -7318,22 +7312,22 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:7.7.0": - version: 7.7.0 - resolution: "@typescript-eslint/scope-manager@npm:7.7.0" +"@typescript-eslint/scope-manager@npm:7.11.0": + version: 7.11.0 + resolution: "@typescript-eslint/scope-manager@npm:7.11.0" dependencies: - "@typescript-eslint/types": 7.7.0 - "@typescript-eslint/visitor-keys": 7.7.0 - checksum: cb280d4aa64cdefee362ef97b6fde3ae86a376fccff7f012e4e635ffe544dd90be37b340c7099784d0fbebb37b925aab6b53195825b41cee38e2382d0b552871 + "@typescript-eslint/types": 7.11.0 + "@typescript-eslint/visitor-keys": 7.11.0 + checksum: c3fbf6c091b418a79cc3eb671184b83eaa26c06766aa78b4f32234d366f1130271317525b0b3bc38670195e4c608df049ae400cc343f6afa6104b2eec1bbb577 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:7.7.0": - version: 7.7.0 - resolution: "@typescript-eslint/type-utils@npm:7.7.0" +"@typescript-eslint/type-utils@npm:7.11.0": + version: 7.11.0 + resolution: "@typescript-eslint/type-utils@npm:7.11.0" dependencies: - "@typescript-eslint/typescript-estree": 7.7.0 - "@typescript-eslint/utils": 7.7.0 + "@typescript-eslint/typescript-estree": 7.11.0 + "@typescript-eslint/utils": 7.11.0 debug: ^4.3.4 ts-api-utils: ^1.3.0 peerDependencies: @@ -7341,7 +7335,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 74c07e4fcc8e6ee7870a161596d25ecfa22624947d94ca9af7147590caa13b6388f0e55101961ab02f77e7e6cffdaf19895575d7329dda50fa18fc71bf15f6b7 + checksum: c4d085a7cc792b971696527d7c55ed0b9d45277fef9cdb100685a839b69a7b6deeae2119b6010b01c14f4f72b49545310f006af6da02e5005e9a11447398847a languageName: node linkType: hard @@ -7359,10 +7353,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:7.7.0": - version: 7.7.0 - resolution: "@typescript-eslint/types@npm:7.7.0" - checksum: c47aae2c1474b85fab012e0518c57685c595f11775b615b6a6749f943aa7a98554d9eb7054114850679f46699578049998408a492e0c1abd3bded2aee8e261a5 +"@typescript-eslint/types@npm:7.11.0": + version: 7.11.0 + resolution: "@typescript-eslint/types@npm:7.11.0" + checksum: 1c2cf1540f08240e12da522fe3b23054adaffc7c5a82eb0fc94b982454ba527358f00c018fba06826ad42708fcb73237f823891d4d3bf18faa5cabee37cd76d4 languageName: node linkType: hard @@ -7403,12 +7397,12 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:7.7.0": - version: 7.7.0 - resolution: "@typescript-eslint/typescript-estree@npm:7.7.0" +"@typescript-eslint/typescript-estree@npm:7.11.0": + version: 7.11.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.11.0" dependencies: - "@typescript-eslint/types": 7.7.0 - "@typescript-eslint/visitor-keys": 7.7.0 + "@typescript-eslint/types": 7.11.0 + "@typescript-eslint/visitor-keys": 7.11.0 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -7418,24 +7412,21 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 54d16b2a083bff3c6d38fbee56465403bbcba411bf25e94f2d8bbbbd8b4b35c151c7845997e5141224f8dba5bc1f34964762713035d49113700efd7381246d02 + checksum: 026e857152874764c18a4f3a7b443f4fc757cf3e1d106f85df9d283205f6b2192ec3d771d71dddd77d1f15df61fb99e3a65e661c5fe39793462050d425463f33 languageName: node linkType: hard -"@typescript-eslint/utils@npm:7.7.0": - version: 7.7.0 - resolution: "@typescript-eslint/utils@npm:7.7.0" +"@typescript-eslint/utils@npm:7.11.0": + version: 7.11.0 + resolution: "@typescript-eslint/utils@npm:7.11.0" dependencies: "@eslint-community/eslint-utils": ^4.4.0 - "@types/json-schema": ^7.0.15 - "@types/semver": ^7.5.8 - "@typescript-eslint/scope-manager": 7.7.0 - "@typescript-eslint/types": 7.7.0 - "@typescript-eslint/typescript-estree": 7.7.0 - semver: ^7.6.0 + "@typescript-eslint/scope-manager": 7.11.0 + "@typescript-eslint/types": 7.11.0 + "@typescript-eslint/typescript-estree": 7.11.0 peerDependencies: eslint: ^8.56.0 - checksum: 830ff3af96538083d7513c211e39f07375b7e973c135a2b9bbae1ad7509bd4dce33a144a22d896a2ff4c18e9fcccd423535b6f9bb8adafe36e800f16bc53378c + checksum: 287d0798dcfd5c56c73dc2a417c3442edb19deb6f274e2406e52b4ac9088494ed4c94b4b8ae8adff7ae2b7a1c520e9643e415018348bf1ec1b17605e7e565488 languageName: node linkType: hard @@ -7477,13 +7468,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:7.7.0": - version: 7.7.0 - resolution: "@typescript-eslint/visitor-keys@npm:7.7.0" +"@typescript-eslint/visitor-keys@npm:7.11.0": + version: 7.11.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.11.0" dependencies: - "@typescript-eslint/types": 7.7.0 + "@typescript-eslint/types": 7.11.0 eslint-visitor-keys: ^3.4.3 - checksum: 16d0b63b9d98ea1d3d20bd6f9dc3cbd2674055845ad493d98118669d54792b1c167f57ae25beaae2c1107ed07012ac3c3093cca978b2ab49833dc491bc302b33 + checksum: 5f1170c1e3110c53b5433949f98079d8bbc8a4334dfef96c802a6df6d475e187796180f844edcff0928a5c2ae5da4babcb5f50c658f61c6fb940efda7457a433 languageName: node linkType: hard @@ -7758,7 +7749,7 @@ __metadata: languageName: node linkType: hard -"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.0": +"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.0, ansi-escapes@npm:^4.3.2": version: 4.3.2 resolution: "ansi-escapes@npm:4.3.2" dependencies: @@ -8900,7 +8891,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:^4.1.1, chalk@npm:^4.1.2": +"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -8966,13 +8957,6 @@ __metadata: languageName: node linkType: hard -"chardet@npm:^0.7.0": - version: 0.7.0 - resolution: "chardet@npm:0.7.0" - checksum: 6fd5da1f5d18ff5712c1e0aed41da200d7c51c28f11b36ee3c7b483f3696dabc08927fc6b227735eb8f0e1215c9a8abd8154637f3eff8cada5959df7f58b024d - languageName: node - linkType: hard - "check-error@npm:^1.0.3": version: 1.0.3 resolution: "check-error@npm:1.0.3" @@ -8989,7 +8973,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.4.2, chokidar@npm:^3.5.3": +"chokidar@npm:^3.5.3": version: 3.5.3 resolution: "chokidar@npm:3.5.3" dependencies: @@ -9064,14 +9048,7 @@ __metadata: languageName: node linkType: hard -"classnames@npm:2.3.2": - version: 2.3.2 - resolution: "classnames@npm:2.3.2" - checksum: 2c62199789618d95545c872787137262e741f9db13328e216b093eea91c85ef2bfb152c1f9e63027204e2559a006a92eb74147d46c800a9f96297ae1d9f96f4e - languageName: node - linkType: hard - -"classnames@npm:^2.2.5": +"classnames@npm:2.5.1, classnames@npm:^2.2.5": version: 2.5.1 resolution: "classnames@npm:2.5.1" checksum: da424a8a6f3a96a2e87d01a432ba19315503294ac7e025f9fece656db6b6a0f7b5003bb1fbb51cbb0d9624d964f1b9bb35a51c73af9b2434c7b292c42231c1e5 @@ -9094,7 +9071,7 @@ __metadata: languageName: node linkType: hard -"cli-spinners@npm:^2.5.0": +"cli-spinners@npm:^2.5.0, cli-spinners@npm:^2.9.2": version: 2.9.2 resolution: "cli-spinners@npm:2.9.2" checksum: 1bd588289b28432e4676cb5d40505cfe3e53f2e4e10fbe05c8a710a154d6fe0ce7836844b00d6858f740f2ffe67cdc36e0fce9c7b6a8430e80e6388d5aa4956c @@ -9124,10 +9101,10 @@ __metadata: languageName: node linkType: hard -"cli-width@npm:^3.0.0": - version: 3.0.0 - resolution: "cli-width@npm:3.0.0" - checksum: 4c94af3769367a70e11ed69aa6095f1c600c0ff510f3921ab4045af961820d57c0233acfa8b6396037391f31b4c397e1f614d234294f979ff61430a6c166c3f6 +"cli-width@npm:^4.1.0": + version: 4.1.0 + resolution: "cli-width@npm:4.1.0" + checksum: 0a79cff2dbf89ef530bcd54c713703ba94461457b11e5634bd024c78796ed21401e32349c004995954e06f442d82609287e7aabf6a5f02c919a1cf3b9b6854ff languageName: node linkType: hard @@ -9629,7 +9606,7 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.0.2, csstype@npm:^3.1.2, csstype@npm:^3.1.3": +"csstype@npm:^3.0.2, csstype@npm:^3.1.3": version: 3.1.3 resolution: "csstype@npm:3.1.3" checksum: 8db785cc92d259102725b3c694ec0c823f5619a84741b5c7991b8ad135dfaa66093038a1cc63e03361a6cd28d122be48f2106ae72334e067dd619a51f49eddf7 @@ -10200,10 +10177,10 @@ __metadata: languageName: node linkType: hard -"diff@npm:5.1.0": - version: 5.1.0 - resolution: "diff@npm:5.1.0" - checksum: c7bf0df7c9bfbe1cf8a678fd1b2137c4fb11be117a67bc18a0e03ae75105e8533dbfb1cda6b46beb3586ef5aed22143ef9d70713977d5fb1f9114e21455fba90 +"diff@npm:5.2.0": + version: 5.2.0 + resolution: "diff@npm:5.2.0" + checksum: 12b63ca9c36c72bafa3effa77121f0581b4015df18bc16bac1f8e263597735649f1a173c26f7eba17fb4162b073fee61788abe49610e6c70a2641fe1895443fd languageName: node linkType: hard @@ -11818,17 +11795,6 @@ __metadata: languageName: node linkType: hard -"external-editor@npm:^3.0.3": - version: 3.1.0 - resolution: "external-editor@npm:3.1.0" - dependencies: - chardet: ^0.7.0 - iconv-lite: ^0.4.24 - tmp: ^0.0.33 - checksum: 1c2a616a73f1b3435ce04030261bed0e22d4737e14b090bb48e58865da92529c9f2b05b893de650738d55e692d071819b45e1669259b2b354bc3154d27a698c7 - languageName: node - linkType: hard - "extglob@npm:^2.0.4": version: 2.0.4 resolution: "extglob@npm:2.0.4" @@ -11979,7 +11945,7 @@ __metadata: languageName: node linkType: hard -"figures@npm:^3.0.0, figures@npm:^3.2.0": +"figures@npm:^3.2.0": version: 3.2.0 resolution: "figures@npm:3.2.0" dependencies: @@ -12688,7 +12654,22 @@ __metadata: languageName: node linkType: hard -"glob@npm:10.3.10, glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": +"glob@npm:10.3.14": + version: 10.3.14 + resolution: "glob@npm:10.3.14" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^2.3.6 + minimatch: ^9.0.1 + minipass: ^7.0.4 + path-scurry: ^1.11.0 + bin: + glob: dist/esm/bin.mjs + checksum: 6fb26013e6ee1cc0fe099c746f5870783612082342eeeca80031446ca8839acc13243015056e4f3158d7c4260d32f37ff1c2aad9c273672ed0911c8262316041 + languageName: node + linkType: hard + +"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": version: 10.3.10 resolution: "glob@npm:10.3.10" dependencies: @@ -13130,10 +13111,10 @@ __metadata: languageName: node linkType: hard -"headers-polyfill@npm:^4.0.1": - version: 4.0.2 - resolution: "headers-polyfill@npm:4.0.2" - checksum: a95280ed58df429fc86c4f49b21596be3ea3f5f3d790e7d75238668df9b90b292f15a968c7c19ae1db88c0ae036dd1bf363a71b8e771199d82848e2d8b3c6c2e +"headers-polyfill@npm:^4.0.2": + version: 4.0.3 + resolution: "headers-polyfill@npm:4.0.3" + checksum: 382efe88575362f9f343f813a9df5131cec23129121111c55fb1151fb6dc87d963a820412fc95ff9cbc3016149de0714211dfa5d5914020ed92a69f014f66600 languageName: node linkType: hard @@ -13336,7 +13317,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.4.24, iconv-lite@npm:^0.4.24": +"iconv-lite@npm:0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" dependencies: @@ -13442,29 +13423,6 @@ __metadata: languageName: node linkType: hard -"inquirer@npm:^8.2.0": - version: 8.2.6 - resolution: "inquirer@npm:8.2.6" - dependencies: - ansi-escapes: ^4.2.1 - chalk: ^4.1.1 - cli-cursor: ^3.1.0 - cli-width: ^3.0.0 - external-editor: ^3.0.3 - figures: ^3.0.0 - lodash: ^4.17.21 - mute-stream: 0.0.8 - ora: ^5.4.1 - run-async: ^2.4.0 - rxjs: ^7.5.5 - string-width: ^4.1.0 - strip-ansi: ^6.0.0 - through: ^2.3.6 - wrap-ansi: ^6.0.1 - checksum: 387ffb0a513559cc7414eb42c57556a60e302f820d6960e89d376d092e257a919961cd485a1b4de693dbb5c0de8bc58320bfd6247dfd827a873aa82a4215a240 - languageName: node - linkType: hard - "internal-slot@npm:^1.0.4, internal-slot@npm:^1.0.5": version: 1.0.6 resolution: "internal-slot@npm:1.0.6" @@ -14275,7 +14233,7 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.3.5": +"jackspeak@npm:^2.3.5, jackspeak@npm:^2.3.6": version: 2.3.6 resolution: "jackspeak@npm:2.3.6" dependencies: @@ -14906,13 +14864,6 @@ __metadata: languageName: node linkType: hard -"js-levenshtein@npm:^1.1.6": - version: 1.1.6 - resolution: "js-levenshtein@npm:1.1.6" - checksum: 409f052a7f1141be4058d97da7860e08efd97fc588b7a4c5cfa0548bc04f6d576644dae65ab630266dff685d56fb90d494e03d4d79cb484c287746b4f1bf0694 - languageName: node - linkType: hard - "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -15471,6 +15422,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^10.2.0": + version: 10.2.2 + resolution: "lru-cache@npm:10.2.2" + checksum: 98e8fc93691c546f719a76103ef2bee5a3ac823955c755a47641ec41f8c7fafa1baeaba466937cc1cbfa9cfd47e03536d10e2db3158a64ad91ff3a58a32c893e + languageName: node + linkType: hard + "lru-cache@npm:^5.1.1": version: 5.1.1 resolution: "lru-cache@npm:5.1.1" @@ -16495,6 +16453,13 @@ __metadata: languageName: node linkType: hard +"minipass@npm:^7.0.4": + version: 7.1.1 + resolution: "minipass@npm:7.1.1" + checksum: d2c461947a7530f93de4162aa3ca0a1bed1f121626906f6ec63a5ba05fd7b1d9bee4fe89a37a43db7241c2416be98a799c1796abae583c7180be37be5c392ef6 + languageName: node + linkType: hard + "minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": version: 2.1.2 resolution: "minizlib@npm:2.1.2" @@ -16586,57 +16551,53 @@ __metadata: languageName: node linkType: hard -"msw-storybook-addon@npm:2.0.0--canary.122.06f0c92.0": - version: 2.0.0--canary.122.06f0c92.0 - resolution: "msw-storybook-addon@npm:2.0.0--canary.122.06f0c92.0" +"msw-storybook-addon@npm:2.0.2": + version: 2.0.2 + resolution: "msw-storybook-addon@npm:2.0.2" dependencies: is-node-process: ^1.0.1 peerDependencies: - msw: ^2.0.9 - checksum: de8a78b1b6f2fbc9122f5a02c1401d0e1254b6389f9ce931e93dcbe00c4a0257bb77f63642b399c881e03f0d6847876dc981d45ed4643ec975647b3a719b2ecc + msw: ^2.0.0 + checksum: 9097cac0a47c56a5d85537622152fe0a25ede6f4320f62c0f8a63ffc5c38af0d218905645f60001f5f1e13da467a39392edeefd5ccd202797d226ff995f676f4 languageName: node linkType: hard -"msw@npm:2.0.11": - version: 2.0.11 - resolution: "msw@npm:2.0.11" +"msw@npm:2.3.0": + version: 2.3.0 + resolution: "msw@npm:2.3.0" dependencies: "@bundled-es-modules/cookie": ^2.0.0 - "@bundled-es-modules/js-levenshtein": ^2.0.1 "@bundled-es-modules/statuses": ^1.0.1 + "@inquirer/confirm": ^3.0.0 "@mswjs/cookies": ^1.1.0 - "@mswjs/interceptors": ^0.25.13 + "@mswjs/interceptors": ^0.29.0 "@open-draft/until": ^2.1.0 - "@types/cookie": ^0.4.1 - "@types/js-levenshtein": ^1.1.1 - "@types/statuses": ^2.0.1 + "@types/cookie": ^0.6.0 + "@types/statuses": ^2.0.4 chalk: ^4.1.2 - chokidar: ^3.4.2 graphql: ^16.8.1 - headers-polyfill: ^4.0.1 - inquirer: ^8.2.0 + headers-polyfill: ^4.0.2 is-node-process: ^1.2.0 - js-levenshtein: ^1.1.6 - outvariant: ^1.4.0 + outvariant: ^1.4.2 path-to-regexp: ^6.2.0 - strict-event-emitter: ^0.5.0 - type-fest: ^2.19.0 - yargs: ^17.3.1 + strict-event-emitter: ^0.5.1 + type-fest: ^4.9.0 + yargs: ^17.7.2 peerDependencies: - typescript: ">= 4.7.x <= 5.2.x" + typescript: ">= 4.7.x" peerDependenciesMeta: typescript: optional: true bin: msw: cli/index.js - checksum: a87175f53e3b510dfdfb16e11f2b0d399a9859ce1f249a70741045ce6325b3512075878921d4bd30ad6cb0789cd6fc4f9eac5db68ae425777e96ad208285242d + checksum: 1b6e9e94f3c3f32f1c5bbdb619dac1c46adc7012e1c3131ab3936817cc7734b6b3cae5cca8947422a84f7b9e6393b5fe44dd174fd2d52d1fc0a0e1fc616a356b languageName: node linkType: hard -"mute-stream@npm:0.0.8": - version: 0.0.8 - resolution: "mute-stream@npm:0.0.8" - checksum: ff48d251fc3f827e5b1206cda0ffdaec885e56057ee86a3155e1951bc940fd5f33531774b1cc8414d7668c10a8907f863f6561875ee6e8768931a62121a531a1 +"mute-stream@npm:^1.0.0": + version: 1.0.0 + resolution: "mute-stream@npm:1.0.0" + checksum: 36fc968b0e9c9c63029d4f9dc63911950a3bdf55c9a87f58d3a266289b67180201cade911e7699f8b2fa596b34c9db43dad37649e3f7fdd13c3bb9edb0017ee7 languageName: node linkType: hard @@ -17141,13 +17102,6 @@ __metadata: languageName: node linkType: hard -"os-tmpdir@npm:~1.0.2": - version: 1.0.2 - resolution: "os-tmpdir@npm:1.0.2" - checksum: 5666560f7b9f10182548bf7013883265be33620b1c1b4a4d405c25be2636f970c5488ff3e6c48de75b55d02bde037249fe5dbfbb4c0fb7714953d56aed062e6d - languageName: node - linkType: hard - "ospath@npm:^1.2.2": version: 1.2.2 resolution: "ospath@npm:1.2.2" @@ -17155,7 +17109,7 @@ __metadata: languageName: node linkType: hard -"outvariant@npm:^1.2.1, outvariant@npm:^1.4.0": +"outvariant@npm:^1.2.1, outvariant@npm:^1.4.0, outvariant@npm:^1.4.2": version: 1.4.2 resolution: "outvariant@npm:1.4.2" checksum: 5d9e2b3edb1cc8be9cbfc1c8c97e8b05137c4384bbfc56e0a465de26c5d2f023e65732ddcda9d46599b06d667fbc0de32c30d2ecd11f6f3f43bcf8ce0d320918 @@ -17375,6 +17329,16 @@ __metadata: languageName: node linkType: hard +"path-scurry@npm:^1.11.0": + version: 1.11.0 + resolution: "path-scurry@npm:1.11.0" + dependencies: + lru-cache: ^10.2.0 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + checksum: 79732c6a4d989846632d3ff8a441fabb8ea197ecdc7f328ea0f1694d611ed9bd3f0c940582d91c7dd108a29898866212a359d1a9b92ca69c4dbb16ebeae86b73 + languageName: node + linkType: hard + "path-to-regexp@npm:0.1.7": version: 0.1.7 resolution: "path-to-regexp@npm:0.1.7" @@ -17935,9 +17899,9 @@ __metadata: languageName: node linkType: hard -"react-big-calendar@npm:1.8.5": - version: 1.8.5 - resolution: "react-big-calendar@npm:1.8.5" +"react-big-calendar@npm:1.12.2": + version: 1.12.2 + resolution: "react-big-calendar@npm:1.12.2" dependencies: "@babel/runtime": ^7.20.7 clsx: ^1.2.1 @@ -17958,7 +17922,7 @@ __metadata: peerDependencies: react: ^16.14.0 || ^17 || ^18 react-dom: ^16.14.0 || ^17 || ^18 - checksum: 57ce758abec0dc949047df586d202ed1b2d9afded0add416d187fe09bfee72812c3652d9e49a6d4f15953301bb92d9d2db09c1dd7c7dfd7a0f8ab8612d844a1a + checksum: 265516ddf23a7fb25bbd332bd07d8622899c5744c66fc76c97f20ff9e66027bf4278e2dacdf1e7ab21a993679c24b034f38db745b25ab9eea57656507bbba37c languageName: node linkType: hard @@ -19006,13 +18970,13 @@ __metadata: "@dnd-kit/sortable": 8.0.0 "@dnd-kit/utilities": 3.2.2 "@emotion/react": 11.11.1 - "@emotion/styled": 11.11.0 + "@emotion/styled": 11.11.5 "@material/material-color-utilities": 0.2.7 "@mui/icons-material": 5.15.13 - "@mui/lab": 5.0.0-alpha.162 - "@mui/material": 5.15.15 + "@mui/lab": 5.0.0-alpha.170 + "@mui/material": 5.15.19 "@mui/styles": 5.15.15 - "@mui/system": 5.15.6 + "@mui/system": 5.15.15 "@mui/x-data-grid": 6.19.6 "@playwright/test": 1.41.2 "@storybook/addon-essentials": 8.0.0 @@ -19023,10 +18987,10 @@ __metadata: "@storybook/react": 8.0.0 "@storybook/react-vite": 8.0.0 "@storybook/test": 8.0.8 - "@storybook/test-runner": 0.17.0 + "@storybook/test-runner": 0.18.2 "@storybook/types": 8.0.6 "@types/chance": 1.1.6 - "@types/diff": 5.0.8 + "@types/diff": 5.2.1 "@types/glob": 8.1.0 "@types/jest": 29.5.12 "@types/lodash": 4.17.1 @@ -19034,20 +18998,20 @@ __metadata: "@types/node": 20.11.30 "@types/prop-types": 15.7.11 "@types/react": 18.2.48 - "@types/react-big-calendar": 1.6.5 + "@types/react-big-calendar": 1.8.9 "@types/react-dom": 18.2.22 "@types/react-transition-group": 4.4.10 "@types/react-virtualized-auto-sizer": 1.0.4 - "@typescript-eslint/eslint-plugin": 7.7.0 + "@typescript-eslint/eslint-plugin": 7.11.0 "@typescript-eslint/parser": 6.21.0 "@urql/exchange-retry": 1.2.1 bowser: 2.11.0 chance: 1.1.11 - classnames: 2.3.2 + classnames: 2.5.1 concurrently: 8.2.2 cypress: 13.3.0 detect-package-manager: 3.0.1 - diff: 5.1.0 + diff: 5.2.0 esbuild: 0.20.2 esbuild-jest: 0.5.0 eslint: 8.57.0 @@ -19065,7 +19029,7 @@ __metadata: eslint-plugin-react-hooks: 4.6.2 eslint-plugin-storybook: 0.8.0 fuse.js: 7.0.0 - glob: 10.3.10 + glob: 10.3.14 graphiql: 3.0.10 graphql: 16.8.1 http-server: 14.1.1 @@ -19074,14 +19038,14 @@ __metadata: luxon: 3.4.4 mdast-util-find-and-replace: 3.0.1 mdi-material-ui: 7.8.0 - msw: 2.0.11 - msw-storybook-addon: 2.0.0--canary.122.06f0c92.0 + msw: 2.3.0 + msw-storybook-addon: 2.0.2 prettier: 3.2.5 prettier-plugin-go-template: 0.0.15 prop-types: 15.8.1 punycode: 2.3.1 react: 18.2.0 - react-big-calendar: 1.8.5 + react-big-calendar: 1.12.2 react-colorful: 5.6.1 react-countdown: 2.3.5 react-dom: 18.2.0 @@ -19102,7 +19066,7 @@ __metadata: storybook: 8.0.9 storybook-addon-mock: 4.3.0 stylelint: 16.2.1 - stylelint-config-standard: 34.0.0 + stylelint-config-standard: 36.0.0 typescript: 5.2.2 urql: 4.0.6 vite: 5.1.7 @@ -19123,13 +19087,6 @@ __metadata: languageName: node linkType: hard -"run-async@npm:^2.4.0": - version: 2.4.1 - resolution: "run-async@npm:2.4.1" - checksum: a2c88aa15df176f091a2878eb840e68d0bdee319d8d97bbb89112223259cebecb94bc0defd735662b83c2f7a30bed8cddb7d1674eb48ae7322dc602b22d03797 - languageName: node - linkType: hard - "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -19139,7 +19096,7 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^7.5.1, rxjs@npm:^7.5.5, rxjs@npm:^7.8.1": +"rxjs@npm:^7.5.1, rxjs@npm:^7.8.1": version: 7.8.1 resolution: "rxjs@npm:7.8.1" dependencies: @@ -19893,7 +19850,7 @@ __metadata: languageName: node linkType: hard -"strict-event-emitter@npm:^0.5.0, strict-event-emitter@npm:^0.5.1": +"strict-event-emitter@npm:^0.5.1": version: 0.5.1 resolution: "strict-event-emitter@npm:0.5.1" checksum: 350480431bc1c28fdb601ef4976c2f8155fc364b4740f9692dd03e5bdd48aafc99a5e021fe655fbd986d0b803e9f3fc5c4b018b35cb838c4690d60f2a26f1cf3 @@ -20143,23 +20100,23 @@ __metadata: languageName: node linkType: hard -"stylelint-config-recommended@npm:^13.0.0": - version: 13.0.0 - resolution: "stylelint-config-recommended@npm:13.0.0" +"stylelint-config-recommended@npm:^14.0.0": + version: 14.0.0 + resolution: "stylelint-config-recommended@npm:14.0.0" peerDependencies: - stylelint: ^15.10.0 - checksum: a56eb6d1a7c7f3a7a172b54bc34218859ba22a5a06816fb4d0964f66cb83cf372062f2c97830e994ad68243548e15fc49abf28887c3261ab1b471b3aa69f8e82 + stylelint: ^16.0.0 + checksum: 36511115b06d9f51aa0edc05f6064a7aae98cc990da14dd03629951f63a029d9e66a4d5b1ca678cce699e24413a62c2cd608cc07413ca5026f9680ddb8993858 languageName: node linkType: hard -"stylelint-config-standard@npm:34.0.0": - version: 34.0.0 - resolution: "stylelint-config-standard@npm:34.0.0" +"stylelint-config-standard@npm:36.0.0": + version: 36.0.0 + resolution: "stylelint-config-standard@npm:36.0.0" dependencies: - stylelint-config-recommended: ^13.0.0 + stylelint-config-recommended: ^14.0.0 peerDependencies: - stylelint: ^15.10.0 - checksum: 536249800c04b48a9c354067765f042713982e8222be17bb897a27d26546e50adfb87e6f1e4541807d720de3554345da99ab470e13e8d7ab0ab326c73ae3df61 + stylelint: ^16.1.0 + checksum: 78b14cdfdd03be409687acc863ef88d0e79d9a7f7ab3a9158e7dcd74212893db24841d22f076f248f3b1b6419d778538a5c885dc42fc056eaeb240463edf2f8f languageName: node linkType: hard @@ -20425,7 +20382,7 @@ __metadata: languageName: node linkType: hard -"through@npm:^2.3.6, through@npm:^2.3.8": +"through@npm:^2.3.8": version: 2.3.8 resolution: "through@npm:2.3.8" checksum: a38c3e059853c494af95d50c072b83f8b676a9ba2818dcc5b108ef252230735c54e0185437618596c790bbba8fcdaef5b290405981ffa09dce67b1f1bf190cbd @@ -20460,15 +20417,6 @@ __metadata: languageName: node linkType: hard -"tmp@npm:^0.0.33": - version: 0.0.33 - resolution: "tmp@npm:0.0.33" - dependencies: - os-tmpdir: ~1.0.2 - checksum: 902d7aceb74453ea02abbf58c203f4a8fc1cead89b60b31e354f74ed5b3fb09ea817f94fb310f884a5d16987dd9fa5a735412a7c2dd088dd3d415aa819ae3a28 - languageName: node - linkType: hard - "tmp@npm:~0.2.1": version: 0.2.1 resolution: "tmp@npm:0.2.1" @@ -20758,6 +20706,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^4.9.0": + version: 4.18.2 + resolution: "type-fest@npm:4.18.2" + checksum: 2e9272b2b97b2f4ea2bbffda43cfce9ca89c474ad7c9565e39b80fee2ce609ea60385faffbbef98994b38feb3fa5fa38feb33acf175f4f85ee21d1773e87bf44 + languageName: node + linkType: hard + "type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" @@ -21721,7 +21676,7 @@ __metadata: languageName: node linkType: hard -"wrap-ansi@npm:^6.0.1, wrap-ansi@npm:^6.2.0": +"wrap-ansi@npm:^6.2.0": version: 6.2.0 resolution: "wrap-ansi@npm:6.2.0" dependencies: @@ -21794,11 +21749,11 @@ __metadata: linkType: hard "ws@npm:^6.1.0": - version: 6.2.2 - resolution: "ws@npm:6.2.2" + version: 6.2.3 + resolution: "ws@npm:6.2.3" dependencies: async-limiter: ~1.0.0 - checksum: aec3154ec51477c094ac2cb5946a156e17561a581fa27005cbf22c53ac57f8d4e5f791dd4bbba6a488602cb28778c8ab7df06251d590507c3c550fd8ebeee949 + checksum: bbc96ff5628832d80669a88fd117487bf070492dfaa50df77fa442a2b119792e772f4365521e0a8e025c0d51173c54fa91adab165c11b8e0674685fdd36844a5 languageName: node linkType: hard