Send mailing list emails
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -1695,6 +1695,13 @@ type MailingList implements Node {
|
||||
last: Int
|
||||
before: CursorKey
|
||||
): MailingListSubscriberConnection! @goField(forceResolver: true)
|
||||
|
||||
updates(
|
||||
first: Int
|
||||
after: CursorKey
|
||||
last: Int
|
||||
before: CursorKey
|
||||
): MailingListUpdateConnection! @goField(forceResolver: true)
|
||||
}
|
||||
|
||||
enum MailingListSubscriberStatus
|
||||
@@ -1734,6 +1741,51 @@ type MailingListSubscriberEdge {
|
||||
node: MailingListSubscriber!
|
||||
}
|
||||
|
||||
enum MailingListUpdateStatus
|
||||
@goModel(
|
||||
model: "go.probo.inc/probo/pkg/coredata.MailingListUpdateStatus"
|
||||
) {
|
||||
DRAFT
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.MailingListUpdateStatusDraft"
|
||||
)
|
||||
ENQUEUED
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.MailingListUpdateStatusEnqueued"
|
||||
)
|
||||
PROCESSING
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.MailingListUpdateStatusProcessing"
|
||||
)
|
||||
SENT
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.MailingListUpdateStatusSent"
|
||||
)
|
||||
}
|
||||
|
||||
type MailingListUpdate implements Node {
|
||||
id: ID!
|
||||
title: String!
|
||||
body: String!
|
||||
status: MailingListUpdateStatus!
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
}
|
||||
|
||||
type MailingListUpdateConnection
|
||||
@goModel(
|
||||
model: "go.probo.inc/probo/pkg/server/api/console/v1/types.MailingListUpdateConnection"
|
||||
) {
|
||||
edges: [MailingListUpdateEdge!]!
|
||||
pageInfo: PageInfo!
|
||||
totalCount: Int! @goField(forceResolver: true)
|
||||
}
|
||||
|
||||
type MailingListUpdateEdge {
|
||||
cursor: CursorKey!
|
||||
node: MailingListUpdate!
|
||||
}
|
||||
|
||||
type Organization implements Node {
|
||||
id: ID!
|
||||
name: String!
|
||||
@@ -3407,6 +3459,19 @@ type Mutation {
|
||||
deleteTrustCenterAccess(
|
||||
input: DeleteTrustCenterAccessInput!
|
||||
): DeleteTrustCenterAccessPayload!
|
||||
# Compliance News mutations
|
||||
createMailingListUpdate(
|
||||
input: CreateMailingListUpdateInput!
|
||||
): CreateMailingListUpdatePayload!
|
||||
updateMailingListUpdate(
|
||||
input: UpdateMailingListUpdateInput!
|
||||
): UpdateMailingListUpdatePayload!
|
||||
sendMailingListUpdate(
|
||||
input: SendMailingListUpdateInput!
|
||||
): SendMailingListUpdatePayload!
|
||||
deleteMailingListUpdate(
|
||||
input: DeleteMailingListUpdateInput!
|
||||
): DeleteMailingListUpdatePayload!
|
||||
# Mailing List mutations
|
||||
updateMailingList(
|
||||
input: UpdateMailingListInput!
|
||||
@@ -3829,6 +3894,26 @@ type UpdateMailingListPayload {
|
||||
mailingList: MailingList!
|
||||
}
|
||||
|
||||
input CreateMailingListUpdateInput {
|
||||
mailingListId: ID!
|
||||
title: String!
|
||||
body: String!
|
||||
}
|
||||
|
||||
input UpdateMailingListUpdateInput {
|
||||
id: ID!
|
||||
title: String!
|
||||
body: String!
|
||||
}
|
||||
|
||||
input SendMailingListUpdateInput {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
input DeleteMailingListUpdateInput {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
input CreateMailingListSubscriberInput {
|
||||
mailingListId: ID!
|
||||
fullName: String!
|
||||
@@ -4690,6 +4775,22 @@ type DeleteTrustCenterAccessPayload {
|
||||
deletedTrustCenterAccessId: ID!
|
||||
}
|
||||
|
||||
type CreateMailingListUpdatePayload {
|
||||
mailingListUpdate: MailingListUpdate!
|
||||
}
|
||||
|
||||
type UpdateMailingListUpdatePayload {
|
||||
mailingListUpdate: MailingListUpdate!
|
||||
}
|
||||
|
||||
type SendMailingListUpdatePayload {
|
||||
mailingListUpdate: MailingListUpdate!
|
||||
}
|
||||
|
||||
type DeleteMailingListUpdatePayload {
|
||||
deletedMailingListUpdateId: ID!
|
||||
}
|
||||
|
||||
type CreateMailingListSubscriberPayload {
|
||||
mailingListSubscriberEdge: MailingListSubscriberEdge!
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
66
pkg/server/api/console/v1/types/mailing_list_update.go
Normal file
66
pkg/server/api/console/v1/types/mailing_list_update.go
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
type MailingListUpdateConnection struct {
|
||||
TotalCount int
|
||||
Edges []*MailingListUpdateEdge
|
||||
PageInfo *PageInfo
|
||||
|
||||
Resolver any
|
||||
ParentID gid.GID
|
||||
}
|
||||
|
||||
func NewMailingListUpdate(mlu *coredata.MailingListUpdate) *MailingListUpdate {
|
||||
return &MailingListUpdate{
|
||||
ID: mlu.ID,
|
||||
Title: mlu.Title,
|
||||
Body: mlu.Body,
|
||||
Status: mlu.Status,
|
||||
CreatedAt: mlu.CreatedAt,
|
||||
UpdatedAt: mlu.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func NewMailingListUpdateEdge(mlu *coredata.MailingListUpdate, orderBy coredata.MailingListUpdateOrderField) *MailingListUpdateEdge {
|
||||
return &MailingListUpdateEdge{
|
||||
Cursor: mlu.CursorKey(orderBy),
|
||||
Node: NewMailingListUpdate(mlu),
|
||||
}
|
||||
}
|
||||
|
||||
func NewMailingListUpdateConnection(
|
||||
p *page.Page[*coredata.MailingListUpdate, coredata.MailingListUpdateOrderField],
|
||||
resolver any,
|
||||
mailingListID gid.GID,
|
||||
) *MailingListUpdateConnection {
|
||||
edges := make([]*MailingListUpdateEdge, len(p.Data))
|
||||
for i := range edges {
|
||||
edges[i] = NewMailingListUpdateEdge(p.Data[i], p.Cursor.OrderBy.Field)
|
||||
}
|
||||
|
||||
return &MailingListUpdateConnection{
|
||||
Edges: edges,
|
||||
PageInfo: NewPageInfo(p),
|
||||
Resolver: resolver,
|
||||
ParentID: mailingListID,
|
||||
}
|
||||
}
|
||||
@@ -446,6 +446,16 @@ type CreateMailingListSubscriberPayload struct {
|
||||
MailingListSubscriberEdge *MailingListSubscriberEdge `json:"mailingListSubscriberEdge"`
|
||||
}
|
||||
|
||||
type CreateMailingListUpdateInput struct {
|
||||
MailingListID gid.GID `json:"mailingListId"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
type CreateMailingListUpdatePayload struct {
|
||||
MailingListUpdate *MailingListUpdate `json:"mailingListUpdate"`
|
||||
}
|
||||
|
||||
type CreateMeasureInput struct {
|
||||
OrganizationID gid.GID `json:"organizationId"`
|
||||
Name string `json:"name"`
|
||||
@@ -977,6 +987,14 @@ type DeleteMailingListSubscriberPayload struct {
|
||||
DeletedMailingListSubscriberID gid.GID `json:"deletedMailingListSubscriberId"`
|
||||
}
|
||||
|
||||
type DeleteMailingListUpdateInput struct {
|
||||
ID gid.GID `json:"id"`
|
||||
}
|
||||
|
||||
type DeleteMailingListUpdatePayload struct {
|
||||
DeletedMailingListUpdateID gid.GID `json:"deletedMailingListUpdateId"`
|
||||
}
|
||||
|
||||
type DeleteMeasureInput struct {
|
||||
MeasureID gid.GID `json:"measureId"`
|
||||
}
|
||||
@@ -1453,6 +1471,7 @@ type MailingList struct {
|
||||
ID gid.GID `json:"id"`
|
||||
ReplyTo *mail.Addr `json:"replyTo,omitempty"`
|
||||
Subscribers *MailingListSubscriberConnection `json:"subscribers"`
|
||||
Updates *MailingListUpdateConnection `json:"updates"`
|
||||
}
|
||||
|
||||
func (MailingList) IsNode() {}
|
||||
@@ -1475,6 +1494,23 @@ type MailingListSubscriberEdge struct {
|
||||
Node *MailingListSubscriber `json:"node"`
|
||||
}
|
||||
|
||||
type MailingListUpdate struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
Status coredata.MailingListUpdateStatus `json:"status"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (MailingListUpdate) IsNode() {}
|
||||
func (this MailingListUpdate) GetID() gid.GID { return this.ID }
|
||||
|
||||
type MailingListUpdateEdge struct {
|
||||
Cursor page.CursorKey `json:"cursor"`
|
||||
Node *MailingListUpdate `json:"node"`
|
||||
}
|
||||
|
||||
type Measure struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Category string `json:"category"`
|
||||
@@ -1815,6 +1851,14 @@ type RiskFilter struct {
|
||||
SnapshotID *gid.GID `json:"snapshotId,omitempty"`
|
||||
}
|
||||
|
||||
type SendMailingListUpdateInput struct {
|
||||
ID gid.GID `json:"id"`
|
||||
}
|
||||
|
||||
type SendMailingListUpdatePayload struct {
|
||||
MailingListUpdate *MailingListUpdate `json:"mailingListUpdate"`
|
||||
}
|
||||
|
||||
type SendSigningNotificationsInput struct {
|
||||
OrganizationID gid.GID `json:"organizationId"`
|
||||
}
|
||||
@@ -2181,6 +2225,16 @@ type UpdateMailingListPayload struct {
|
||||
MailingList *MailingList `json:"mailingList"`
|
||||
}
|
||||
|
||||
type UpdateMailingListUpdateInput struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
type UpdateMailingListUpdatePayload struct {
|
||||
MailingListUpdate *MailingListUpdate `json:"mailingListUpdate"`
|
||||
}
|
||||
|
||||
type UpdateMeasureInput struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/iam"
|
||||
"go.probo.inc/probo/pkg/mailman"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/probo"
|
||||
"go.probo.inc/probo/pkg/server/api/authn"
|
||||
@@ -1546,6 +1547,28 @@ func (r *mailingListResolver) Subscribers(ctx context.Context, obj *types.Mailin
|
||||
return types.NewMailingListSubscriberConnection(result, r, obj.ID), nil
|
||||
}
|
||||
|
||||
// Updates is the resolver for the updates field on MailingList.
|
||||
func (r *mailingListResolver) Updates(ctx context.Context, obj *types.MailingList, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.MailingListUpdateConnection, error) {
|
||||
if err := r.authorize(ctx, obj.ID, probo.ActionMailingListUpdateList); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.MailingListUpdateOrderField]{
|
||||
Field: coredata.MailingListUpdateOrderFieldUpdatedAt,
|
||||
Direction: page.OrderDirectionDesc,
|
||||
}
|
||||
|
||||
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||
|
||||
result, err := r.mailman.ListMailingListUpdates(ctx, obj.ID, cursor)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot list mailing list updates", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return types.NewMailingListUpdateConnection(result, r, obj.ID), nil
|
||||
}
|
||||
|
||||
// TotalCount is the resolver for the totalCount field.
|
||||
func (r *mailingListSubscriberConnectionResolver) TotalCount(ctx context.Context, obj *types.MailingListSubscriberConnection) (int, error) {
|
||||
if err := r.authorize(ctx, obj.ParentID, probo.ActionMailingListSubscriberList); err != nil {
|
||||
@@ -1565,6 +1588,21 @@ func (r *mailingListSubscriberConnectionResolver) TotalCount(ctx context.Context
|
||||
panic(fmt.Errorf("not implemented: TotalCount for parent type %T", obj.Resolver))
|
||||
}
|
||||
|
||||
// TotalCount is the resolver for the totalCount field on MailingListUpdateConnection.
|
||||
func (r *mailingListUpdateConnectionResolver) TotalCount(ctx context.Context, obj *types.MailingListUpdateConnection) (int, error) {
|
||||
if err := r.authorize(ctx, obj.ParentID, probo.ActionMailingListUpdateList); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
count, err := r.mailman.CountMailingListUpdates(ctx, obj.ParentID)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot count mailing list updates", log.Error(err))
|
||||
return 0, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// Evidences is the resolver for the evidences field.
|
||||
func (r *measureResolver) Evidences(ctx context.Context, obj *types.Measure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.EvidenceOrderBy) (*types.EvidenceConnection, error) {
|
||||
if err := r.authorize(ctx, obj.ID, probo.ActionEvidenceList); err != nil {
|
||||
@@ -2028,6 +2066,88 @@ func (r *mutationResolver) DeleteTrustCenterAccess(ctx context.Context, input ty
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CreateMailingListUpdate is the resolver for the createMailingListUpdate field.
|
||||
func (r *mutationResolver) CreateMailingListUpdate(ctx context.Context, input types.CreateMailingListUpdateInput) (*types.CreateMailingListUpdatePayload, error) {
|
||||
if err := r.authorize(ctx, input.MailingListID, probo.ActionMailingListUpdateCreate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mlu, err := r.mailman.CreateMailingListUpdate(ctx, input.MailingListID, input.Title, input.Body)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot create mailing list update", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return &types.CreateMailingListUpdatePayload{
|
||||
MailingListUpdate: types.NewMailingListUpdate(mlu),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateMailingListUpdate is the resolver for the updateMailingListUpdate field.
|
||||
func (r *mutationResolver) UpdateMailingListUpdate(ctx context.Context, input types.UpdateMailingListUpdateInput) (*types.UpdateMailingListUpdatePayload, error) {
|
||||
if err := r.authorize(ctx, input.ID, probo.ActionMailingListUpdateUpdate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mlu, err := r.mailman.UpdateMailingListUpdate(ctx, input.ID, input.Title, input.Body)
|
||||
if err != nil {
|
||||
if errors.Is(err, mailman.ErrMailingListUpdateAlreadySent) {
|
||||
return nil, gqlutils.Conflictf(ctx, "mailing list update can only be edited when in draft")
|
||||
}
|
||||
if errors.Is(err, mailman.ErrMailingListUpdateNotFound) {
|
||||
return nil, gqlutils.NotFoundf(ctx, "mailing list update not found")
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot update mailing list update", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return &types.UpdateMailingListUpdatePayload{
|
||||
MailingListUpdate: types.NewMailingListUpdate(mlu),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SendMailingListUpdate is the resolver for the sendMailingListUpdate field.
|
||||
func (r *mutationResolver) SendMailingListUpdate(ctx context.Context, input types.SendMailingListUpdateInput) (*types.SendMailingListUpdatePayload, error) {
|
||||
if err := r.authorize(ctx, input.ID, probo.ActionMailingListUpdateUpdate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mlu, err := r.mailman.SendMailingListUpdate(ctx, input.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, mailman.ErrMailingListUpdateAlreadySent) {
|
||||
return nil, gqlutils.Conflictf(ctx, "mailing list update has already been queued for sending")
|
||||
}
|
||||
if errors.Is(err, mailman.ErrMailingListUpdateNotFound) {
|
||||
return nil, gqlutils.NotFoundf(ctx, "mailing list update not found")
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot queue mailing list update for sending", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return &types.SendMailingListUpdatePayload{
|
||||
MailingListUpdate: types.NewMailingListUpdate(mlu),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DeleteMailingListUpdate is the resolver for the deleteMailingListUpdate field.
|
||||
func (r *mutationResolver) DeleteMailingListUpdate(ctx context.Context, input types.DeleteMailingListUpdateInput) (*types.DeleteMailingListUpdatePayload, error) {
|
||||
if err := r.authorize(ctx, input.ID, probo.ActionMailingListUpdateDelete); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := r.mailman.DeleteMailingListUpdate(ctx, input.ID); err != nil {
|
||||
if errors.Is(err, mailman.ErrMailingListUpdateNotFound) {
|
||||
return nil, gqlutils.NotFoundf(ctx, "mailing list update not found")
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot delete mailing list update", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return &types.DeleteMailingListUpdatePayload{
|
||||
DeletedMailingListUpdateID: input.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateMailingList is the resolver for the updateMailingList field.
|
||||
func (r *mutationResolver) UpdateMailingList(ctx context.Context, input types.UpdateMailingListInput) (*types.UpdateMailingListPayload, error) {
|
||||
if err := r.authorize(ctx, input.ID, probo.ActionMailingListUpdate); err != nil {
|
||||
@@ -2051,8 +2171,16 @@ func (r *mutationResolver) CreateMailingListSubscriber(ctx context.Context, inpu
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subscriber, err := r.mailman.CreateSubscriber(ctx, input.MailingListID, input.Email, input.FullName)
|
||||
subscriber, err := r.mailman.CreateSubscriber(
|
||||
ctx,
|
||||
input.MailingListID,
|
||||
input.Email,
|
||||
input.FullName,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, mailman.ErrSubscriberAlreadyExist) {
|
||||
return nil, gqlutils.Conflictf(ctx, "subscriber already exists in this mailing list")
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot create mailing list subscriber", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
@@ -2069,6 +2197,9 @@ func (r *mutationResolver) DeleteMailingListSubscriber(ctx context.Context, inpu
|
||||
}
|
||||
|
||||
if err := r.mailman.DeleteSubscriber(ctx, input.ID); err != nil {
|
||||
if errors.Is(err, mailman.ErrSubscriberNotFound) {
|
||||
return nil, gqlutils.NotFoundf(ctx, "mailing list subscriber not found")
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot delete mailing list subscriber", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
@@ -9196,6 +9327,11 @@ func (r *Resolver) MailingListSubscriberConnection() schema.MailingListSubscribe
|
||||
return &mailingListSubscriberConnectionResolver{r}
|
||||
}
|
||||
|
||||
// MailingListUpdateConnection returns schema.MailingListUpdateConnectionResolver implementation.
|
||||
func (r *Resolver) MailingListUpdateConnection() schema.MailingListUpdateConnectionResolver {
|
||||
return &mailingListUpdateConnectionResolver{r}
|
||||
}
|
||||
|
||||
// Measure returns schema.MeasureResolver implementation.
|
||||
func (r *Resolver) Measure() schema.MeasureResolver { return &measureResolver{r} }
|
||||
|
||||
@@ -9432,6 +9568,7 @@ type frameworkResolver struct{ *Resolver }
|
||||
type frameworkConnectionResolver struct{ *Resolver }
|
||||
type mailingListResolver struct{ *Resolver }
|
||||
type mailingListSubscriberConnectionResolver struct{ *Resolver }
|
||||
type mailingListUpdateConnectionResolver struct{ *Resolver }
|
||||
type measureResolver struct{ *Resolver }
|
||||
type measureConnectionResolver struct{ *Resolver }
|
||||
type meetingResolver struct{ *Resolver }
|
||||
|
||||
Reference in New Issue
Block a user