Bunch of work around assigning reports to districts

I added some DB schema to track logos and to relate reports to
organizations. I reworked how GPS data comes from EXIF data on images
because it wasn't working for JPEGs. I might have broken PNGs in the
process. Also made the config options for domain names more
standardized.
This commit is contained in:
Eli Ribble 2026-01-22 03:27:32 +00:00
parent 486a2d98c2
commit 61d8d14fc2
No known key found for this signature in database
41 changed files with 3029 additions and 337 deletions

View file

@ -78,46 +78,6 @@ func apiAudioContentPost(w http.ResponseWriter, r *http.Request, u *models.User)
w.WriteHeader(http.StatusOK)
}
func apiGetDistrict(w http.ResponseWriter, r *http.Request) {
var latStr, lngStr string
err := r.ParseForm()
if err != nil {
render.Render(w, r, errRender(fmt.Errorf("Failed to parse GET form: %w", err)))
return
} else {
latStr = r.FormValue("lat")
lngStr = r.FormValue("lng")
}
lat, err := strconv.ParseFloat(latStr, 64)
if err != nil {
render.Render(w, r, errRender(fmt.Errorf("Failed to parse lat as float: %w", err)))
return
}
lng, err := strconv.ParseFloat(lngStr, 64)
if err != nil {
render.Render(w, r, errRender(fmt.Errorf("Failed to parse lng as float: %w", err)))
return
}
district, err := platform.DistrictForLocation(r.Context(), lng, lat)
if err != nil {
render.Render(w, r, errRender(fmt.Errorf("Failed to get district: %w", err)))
return
}
if district == nil {
http.NotFound(w, r)
return
}
d := ResponseDistrict{
Agency: district.Agency.GetOr(""),
Manager: district.GeneralMG.GetOr(""),
Phone: district.Phone1.GetOr(""),
Website: district.Website.GetOr(""),
}
if err := render.Render(w, r, d); err != nil {
render.Render(w, r, errRender(err))
}
}
func handleClientIos(w http.ResponseWriter, r *http.Request, u *models.User) {
var sinceStr string
err := r.ParseForm()

74
api/district.go Normal file
View file

@ -0,0 +1,74 @@
package api
import (
"fmt"
"net/http"
"strconv"
"github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/Gleipnir-Technology/nidus-sync/platform"
"github.com/Gleipnir-Technology/nidus-sync/userfile"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
)
func apiGetDistrict(w http.ResponseWriter, r *http.Request) {
var latStr, lngStr string
err := r.ParseForm()
if err != nil {
render.Render(w, r, errRender(fmt.Errorf("Failed to parse GET form: %w", err)))
return
} else {
latStr = r.FormValue("lat")
lngStr = r.FormValue("lng")
}
lat, err := strconv.ParseFloat(latStr, 64)
if err != nil {
render.Render(w, r, errRender(fmt.Errorf("Failed to parse lat as float: %w", err)))
return
}
lng, err := strconv.ParseFloat(lngStr, 64)
if err != nil {
render.Render(w, r, errRender(fmt.Errorf("Failed to parse lng as float: %w", err)))
return
}
district, _, err := platform.DistrictForLocation(r.Context(), lng, lat)
if err != nil {
render.Render(w, r, errRender(fmt.Errorf("Failed to get district: %w", err)))
return
}
if district == nil {
http.NotFound(w, r)
return
}
d := ResponseDistrict{
Agency: district.Agency.GetOr(""),
Manager: district.GeneralMG.GetOr(""),
Phone: district.Phone1.GetOr(""),
Website: district.Website.GetOr(""),
}
if err := render.Render(w, r, d); err != nil {
render.Render(w, r, errRender(err))
}
}
func apiGetDistrictLogo(w http.ResponseWriter, r *http.Request) {
id_str := chi.URLParam(r, "id")
org_id, err := strconv.ParseInt(id_str, 10, 32)
if err != nil {
render.Render(w, r, errRender(fmt.Errorf("%s is not a recognized organization ID: %w", id_str, err)))
return
}
ctx := r.Context()
org, err := models.FindOrganization(ctx, db.PGInstance.BobDB, int32(org_id))
if err != nil {
http.Error(w, "Organization not found", http.StatusNotFound)
return
}
if org.LogoUUID.IsNull() {
http.Error(w, "Logo not found", http.StatusNotFound)
return
}
userfile.ImageFileContentWriteLogo(w, org.LogoUUID.MustGet())
}

View file

@ -21,6 +21,7 @@ func AddRoutes(r chi.Router) {
// Unauthenticated endpoints
r.Get("/district", apiGetDistrict)
r.Get("/district/{id}/logo", apiGetDistrictLogo)
r.Post("/twilio/message", twilioMessagePost)
r.Post("/twilio/status", twilioStatusPost)
r.Post("/twilio/text", twilioTextPost)

@ -1 +1 @@
Subproject commit af786fabcc08ed506a23718a71aa0dd52ce047ac
Subproject commit 09fda12abb8af08b4d95ea519fdda73b5399bf63

View file

@ -72,7 +72,7 @@ func HandleOauthAccessCode(ctx context.Context, user *models.User, code string)
"grant_type": []string{"authorization_code"},
"code": []string{code},
"client_id": []string{config.ClientID},
"redirect_uri": []string{config.RedirectURL()},
"redirect_uri": []string{config.ArcGISOauthRedirectURL()},
}
req, err := http.NewRequest("POST", baseURL, strings.NewReader(form.Encode()))
@ -652,7 +652,7 @@ func refreshRefreshToken(ctx context.Context, oauth *models.OauthToken) error {
form := url.Values{
"grant_type": []string{"exchange_refresh_token"},
"client_id": []string{config.ClientID},
"redirect_uri": []string{config.RedirectURL()},
"redirect_uri": []string{config.ArcGISOauthRedirectURL()},
"refresh_token": []string{oauth.RefreshToken},
}

View file

@ -106,10 +106,10 @@ type emailResponse struct {
func contentEmailSubscriptionConfirmation(report_id string) contentEmailReportConfirmation {
return contentEmailReportConfirmation{
URLLogo: fmt.Sprintf("https://%s/static/img/nidus-logo-no-lettering-64.png", config.URLReport),
URLReportStatus: fmt.Sprintf("https://%s/status/%s", config.URLReport, report_id),
URLReportUnsubscribe: fmt.Sprintf("https://%s/report/%s/unsubscribe", config.URLReport, report_id),
URLViewInBrowser: fmt.Sprintf("https://%s/email/report/%s/subscription-confirmation", config.URLReport, report_id),
URLLogo: config.MakeURLReport("/static/img/nidus-logo-no-lettering-64.png"),
URLReportStatus: config.MakeURLReport("/status/%s", report_id),
URLReportUnsubscribe: config.MakeURLReport("/report/%s/unsubscribe", report_id),
URLViewInBrowser: config.MakeURLReport("/email/report/%s/subscription-confirmation", report_id),
}
}

View file

@ -2,9 +2,7 @@ package config
import (
"fmt"
"net/url"
"os"
"strconv"
"github.com/nyaruka/phonenumbers"
)
@ -13,7 +11,11 @@ var (
Bind string
ClientID string
ClientSecret string
DomainRMO string
DomainNidus string
DomainTegola string
Environment string
FilesDirectoryLogo string
FilesDirectoryPublic string
FilesDirectoryUser string
FieldseekerSchemaDirectory string
@ -23,47 +25,29 @@ var (
ForwardEmailReportUsername string
MapboxToken string
PGDSN string
RMODomain string
RMOPhoneNumber phonenumbers.PhoneNumber
URLReport string
URLSync string
URLTegola string
TwilioAuthToken string
TwilioAccountSID string
TwilioMessagingServiceSID string
)
// Build the ArcGIS authorization URL with PKCE
func BuildArcGISAuthURL(clientID string) string {
baseURL := "https://www.arcgis.com/sharing/rest/oauth2/authorize/"
params := url.Values{}
params.Add("client_id", clientID)
params.Add("redirect_uri", RedirectURL())
params.Add("response_type", "code")
//params.Add("code_challenge", generateCodeChallenge(codeVerifier))
//params.Add("code_challenge_method", "S256")
// See https://developers.arcgis.com/rest/users-groups-and-items/token/
// expiration is defined in minutes
var expiration int
if IsProductionEnvironment() {
// 2 weeks is the maximum allowed
expiration = 20160
} else {
expiration = 20
}
params.Add("expiration", strconv.Itoa(expiration))
return baseURL + "?" + params.Encode()
}
func IsProductionEnvironment() bool {
return Environment == "PRODUCTION"
}
func MakeURLSync(path string) string {
return fmt.Sprintf("https://%s%s", URLSync, path)
func makeURL(domain, path string, args ...interface{}) string {
pattern := "https://" + domain + path
return fmt.Sprintf(pattern, args...)
}
func MakeURLNidus(path string, args ...interface{}) string {
return makeURL(DomainNidus, path, args...)
}
func MakeURLReport(path string, args ...interface{}) string {
return makeURL(DomainRMO, path, args...)
}
func MakeURLTegola(path string, args ...interface{}) string {
return makeURL(DomainTegola, path, args...)
}
func Parse() (err error) {
@ -79,6 +63,18 @@ func Parse() (err error) {
if ClientSecret == "" {
return fmt.Errorf("You must specify a non-empty ARCGIS_CLIENT_SECRET")
}
DomainNidus = os.Getenv("DOMAIN_NIDUS")
if DomainNidus == "" {
return fmt.Errorf("You must specify a non-empty DOMAIN_NIDUS")
}
DomainRMO = os.Getenv("DOMAIN_RMO")
if DomainRMO == "" {
return fmt.Errorf("You must specify a non-empty DOMAIN_RMO")
}
DomainTegola = os.Getenv("DOMAIN_TEGOLA")
if DomainTegola == "" {
return fmt.Errorf("You must specify a non-empty DOMAIN_TEGOLA")
}
Environment = os.Getenv("ENVIRONMENT")
if Environment == "" {
return fmt.Errorf("You must specify a non-empty ENVIRONMENT")
@ -90,6 +86,10 @@ func Parse() (err error) {
if FieldseekerSchemaDirectory == "" {
return fmt.Errorf("You must specify a non-empty FIELDSEEKER_SCHEMA_DIRECTORY")
}
FilesDirectoryLogo = os.Getenv("FILES_DIRECTORY_LOGO")
if FilesDirectoryLogo == "" {
return fmt.Errorf("You must specify a non-empty FILES_DIRECTORY_LOGO")
}
FilesDirectoryPublic = os.Getenv("FILES_DIRECTORY_PUBLIC")
if FilesDirectoryPublic == "" {
return fmt.Errorf("You must specify a non-empty FILES_DIRECTORY_PUBLIC")
@ -122,10 +122,6 @@ func Parse() (err error) {
if PGDSN == "" {
return fmt.Errorf("You must specify a non-empty POSTGRES_DSN")
}
RMODomain = os.Getenv("RMO_DOMAIN")
if RMODomain == "" {
return fmt.Errorf("You must specify a non-empty RMO_DOMAIN")
}
rmo_phone_number := os.Getenv("RMO_PHONE_NUMBER")
if rmo_phone_number == "" {
return fmt.Errorf("You must specify a non-empty RMO_PHONE_NUMBER")
@ -136,18 +132,6 @@ func Parse() (err error) {
}
RMOPhoneNumber = *p
URLReport = os.Getenv("URL_REPORT")
if URLReport == "" {
return fmt.Errorf("You must specify a non-empty URL_REPORT")
}
URLSync = os.Getenv("URL_SYNC")
if URLSync == "" {
return fmt.Errorf("You must specify a non-empty URL_SYNC")
}
URLTegola = os.Getenv("URL_TEGOLA")
if URLTegola == "" {
return fmt.Errorf("You must specify a non-empty URL_TEGOLA")
}
TwilioAccountSID = os.Getenv("TWILIO_ACCOUNT_SID")
if TwilioAccountSID == "" {
return fmt.Errorf("You must specify a non-empty TWILIO_ACCOUNT_SID")
@ -163,6 +147,6 @@ func Parse() (err error) {
return nil
}
func RedirectURL() string {
return MakeURLSync("/arcgis/oauth/callback")
func ArcGISOauthRedirectURL() string {
return MakeURLNidus("/arcgis/oauth/callback")
}

View file

@ -4,6 +4,9 @@ aliases:
up_singular: "ArcgisUser"
down_plural: "arcgisusers"
down_singular: "arcgisuser"
organization:
relationships:
publicreport.pool.pool_organization_id_fkey: "PublicreportPool"
user_:
up_plural: "Users"
up_singular: "User"

View file

@ -78,6 +78,15 @@ var Organizations = Table[
Generated: false,
AutoIncr: false,
},
LogoUUID: column{
Name: "logo_uuid",
DBType: "uuid",
Default: "NULL",
Comment: "",
Nullable: true,
Generated: false,
AutoIncr: false,
},
},
Indexes: organizationIndexes{
OrganizationPkey: index{
@ -172,11 +181,12 @@ type organizationColumns struct {
FieldseekerURL column
ImportDistrictGid column
Website column
LogoUUID column
}
func (c organizationColumns) AsSlice() []column {
return []column{
c.ID, c.Name, c.ArcgisID, c.ArcgisName, c.FieldseekerURL, c.ImportDistrictGid, c.Website,
c.ID, c.Name, c.ArcgisID, c.ArcgisName, c.FieldseekerURL, c.ImportDistrictGid, c.Website, c.LogoUUID,
}
}

View file

@ -258,6 +258,15 @@ var PublicreportNuisances = Table[
Generated: false,
AutoIncr: false,
},
OrganizationID: column{
Name: "organization_id",
DBType: "integer",
Default: "NULL",
Comment: "",
Nullable: true,
Generated: false,
AutoIncr: false,
},
},
Indexes: publicreportNuisanceIndexes{
NuisancePkey: index{
@ -300,7 +309,17 @@ var PublicreportNuisances = Table[
Columns: []string{"id"},
Comment: "",
},
ForeignKeys: publicreportNuisanceForeignKeys{
PublicreportNuisanceNuisanceOrganizationIDFkey: foreignKey{
constraint: constraint{
Name: "publicreport.nuisance.nuisance_organization_id_fkey",
Columns: []string{"organization_id"},
Comment: "",
},
ForeignTable: "organization",
ForeignColumns: []string{"id"},
},
},
Uniques: publicreportNuisanceUniques{
NuisancePublicIDKey: constraint{
Name: "nuisance_public_id_key",
@ -340,11 +359,12 @@ type publicreportNuisanceColumns struct {
Address column
Location column
Status column
OrganizationID column
}
func (c publicreportNuisanceColumns) AsSlice() []column {
return []column{
c.ID, c.AdditionalInfo, c.Created, c.Duration, c.Email, c.InspectionType, c.SourceLocation, c.PreferredDateRange, c.PreferredTime, c.RequestCall, c.Severity, c.SourceContainer, c.SourceDescription, c.SourceRoof, c.SourceStagnant, c.TimeOfDayDay, c.TimeOfDayEarly, c.TimeOfDayEvening, c.TimeOfDayNight, c.PublicID, c.ReporterAddress, c.ReporterEmail, c.ReporterName, c.ReporterPhone, c.Address, c.Location, c.Status,
c.ID, c.AdditionalInfo, c.Created, c.Duration, c.Email, c.InspectionType, c.SourceLocation, c.PreferredDateRange, c.PreferredTime, c.RequestCall, c.Severity, c.SourceContainer, c.SourceDescription, c.SourceRoof, c.SourceStagnant, c.TimeOfDayDay, c.TimeOfDayEarly, c.TimeOfDayEvening, c.TimeOfDayNight, c.PublicID, c.ReporterAddress, c.ReporterEmail, c.ReporterName, c.ReporterPhone, c.Address, c.Location, c.Status, c.OrganizationID,
}
}
@ -359,10 +379,14 @@ func (i publicreportNuisanceIndexes) AsSlice() []index {
}
}
type publicreportNuisanceForeignKeys struct{}
type publicreportNuisanceForeignKeys struct {
PublicreportNuisanceNuisanceOrganizationIDFkey foreignKey
}
func (f publicreportNuisanceForeignKeys) AsSlice() []foreignKey {
return []foreignKey{}
return []foreignKey{
f.PublicreportNuisanceNuisanceOrganizationIDFkey,
}
}
type publicreportNuisanceUniques struct {

View file

@ -285,6 +285,15 @@ var PublicreportPools = Table[
Generated: false,
AutoIncr: false,
},
OrganizationID: column{
Name: "organization_id",
DBType: "integer",
Default: "NULL",
Comment: "",
Nullable: true,
Generated: false,
AutoIncr: false,
},
},
Indexes: publicreportPoolIndexes{
PoolPkey: index{
@ -327,7 +336,17 @@ var PublicreportPools = Table[
Columns: []string{"id"},
Comment: "",
},
ForeignKeys: publicreportPoolForeignKeys{
PublicreportPoolPoolOrganizationIDFkey: foreignKey{
constraint: constraint{
Name: "publicreport.pool.pool_organization_id_fkey",
Columns: []string{"organization_id"},
Comment: "",
},
ForeignTable: "organization",
ForeignColumns: []string{"id"},
},
},
Uniques: publicreportPoolUniques{
PoolPublicIDKey: constraint{
Name: "pool_public_id_key",
@ -370,11 +389,12 @@ type publicreportPoolColumns struct {
ReporterPhone column
Subscribe column
Status column
OrganizationID column
}
func (c publicreportPoolColumns) AsSlice() []column {
return []column{
c.ID, c.AccessComments, c.AccessGate, c.AccessFence, c.AccessLocked, c.AccessDog, c.AccessOther, c.Address, c.AddressCountry, c.AddressPostCode, c.AddressPlace, c.AddressStreet, c.AddressRegion, c.Comments, c.Created, c.H3cell, c.HasAdult, c.HasLarvae, c.HasPupae, c.Location, c.MapZoom, c.OwnerEmail, c.OwnerName, c.OwnerPhone, c.PublicID, c.ReporterEmail, c.ReporterName, c.ReporterPhone, c.Subscribe, c.Status,
c.ID, c.AccessComments, c.AccessGate, c.AccessFence, c.AccessLocked, c.AccessDog, c.AccessOther, c.Address, c.AddressCountry, c.AddressPostCode, c.AddressPlace, c.AddressStreet, c.AddressRegion, c.Comments, c.Created, c.H3cell, c.HasAdult, c.HasLarvae, c.HasPupae, c.Location, c.MapZoom, c.OwnerEmail, c.OwnerName, c.OwnerPhone, c.PublicID, c.ReporterEmail, c.ReporterName, c.ReporterPhone, c.Subscribe, c.Status, c.OrganizationID,
}
}
@ -389,10 +409,14 @@ func (i publicreportPoolIndexes) AsSlice() []index {
}
}
type publicreportPoolForeignKeys struct{}
type publicreportPoolForeignKeys struct {
PublicreportPoolPoolOrganizationIDFkey foreignKey
}
func (f publicreportPoolForeignKeys) AsSlice() []foreignKey {
return []foreignKey{}
return []foreignKey{
f.PublicreportPoolPoolOrganizationIDFkey,
}
}
type publicreportPoolUniques struct {

View file

@ -105,6 +105,15 @@ var PublicreportQuicks = Table[
Generated: false,
AutoIncr: false,
},
OrganizationID: column{
Name: "organization_id",
DBType: "integer",
Default: "NULL",
Comment: "",
Nullable: true,
Generated: false,
AutoIncr: false,
},
},
Indexes: publicreportQuickIndexes{
QuickPkey: index{
@ -147,7 +156,17 @@ var PublicreportQuicks = Table[
Columns: []string{"id"},
Comment: "",
},
ForeignKeys: publicreportQuickForeignKeys{
PublicreportQuickQuickOrganizationIDFkey: foreignKey{
constraint: constraint{
Name: "publicreport.quick.quick_organization_id_fkey",
Columns: []string{"organization_id"},
Comment: "",
},
ForeignTable: "organization",
ForeignColumns: []string{"id"},
},
},
Uniques: publicreportQuickUniques{
QuickPublicIDKey: constraint{
Name: "quick_public_id_key",
@ -160,21 +179,22 @@ var PublicreportQuicks = Table[
}
type publicreportQuickColumns struct {
ID column
Created column
Comments column
Location column
H3cell column
PublicID column
ReporterEmail column
ReporterPhone column
Address column
Status column
ID column
Created column
Comments column
Location column
H3cell column
PublicID column
ReporterEmail column
ReporterPhone column
Address column
Status column
OrganizationID column
}
func (c publicreportQuickColumns) AsSlice() []column {
return []column{
c.ID, c.Created, c.Comments, c.Location, c.H3cell, c.PublicID, c.ReporterEmail, c.ReporterPhone, c.Address, c.Status,
c.ID, c.Created, c.Comments, c.Location, c.H3cell, c.PublicID, c.ReporterEmail, c.ReporterPhone, c.Address, c.Status, c.OrganizationID,
}
}
@ -189,10 +209,14 @@ func (i publicreportQuickIndexes) AsSlice() []index {
}
}
type publicreportQuickForeignKeys struct{}
type publicreportQuickForeignKeys struct {
PublicreportQuickQuickOrganizationIDFkey foreignKey
}
func (f publicreportQuickForeignKeys) AsSlice() []foreignKey {
return []foreignKey{}
return []foreignKey{
f.PublicreportQuickQuickOrganizationIDFkey,
}
}
type publicreportQuickUniques struct {

View file

@ -240,6 +240,9 @@ var (
organizationRelNoteAudiosCtx = newContextual[bool]("note_audio.organization.note_audio.note_audio_organization_id_fkey")
organizationRelNoteImagesCtx = newContextual[bool]("note_image.organization.note_image.note_image_organization_id_fkey")
organizationRelImportDistrictGidDistrictCtx = newContextual[bool]("import.district.organization.organization.organization_import_district_gid_fkey")
organizationRelNuisancesCtx = newContextual[bool]("organization.publicreport.nuisance.publicreport.nuisance.nuisance_organization_id_fkey")
organizationRelPublicreportPoolCtx = newContextual[bool]("organization.publicreport.pool.publicreport.pool.pool_organization_id_fkey")
organizationRelQuicksCtx = newContextual[bool]("organization.publicreport.quick.publicreport.quick.quick_organization_id_fkey")
organizationRelUserCtx = newContextual[bool]("organization.user_.user_.user__organization_id_fkey")
// Relationship Contexts for publicreport.image
@ -254,9 +257,11 @@ var (
// Relationship Contexts for publicreport.nuisance
publicreportNuisanceWithParentsCascadingCtx = newContextual[bool]("publicreportNuisanceWithParentsCascading")
publicreportNuisanceRelOrganizationCtx = newContextual[bool]("organization.publicreport.nuisance.publicreport.nuisance.nuisance_organization_id_fkey")
// Relationship Contexts for publicreport.pool
publicreportPoolWithParentsCascadingCtx = newContextual[bool]("publicreportPoolWithParentsCascading")
publicreportPoolRelOrganizationCtx = newContextual[bool]("organization.publicreport.pool.publicreport.pool.pool_organization_id_fkey")
publicreportPoolRelImagesCtx = newContextual[bool]("publicreport.image.publicreport.pool.publicreport.pool_image.pool_image_image_id_fkeypublicreport.pool_image.pool_image_pool_id_fkey")
// Relationship Contexts for publicreport.pool_image
@ -266,6 +271,7 @@ var (
// Relationship Contexts for publicreport.quick
publicreportQuickWithParentsCascadingCtx = newContextual[bool]("publicreportQuickWithParentsCascading")
publicreportQuickRelOrganizationCtx = newContextual[bool]("organization.publicreport.quick.publicreport.quick.quick_organization_id_fkey")
publicreportQuickRelImagesCtx = newContextual[bool]("publicreport.image.publicreport.quick.publicreport.quick_image.quick_image_image_id_fkeypublicreport.quick_image.quick_image_quick_id_fkey")
// Relationship Contexts for publicreport.quick_image

View file

@ -2550,6 +2550,7 @@ func (f *Factory) FromExistingOrganization(m *models.Organization) *Organization
o.FieldseekerURL = func() null.Val[string] { return m.FieldseekerURL }
o.ImportDistrictGid = func() null.Val[int32] { return m.ImportDistrictGid }
o.Website = func() null.Val[string] { return m.Website }
o.LogoUUID = func() null.Val[uuid.UUID] { return m.LogoUUID }
ctx := context.Background()
if len(m.R.Containerrelates) > 0 {
@ -2648,6 +2649,15 @@ func (f *Factory) FromExistingOrganization(m *models.Organization) *Organization
if m.R.ImportDistrictGidDistrict != nil {
OrganizationMods.WithExistingImportDistrictGidDistrict(m.R.ImportDistrictGidDistrict).Apply(ctx, o)
}
if len(m.R.Nuisances) > 0 {
OrganizationMods.AddExistingNuisances(m.R.Nuisances...).Apply(ctx, o)
}
if len(m.R.PublicreportPool) > 0 {
OrganizationMods.AddExistingPublicreportPool(m.R.PublicreportPool...).Apply(ctx, o)
}
if len(m.R.Quicks) > 0 {
OrganizationMods.AddExistingQuicks(m.R.Quicks...).Apply(ctx, o)
}
if len(m.R.User) > 0 {
OrganizationMods.AddExistingUser(m.R.User...).Apply(ctx, o)
}
@ -2775,6 +2785,12 @@ func (f *Factory) FromExistingPublicreportNuisance(m *models.PublicreportNuisanc
o.Address = func() string { return m.Address }
o.Location = func() null.Val[string] { return m.Location }
o.Status = func() enums.PublicreportReportstatustype { return m.Status }
o.OrganizationID = func() null.Val[int32] { return m.OrganizationID }
ctx := context.Background()
if m.R.Organization != nil {
PublicreportNuisanceMods.WithExistingOrganization(m.R.Organization).Apply(ctx, o)
}
return o
}
@ -2828,8 +2844,12 @@ func (f *Factory) FromExistingPublicreportPool(m *models.PublicreportPool) *Publ
o.ReporterPhone = func() string { return m.ReporterPhone }
o.Subscribe = func() bool { return m.Subscribe }
o.Status = func() enums.PublicreportReportstatustype { return m.Status }
o.OrganizationID = func() null.Val[int32] { return m.OrganizationID }
ctx := context.Background()
if m.R.Organization != nil {
PublicreportPoolMods.WithExistingOrganization(m.R.Organization).Apply(ctx, o)
}
if len(m.R.Images) > 0 {
PublicreportPoolMods.AddExistingImages(m.R.Images...).Apply(ctx, o)
}
@ -2899,8 +2919,12 @@ func (f *Factory) FromExistingPublicreportQuick(m *models.PublicreportQuick) *Pu
o.ReporterPhone = func() string { return m.ReporterPhone }
o.Address = func() string { return m.Address }
o.Status = func() enums.PublicreportReportstatustype { return m.Status }
o.OrganizationID = func() null.Val[int32] { return m.OrganizationID }
ctx := context.Background()
if m.R.Organization != nil {
PublicreportQuickMods.WithExistingOrganization(m.R.Organization).Apply(ctx, o)
}
if len(m.R.Images) > 0 {
PublicreportQuickMods.AddExistingImages(m.R.Images...).Apply(ctx, o)
}

View file

@ -11,6 +11,7 @@ import (
"github.com/aarondl/opt/null"
"github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull"
"github.com/google/uuid"
"github.com/jaswdr/faker/v2"
"github.com/stephenafamo/bob"
)
@ -43,6 +44,7 @@ type OrganizationTemplate struct {
FieldseekerURL func() null.Val[string]
ImportDistrictGid func() null.Val[int32]
Website func() null.Val[string]
LogoUUID func() null.Val[uuid.UUID]
r organizationR
f *Factory
@ -83,6 +85,9 @@ type organizationR struct {
NoteAudios []*organizationRNoteAudiosR
NoteImages []*organizationRNoteImagesR
ImportDistrictGidDistrict *organizationRImportDistrictGidDistrictR
Nuisances []*organizationRNuisancesR
PublicreportPool []*organizationRPublicreportPoolR
Quicks []*organizationRQuicksR
User []*organizationRUserR
}
@ -213,6 +218,18 @@ type organizationRNoteImagesR struct {
type organizationRImportDistrictGidDistrictR struct {
o *ImportDistrictTemplate
}
type organizationRNuisancesR struct {
number int
o *PublicreportNuisanceTemplate
}
type organizationRPublicreportPoolR struct {
number int
o *PublicreportPoolTemplate
}
type organizationRQuicksR struct {
number int
o *PublicreportQuickTemplate
}
type organizationRUserR struct {
number int
o *UserTemplate
@ -638,6 +655,45 @@ func (t OrganizationTemplate) setModelRels(o *models.Organization) {
o.R.ImportDistrictGidDistrict = rel
}
if t.r.Nuisances != nil {
rel := models.PublicreportNuisanceSlice{}
for _, r := range t.r.Nuisances {
related := r.o.BuildMany(r.number)
for _, rel := range related {
rel.OrganizationID = null.From(o.ID) // h2
rel.R.Organization = o
}
rel = append(rel, related...)
}
o.R.Nuisances = rel
}
if t.r.PublicreportPool != nil {
rel := models.PublicreportPoolSlice{}
for _, r := range t.r.PublicreportPool {
related := r.o.BuildMany(r.number)
for _, rel := range related {
rel.OrganizationID = null.From(o.ID) // h2
rel.R.Organization = o
}
rel = append(rel, related...)
}
o.R.PublicreportPool = rel
}
if t.r.Quicks != nil {
rel := models.PublicreportQuickSlice{}
for _, r := range t.r.Quicks {
related := r.o.BuildMany(r.number)
for _, rel := range related {
rel.OrganizationID = null.From(o.ID) // h2
rel.R.Organization = o
}
rel = append(rel, related...)
}
o.R.Quicks = rel
}
if t.r.User != nil {
rel := models.UserSlice{}
for _, r := range t.r.User {
@ -685,6 +741,10 @@ func (o OrganizationTemplate) BuildSetter() *models.OrganizationSetter {
val := o.Website()
m.Website = omitnull.FromNull(val)
}
if o.LogoUUID != nil {
val := o.LogoUUID()
m.LogoUUID = omitnull.FromNull(val)
}
return m
}
@ -728,6 +788,9 @@ func (o OrganizationTemplate) Build() *models.Organization {
if o.Website != nil {
m.Website = o.Website()
}
if o.LogoUUID != nil {
m.LogoUUID = o.LogoUUID()
}
o.setModelRels(m)
@ -1399,6 +1462,66 @@ func (o *OrganizationTemplate) insertOptRels(ctx context.Context, exec bob.Execu
}
isNuisancesDone, _ := organizationRelNuisancesCtx.Value(ctx)
if !isNuisancesDone && o.r.Nuisances != nil {
ctx = organizationRelNuisancesCtx.WithValue(ctx, true)
for _, r := range o.r.Nuisances {
if r.o.alreadyPersisted {
m.R.Nuisances = append(m.R.Nuisances, r.o.Build())
} else {
rel32, err := r.o.CreateMany(ctx, exec, r.number)
if err != nil {
return err
}
err = m.AttachNuisances(ctx, exec, rel32...)
if err != nil {
return err
}
}
}
}
isPublicreportPoolDone, _ := organizationRelPublicreportPoolCtx.Value(ctx)
if !isPublicreportPoolDone && o.r.PublicreportPool != nil {
ctx = organizationRelPublicreportPoolCtx.WithValue(ctx, true)
for _, r := range o.r.PublicreportPool {
if r.o.alreadyPersisted {
m.R.PublicreportPool = append(m.R.PublicreportPool, r.o.Build())
} else {
rel33, err := r.o.CreateMany(ctx, exec, r.number)
if err != nil {
return err
}
err = m.AttachPublicreportPool(ctx, exec, rel33...)
if err != nil {
return err
}
}
}
}
isQuicksDone, _ := organizationRelQuicksCtx.Value(ctx)
if !isQuicksDone && o.r.Quicks != nil {
ctx = organizationRelQuicksCtx.WithValue(ctx, true)
for _, r := range o.r.Quicks {
if r.o.alreadyPersisted {
m.R.Quicks = append(m.R.Quicks, r.o.Build())
} else {
rel34, err := r.o.CreateMany(ctx, exec, r.number)
if err != nil {
return err
}
err = m.AttachQuicks(ctx, exec, rel34...)
if err != nil {
return err
}
}
}
}
isUserDone, _ := organizationRelUserCtx.Value(ctx)
if !isUserDone && o.r.User != nil {
ctx = organizationRelUserCtx.WithValue(ctx, true)
@ -1406,12 +1529,12 @@ func (o *OrganizationTemplate) insertOptRels(ctx context.Context, exec bob.Execu
if r.o.alreadyPersisted {
m.R.User = append(m.R.User, r.o.Build())
} else {
rel32, err := r.o.CreateMany(ctx, exec, r.number)
rel35, err := r.o.CreateMany(ctx, exec, r.number)
if err != nil {
return err
}
err = m.AttachUser(ctx, exec, rel32...)
err = m.AttachUser(ctx, exec, rel35...)
if err != nil {
return err
}
@ -1518,6 +1641,7 @@ func (m organizationMods) RandomizeAllColumns(f *faker.Faker) OrganizationMod {
OrganizationMods.RandomFieldseekerURL(f),
OrganizationMods.RandomImportDistrictGid(f),
OrganizationMods.RandomWebsite(f),
OrganizationMods.RandomLogoUUID(f),
}
}
@ -1848,6 +1972,59 @@ func (m organizationMods) RandomWebsiteNotNull(f *faker.Faker) OrganizationMod {
})
}
// Set the model columns to this value
func (m organizationMods) LogoUUID(val null.Val[uuid.UUID]) OrganizationMod {
return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) {
o.LogoUUID = func() null.Val[uuid.UUID] { return val }
})
}
// Set the Column from the function
func (m organizationMods) LogoUUIDFunc(f func() null.Val[uuid.UUID]) OrganizationMod {
return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) {
o.LogoUUID = f
})
}
// Clear any values for the column
func (m organizationMods) UnsetLogoUUID() OrganizationMod {
return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) {
o.LogoUUID = nil
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is sometimes null
func (m organizationMods) RandomLogoUUID(f *faker.Faker) OrganizationMod {
return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) {
o.LogoUUID = func() null.Val[uuid.UUID] {
if f == nil {
f = &defaultFaker
}
val := random_uuid_UUID(f)
return null.From(val)
}
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is never null
func (m organizationMods) RandomLogoUUIDNotNull(f *faker.Faker) OrganizationMod {
return OrganizationModFunc(func(_ context.Context, o *OrganizationTemplate) {
o.LogoUUID = func() null.Val[uuid.UUID] {
if f == nil {
f = &defaultFaker
}
val := random_uuid_UUID(f)
return null.From(val)
}
})
}
func (m organizationMods) WithParentsCascading() OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
if isDone, _ := organizationWithParentsCascadingCtx.Value(ctx); isDone {
@ -3380,6 +3557,150 @@ func (m organizationMods) WithoutNoteImages() OrganizationMod {
})
}
func (m organizationMods) WithNuisances(number int, related *PublicreportNuisanceTemplate) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
o.r.Nuisances = []*organizationRNuisancesR{{
number: number,
o: related,
}}
})
}
func (m organizationMods) WithNewNuisances(number int, mods ...PublicreportNuisanceMod) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
related := o.f.NewPublicreportNuisanceWithContext(ctx, mods...)
m.WithNuisances(number, related).Apply(ctx, o)
})
}
func (m organizationMods) AddNuisances(number int, related *PublicreportNuisanceTemplate) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
o.r.Nuisances = append(o.r.Nuisances, &organizationRNuisancesR{
number: number,
o: related,
})
})
}
func (m organizationMods) AddNewNuisances(number int, mods ...PublicreportNuisanceMod) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
related := o.f.NewPublicreportNuisanceWithContext(ctx, mods...)
m.AddNuisances(number, related).Apply(ctx, o)
})
}
func (m organizationMods) AddExistingNuisances(existingModels ...*models.PublicreportNuisance) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
for _, em := range existingModels {
o.r.Nuisances = append(o.r.Nuisances, &organizationRNuisancesR{
o: o.f.FromExistingPublicreportNuisance(em),
})
}
})
}
func (m organizationMods) WithoutNuisances() OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
o.r.Nuisances = nil
})
}
func (m organizationMods) WithPublicreportPool(number int, related *PublicreportPoolTemplate) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
o.r.PublicreportPool = []*organizationRPublicreportPoolR{{
number: number,
o: related,
}}
})
}
func (m organizationMods) WithNewPublicreportPool(number int, mods ...PublicreportPoolMod) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
related := o.f.NewPublicreportPoolWithContext(ctx, mods...)
m.WithPublicreportPool(number, related).Apply(ctx, o)
})
}
func (m organizationMods) AddPublicreportPool(number int, related *PublicreportPoolTemplate) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
o.r.PublicreportPool = append(o.r.PublicreportPool, &organizationRPublicreportPoolR{
number: number,
o: related,
})
})
}
func (m organizationMods) AddNewPublicreportPool(number int, mods ...PublicreportPoolMod) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
related := o.f.NewPublicreportPoolWithContext(ctx, mods...)
m.AddPublicreportPool(number, related).Apply(ctx, o)
})
}
func (m organizationMods) AddExistingPublicreportPool(existingModels ...*models.PublicreportPool) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
for _, em := range existingModels {
o.r.PublicreportPool = append(o.r.PublicreportPool, &organizationRPublicreportPoolR{
o: o.f.FromExistingPublicreportPool(em),
})
}
})
}
func (m organizationMods) WithoutPublicreportPool() OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
o.r.PublicreportPool = nil
})
}
func (m organizationMods) WithQuicks(number int, related *PublicreportQuickTemplate) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
o.r.Quicks = []*organizationRQuicksR{{
number: number,
o: related,
}}
})
}
func (m organizationMods) WithNewQuicks(number int, mods ...PublicreportQuickMod) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
related := o.f.NewPublicreportQuickWithContext(ctx, mods...)
m.WithQuicks(number, related).Apply(ctx, o)
})
}
func (m organizationMods) AddQuicks(number int, related *PublicreportQuickTemplate) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
o.r.Quicks = append(o.r.Quicks, &organizationRQuicksR{
number: number,
o: related,
})
})
}
func (m organizationMods) AddNewQuicks(number int, mods ...PublicreportQuickMod) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
related := o.f.NewPublicreportQuickWithContext(ctx, mods...)
m.AddQuicks(number, related).Apply(ctx, o)
})
}
func (m organizationMods) AddExistingQuicks(existingModels ...*models.PublicreportQuick) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
for _, em := range existingModels {
o.r.Quicks = append(o.r.Quicks, &organizationRQuicksR{
o: o.f.FromExistingPublicreportQuick(em),
})
}
})
}
func (m organizationMods) WithoutQuicks() OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
o.r.Quicks = nil
})
}
func (m organizationMods) WithUser(number int, related *UserTemplate) OrganizationMod {
return OrganizationModFunc(func(ctx context.Context, o *OrganizationTemplate) {
o.r.User = []*organizationRUserR{{

View file

@ -65,12 +65,22 @@ type PublicreportNuisanceTemplate struct {
Address func() string
Location func() null.Val[string]
Status func() enums.PublicreportReportstatustype
OrganizationID func() null.Val[int32]
r publicreportNuisanceR
f *Factory
alreadyPersisted bool
}
type publicreportNuisanceR struct {
Organization *publicreportNuisanceROrganizationR
}
type publicreportNuisanceROrganizationR struct {
o *OrganizationTemplate
}
// Apply mods to the PublicreportNuisanceTemplate
func (o *PublicreportNuisanceTemplate) Apply(ctx context.Context, mods ...PublicreportNuisanceMod) {
for _, mod := range mods {
@ -80,7 +90,14 @@ func (o *PublicreportNuisanceTemplate) Apply(ctx context.Context, mods ...Public
// setModelRels creates and sets the relationships on *models.PublicreportNuisance
// according to the relationships in the template. Nothing is inserted into the db
func (t PublicreportNuisanceTemplate) setModelRels(o *models.PublicreportNuisance) {}
func (t PublicreportNuisanceTemplate) setModelRels(o *models.PublicreportNuisance) {
if t.r.Organization != nil {
rel := t.r.Organization.o.Build()
rel.R.Nuisances = append(rel.R.Nuisances, o)
o.OrganizationID = null.From(rel.ID) // h2
o.R.Organization = rel
}
}
// BuildSetter returns an *models.PublicreportNuisanceSetter
// this does nothing with the relationship templates
@ -195,6 +212,10 @@ func (o PublicreportNuisanceTemplate) BuildSetter() *models.PublicreportNuisance
val := o.Status()
m.Status = omit.From(val)
}
if o.OrganizationID != nil {
val := o.OrganizationID()
m.OrganizationID = omitnull.FromNull(val)
}
return m
}
@ -298,6 +319,9 @@ func (o PublicreportNuisanceTemplate) Build() *models.PublicreportNuisance {
if o.Status != nil {
m.Status = o.Status()
}
if o.OrganizationID != nil {
m.OrganizationID = o.OrganizationID()
}
o.setModelRels(m)
@ -426,6 +450,25 @@ func ensureCreatablePublicreportNuisance(m *models.PublicreportNuisanceSetter) {
func (o *PublicreportNuisanceTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m *models.PublicreportNuisance) error {
var err error
isOrganizationDone, _ := publicreportNuisanceRelOrganizationCtx.Value(ctx)
if !isOrganizationDone && o.r.Organization != nil {
ctx = publicreportNuisanceRelOrganizationCtx.WithValue(ctx, true)
if o.r.Organization.o.alreadyPersisted {
m.R.Organization = o.r.Organization.o.Build()
} else {
var rel0 *models.Organization
rel0, err = o.r.Organization.o.Create(ctx, exec)
if err != nil {
return err
}
err = m.AttachOrganization(ctx, exec, rel0)
if err != nil {
return err
}
}
}
return err
}
@ -545,6 +588,7 @@ func (m publicreportNuisanceMods) RandomizeAllColumns(f *faker.Faker) Publicrepo
PublicreportNuisanceMods.RandomAddress(f),
PublicreportNuisanceMods.RandomLocation(f),
PublicreportNuisanceMods.RandomStatus(f),
PublicreportNuisanceMods.RandomOrganizationID(f),
}
}
@ -1407,11 +1451,99 @@ func (m publicreportNuisanceMods) RandomStatus(f *faker.Faker) PublicreportNuisa
})
}
// Set the model columns to this value
func (m publicreportNuisanceMods) OrganizationID(val null.Val[int32]) PublicreportNuisanceMod {
return PublicreportNuisanceModFunc(func(_ context.Context, o *PublicreportNuisanceTemplate) {
o.OrganizationID = func() null.Val[int32] { return val }
})
}
// Set the Column from the function
func (m publicreportNuisanceMods) OrganizationIDFunc(f func() null.Val[int32]) PublicreportNuisanceMod {
return PublicreportNuisanceModFunc(func(_ context.Context, o *PublicreportNuisanceTemplate) {
o.OrganizationID = f
})
}
// Clear any values for the column
func (m publicreportNuisanceMods) UnsetOrganizationID() PublicreportNuisanceMod {
return PublicreportNuisanceModFunc(func(_ context.Context, o *PublicreportNuisanceTemplate) {
o.OrganizationID = nil
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is sometimes null
func (m publicreportNuisanceMods) RandomOrganizationID(f *faker.Faker) PublicreportNuisanceMod {
return PublicreportNuisanceModFunc(func(_ context.Context, o *PublicreportNuisanceTemplate) {
o.OrganizationID = func() null.Val[int32] {
if f == nil {
f = &defaultFaker
}
val := random_int32(f)
return null.From(val)
}
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is never null
func (m publicreportNuisanceMods) RandomOrganizationIDNotNull(f *faker.Faker) PublicreportNuisanceMod {
return PublicreportNuisanceModFunc(func(_ context.Context, o *PublicreportNuisanceTemplate) {
o.OrganizationID = func() null.Val[int32] {
if f == nil {
f = &defaultFaker
}
val := random_int32(f)
return null.From(val)
}
})
}
func (m publicreportNuisanceMods) WithParentsCascading() PublicreportNuisanceMod {
return PublicreportNuisanceModFunc(func(ctx context.Context, o *PublicreportNuisanceTemplate) {
if isDone, _ := publicreportNuisanceWithParentsCascadingCtx.Value(ctx); isDone {
return
}
ctx = publicreportNuisanceWithParentsCascadingCtx.WithValue(ctx, true)
{
related := o.f.NewOrganizationWithContext(ctx, OrganizationMods.WithParentsCascading())
m.WithOrganization(related).Apply(ctx, o)
}
})
}
func (m publicreportNuisanceMods) WithOrganization(rel *OrganizationTemplate) PublicreportNuisanceMod {
return PublicreportNuisanceModFunc(func(ctx context.Context, o *PublicreportNuisanceTemplate) {
o.r.Organization = &publicreportNuisanceROrganizationR{
o: rel,
}
})
}
func (m publicreportNuisanceMods) WithNewOrganization(mods ...OrganizationMod) PublicreportNuisanceMod {
return PublicreportNuisanceModFunc(func(ctx context.Context, o *PublicreportNuisanceTemplate) {
related := o.f.NewOrganizationWithContext(ctx, mods...)
m.WithOrganization(related).Apply(ctx, o)
})
}
func (m publicreportNuisanceMods) WithExistingOrganization(em *models.Organization) PublicreportNuisanceMod {
return PublicreportNuisanceModFunc(func(ctx context.Context, o *PublicreportNuisanceTemplate) {
o.r.Organization = &publicreportNuisanceROrganizationR{
o: o.f.FromExistingOrganization(em),
}
})
}
func (m publicreportNuisanceMods) WithoutOrganization() PublicreportNuisanceMod {
return PublicreportNuisanceModFunc(func(ctx context.Context, o *PublicreportNuisanceTemplate) {
o.r.Organization = nil
})
}

View file

@ -68,6 +68,7 @@ type PublicreportPoolTemplate struct {
ReporterPhone func() string
Subscribe func() bool
Status func() enums.PublicreportReportstatustype
OrganizationID func() null.Val[int32]
r publicreportPoolR
f *Factory
@ -76,9 +77,13 @@ type PublicreportPoolTemplate struct {
}
type publicreportPoolR struct {
Images []*publicreportPoolRImagesR
Organization *publicreportPoolROrganizationR
Images []*publicreportPoolRImagesR
}
type publicreportPoolROrganizationR struct {
o *OrganizationTemplate
}
type publicreportPoolRImagesR struct {
number int
o *PublicreportImageTemplate
@ -94,6 +99,13 @@ func (o *PublicreportPoolTemplate) Apply(ctx context.Context, mods ...Publicrepo
// setModelRels creates and sets the relationships on *models.PublicreportPool
// according to the relationships in the template. Nothing is inserted into the db
func (t PublicreportPoolTemplate) setModelRels(o *models.PublicreportPool) {
if t.r.Organization != nil {
rel := t.r.Organization.o.Build()
rel.R.PublicreportPool = append(rel.R.PublicreportPool, o)
o.OrganizationID = null.From(rel.ID) // h2
o.R.Organization = rel
}
if t.r.Images != nil {
rel := models.PublicreportImageSlice{}
for _, r := range t.r.Images {
@ -232,6 +244,10 @@ func (o PublicreportPoolTemplate) BuildSetter() *models.PublicreportPoolSetter {
val := o.Status()
m.Status = omit.From(val)
}
if o.OrganizationID != nil {
val := o.OrganizationID()
m.OrganizationID = omitnull.FromNull(val)
}
return m
}
@ -344,6 +360,9 @@ func (o PublicreportPoolTemplate) Build() *models.PublicreportPool {
if o.Status != nil {
m.Status = o.Status()
}
if o.OrganizationID != nil {
m.OrganizationID = o.OrganizationID()
}
o.setModelRels(m)
@ -480,6 +499,25 @@ func ensureCreatablePublicreportPool(m *models.PublicreportPoolSetter) {
func (o *PublicreportPoolTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m *models.PublicreportPool) error {
var err error
isOrganizationDone, _ := publicreportPoolRelOrganizationCtx.Value(ctx)
if !isOrganizationDone && o.r.Organization != nil {
ctx = publicreportPoolRelOrganizationCtx.WithValue(ctx, true)
if o.r.Organization.o.alreadyPersisted {
m.R.Organization = o.r.Organization.o.Build()
} else {
var rel0 *models.Organization
rel0, err = o.r.Organization.o.Create(ctx, exec)
if err != nil {
return err
}
err = m.AttachOrganization(ctx, exec, rel0)
if err != nil {
return err
}
}
}
isImagesDone, _ := publicreportPoolRelImagesCtx.Value(ctx)
if !isImagesDone && o.r.Images != nil {
ctx = publicreportPoolRelImagesCtx.WithValue(ctx, true)
@ -487,12 +525,12 @@ func (o *PublicreportPoolTemplate) insertOptRels(ctx context.Context, exec bob.E
if r.o.alreadyPersisted {
m.R.Images = append(m.R.Images, r.o.Build())
} else {
rel0, err := r.o.CreateMany(ctx, exec, r.number)
rel1, err := r.o.CreateMany(ctx, exec, r.number)
if err != nil {
return err
}
err = m.AttachImages(ctx, exec, rel0...)
err = m.AttachImages(ctx, exec, rel1...)
if err != nil {
return err
}
@ -622,6 +660,7 @@ func (m publicreportPoolMods) RandomizeAllColumns(f *faker.Faker) PublicreportPo
PublicreportPoolMods.RandomReporterPhone(f),
PublicreportPoolMods.RandomSubscribe(f),
PublicreportPoolMods.RandomStatus(f),
PublicreportPoolMods.RandomOrganizationID(f),
}
}
@ -1599,12 +1638,100 @@ func (m publicreportPoolMods) RandomStatus(f *faker.Faker) PublicreportPoolMod {
})
}
// Set the model columns to this value
func (m publicreportPoolMods) OrganizationID(val null.Val[int32]) PublicreportPoolMod {
return PublicreportPoolModFunc(func(_ context.Context, o *PublicreportPoolTemplate) {
o.OrganizationID = func() null.Val[int32] { return val }
})
}
// Set the Column from the function
func (m publicreportPoolMods) OrganizationIDFunc(f func() null.Val[int32]) PublicreportPoolMod {
return PublicreportPoolModFunc(func(_ context.Context, o *PublicreportPoolTemplate) {
o.OrganizationID = f
})
}
// Clear any values for the column
func (m publicreportPoolMods) UnsetOrganizationID() PublicreportPoolMod {
return PublicreportPoolModFunc(func(_ context.Context, o *PublicreportPoolTemplate) {
o.OrganizationID = nil
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is sometimes null
func (m publicreportPoolMods) RandomOrganizationID(f *faker.Faker) PublicreportPoolMod {
return PublicreportPoolModFunc(func(_ context.Context, o *PublicreportPoolTemplate) {
o.OrganizationID = func() null.Val[int32] {
if f == nil {
f = &defaultFaker
}
val := random_int32(f)
return null.From(val)
}
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is never null
func (m publicreportPoolMods) RandomOrganizationIDNotNull(f *faker.Faker) PublicreportPoolMod {
return PublicreportPoolModFunc(func(_ context.Context, o *PublicreportPoolTemplate) {
o.OrganizationID = func() null.Val[int32] {
if f == nil {
f = &defaultFaker
}
val := random_int32(f)
return null.From(val)
}
})
}
func (m publicreportPoolMods) WithParentsCascading() PublicreportPoolMod {
return PublicreportPoolModFunc(func(ctx context.Context, o *PublicreportPoolTemplate) {
if isDone, _ := publicreportPoolWithParentsCascadingCtx.Value(ctx); isDone {
return
}
ctx = publicreportPoolWithParentsCascadingCtx.WithValue(ctx, true)
{
related := o.f.NewOrganizationWithContext(ctx, OrganizationMods.WithParentsCascading())
m.WithOrganization(related).Apply(ctx, o)
}
})
}
func (m publicreportPoolMods) WithOrganization(rel *OrganizationTemplate) PublicreportPoolMod {
return PublicreportPoolModFunc(func(ctx context.Context, o *PublicreportPoolTemplate) {
o.r.Organization = &publicreportPoolROrganizationR{
o: rel,
}
})
}
func (m publicreportPoolMods) WithNewOrganization(mods ...OrganizationMod) PublicreportPoolMod {
return PublicreportPoolModFunc(func(ctx context.Context, o *PublicreportPoolTemplate) {
related := o.f.NewOrganizationWithContext(ctx, mods...)
m.WithOrganization(related).Apply(ctx, o)
})
}
func (m publicreportPoolMods) WithExistingOrganization(em *models.Organization) PublicreportPoolMod {
return PublicreportPoolModFunc(func(ctx context.Context, o *PublicreportPoolTemplate) {
o.r.Organization = &publicreportPoolROrganizationR{
o: o.f.FromExistingOrganization(em),
}
})
}
func (m publicreportPoolMods) WithoutOrganization() PublicreportPoolMod {
return PublicreportPoolModFunc(func(ctx context.Context, o *PublicreportPoolTemplate) {
o.r.Organization = nil
})
}

View file

@ -38,16 +38,17 @@ func (mods PublicreportQuickModSlice) Apply(ctx context.Context, n *Publicreport
// PublicreportQuickTemplate is an object representing the database table.
// all columns are optional and should be set by mods
type PublicreportQuickTemplate struct {
ID func() int32
Created func() time.Time
Comments func() string
Location func() null.Val[string]
H3cell func() null.Val[string]
PublicID func() string
ReporterEmail func() string
ReporterPhone func() string
Address func() string
Status func() enums.PublicreportReportstatustype
ID func() int32
Created func() time.Time
Comments func() string
Location func() null.Val[string]
H3cell func() null.Val[string]
PublicID func() string
ReporterEmail func() string
ReporterPhone func() string
Address func() string
Status func() enums.PublicreportReportstatustype
OrganizationID func() null.Val[int32]
r publicreportQuickR
f *Factory
@ -56,9 +57,13 @@ type PublicreportQuickTemplate struct {
}
type publicreportQuickR struct {
Images []*publicreportQuickRImagesR
Organization *publicreportQuickROrganizationR
Images []*publicreportQuickRImagesR
}
type publicreportQuickROrganizationR struct {
o *OrganizationTemplate
}
type publicreportQuickRImagesR struct {
number int
o *PublicreportImageTemplate
@ -74,6 +79,13 @@ func (o *PublicreportQuickTemplate) Apply(ctx context.Context, mods ...Publicrep
// setModelRels creates and sets the relationships on *models.PublicreportQuick
// according to the relationships in the template. Nothing is inserted into the db
func (t PublicreportQuickTemplate) setModelRels(o *models.PublicreportQuick) {
if t.r.Organization != nil {
rel := t.r.Organization.o.Build()
rel.R.Quicks = append(rel.R.Quicks, o)
o.OrganizationID = null.From(rel.ID) // h2
o.R.Organization = rel
}
if t.r.Images != nil {
rel := models.PublicreportImageSlice{}
for _, r := range t.r.Images {
@ -132,6 +144,10 @@ func (o PublicreportQuickTemplate) BuildSetter() *models.PublicreportQuickSetter
val := o.Status()
m.Status = omit.From(val)
}
if o.OrganizationID != nil {
val := o.OrganizationID()
m.OrganizationID = omitnull.FromNull(val)
}
return m
}
@ -184,6 +200,9 @@ func (o PublicreportQuickTemplate) Build() *models.PublicreportQuick {
if o.Status != nil {
m.Status = o.Status()
}
if o.OrganizationID != nil {
m.OrganizationID = o.OrganizationID()
}
o.setModelRels(m)
@ -240,6 +259,25 @@ func ensureCreatablePublicreportQuick(m *models.PublicreportQuickSetter) {
func (o *PublicreportQuickTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m *models.PublicreportQuick) error {
var err error
isOrganizationDone, _ := publicreportQuickRelOrganizationCtx.Value(ctx)
if !isOrganizationDone && o.r.Organization != nil {
ctx = publicreportQuickRelOrganizationCtx.WithValue(ctx, true)
if o.r.Organization.o.alreadyPersisted {
m.R.Organization = o.r.Organization.o.Build()
} else {
var rel0 *models.Organization
rel0, err = o.r.Organization.o.Create(ctx, exec)
if err != nil {
return err
}
err = m.AttachOrganization(ctx, exec, rel0)
if err != nil {
return err
}
}
}
isImagesDone, _ := publicreportQuickRelImagesCtx.Value(ctx)
if !isImagesDone && o.r.Images != nil {
ctx = publicreportQuickRelImagesCtx.WithValue(ctx, true)
@ -247,12 +285,12 @@ func (o *PublicreportQuickTemplate) insertOptRels(ctx context.Context, exec bob.
if r.o.alreadyPersisted {
m.R.Images = append(m.R.Images, r.o.Build())
} else {
rel0, err := r.o.CreateMany(ctx, exec, r.number)
rel1, err := r.o.CreateMany(ctx, exec, r.number)
if err != nil {
return err
}
err = m.AttachImages(ctx, exec, rel0...)
err = m.AttachImages(ctx, exec, rel1...)
if err != nil {
return err
}
@ -362,6 +400,7 @@ func (m publicreportQuickMods) RandomizeAllColumns(f *faker.Faker) PublicreportQ
PublicreportQuickMods.RandomReporterPhone(f),
PublicreportQuickMods.RandomAddress(f),
PublicreportQuickMods.RandomStatus(f),
PublicreportQuickMods.RandomOrganizationID(f),
}
}
@ -719,12 +758,100 @@ func (m publicreportQuickMods) RandomStatus(f *faker.Faker) PublicreportQuickMod
})
}
// Set the model columns to this value
func (m publicreportQuickMods) OrganizationID(val null.Val[int32]) PublicreportQuickMod {
return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) {
o.OrganizationID = func() null.Val[int32] { return val }
})
}
// Set the Column from the function
func (m publicreportQuickMods) OrganizationIDFunc(f func() null.Val[int32]) PublicreportQuickMod {
return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) {
o.OrganizationID = f
})
}
// Clear any values for the column
func (m publicreportQuickMods) UnsetOrganizationID() PublicreportQuickMod {
return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) {
o.OrganizationID = nil
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is sometimes null
func (m publicreportQuickMods) RandomOrganizationID(f *faker.Faker) PublicreportQuickMod {
return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) {
o.OrganizationID = func() null.Val[int32] {
if f == nil {
f = &defaultFaker
}
val := random_int32(f)
return null.From(val)
}
})
}
// Generates a random value for the column using the given faker
// if faker is nil, a default faker is used
// The generated value is never null
func (m publicreportQuickMods) RandomOrganizationIDNotNull(f *faker.Faker) PublicreportQuickMod {
return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) {
o.OrganizationID = func() null.Val[int32] {
if f == nil {
f = &defaultFaker
}
val := random_int32(f)
return null.From(val)
}
})
}
func (m publicreportQuickMods) WithParentsCascading() PublicreportQuickMod {
return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) {
if isDone, _ := publicreportQuickWithParentsCascadingCtx.Value(ctx); isDone {
return
}
ctx = publicreportQuickWithParentsCascadingCtx.WithValue(ctx, true)
{
related := o.f.NewOrganizationWithContext(ctx, OrganizationMods.WithParentsCascading())
m.WithOrganization(related).Apply(ctx, o)
}
})
}
func (m publicreportQuickMods) WithOrganization(rel *OrganizationTemplate) PublicreportQuickMod {
return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) {
o.r.Organization = &publicreportQuickROrganizationR{
o: rel,
}
})
}
func (m publicreportQuickMods) WithNewOrganization(mods ...OrganizationMod) PublicreportQuickMod {
return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) {
related := o.f.NewOrganizationWithContext(ctx, mods...)
m.WithOrganization(related).Apply(ctx, o)
})
}
func (m publicreportQuickMods) WithExistingOrganization(em *models.Organization) PublicreportQuickMod {
return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) {
o.r.Organization = &publicreportQuickROrganizationR{
o: o.f.FromExistingOrganization(em),
}
})
}
func (m publicreportQuickMods) WithoutOrganization() PublicreportQuickMod {
return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) {
o.r.Organization = nil
})
}

View file

@ -0,0 +1,8 @@
-- +goose Up
ALTER TABLE publicreport.quick ADD COLUMN organization_id INTEGER REFERENCES "public"."organization"(id);
ALTER TABLE publicreport.pool ADD COLUMN organization_id INTEGER REFERENCES "public"."organization"(id);
ALTER TABLE publicreport.nuisance ADD COLUMN organization_id INTEGER REFERENCES "public"."organization"(id);
-- +goose Down
ALTER TABLE publicreport.nuisance DROP COLUMN organization_id;
ALTER TABLE publicreport.pool DROP COLUMN organization_id;
ALTER TABLE publicreport.quick DROP COLUMN organization_id;

View file

@ -0,0 +1,2 @@
-- +goose UP
ALTER TABLE public.organization ADD COLUMN logo_uuid UUID;

View file

@ -79,6 +79,7 @@ type joins[Q dialect.Joinable] struct {
Organizations joinSet[organizationJoins[Q]]
PublicreportImages joinSet[publicreportImageJoins[Q]]
PublicreportImageExifs joinSet[publicreportImageExifJoins[Q]]
PublicreportNuisances joinSet[publicreportNuisanceJoins[Q]]
PublicreportPools joinSet[publicreportPoolJoins[Q]]
PublicreportPoolImages joinSet[publicreportPoolImageJoins[Q]]
PublicreportQuicks joinSet[publicreportQuickJoins[Q]]
@ -143,6 +144,7 @@ func getJoins[Q dialect.Joinable]() joins[Q] {
Organizations: buildJoinSet[organizationJoins[Q]](Organizations.Columns, buildOrganizationJoins),
PublicreportImages: buildJoinSet[publicreportImageJoins[Q]](PublicreportImages.Columns, buildPublicreportImageJoins),
PublicreportImageExifs: buildJoinSet[publicreportImageExifJoins[Q]](PublicreportImageExifs.Columns, buildPublicreportImageExifJoins),
PublicreportNuisances: buildJoinSet[publicreportNuisanceJoins[Q]](PublicreportNuisances.Columns, buildPublicreportNuisanceJoins),
PublicreportPools: buildJoinSet[publicreportPoolJoins[Q]](PublicreportPools.Columns, buildPublicreportPoolJoins),
PublicreportPoolImages: buildJoinSet[publicreportPoolImageJoins[Q]](PublicreportPoolImages.Columns, buildPublicreportPoolImageJoins),
PublicreportQuicks: buildJoinSet[publicreportQuickJoins[Q]](PublicreportQuicks.Columns, buildPublicreportQuickJoins),

View file

@ -64,6 +64,7 @@ type preloaders struct {
Organization organizationPreloader
PublicreportImage publicreportImagePreloader
PublicreportImageExif publicreportImageExifPreloader
PublicreportNuisance publicreportNuisancePreloader
PublicreportPool publicreportPoolPreloader
PublicreportPoolImage publicreportPoolImagePreloader
PublicreportQuick publicreportQuickPreloader
@ -120,6 +121,7 @@ func getPreloaders() preloaders {
Organization: buildOrganizationPreloader(),
PublicreportImage: buildPublicreportImagePreloader(),
PublicreportImageExif: buildPublicreportImageExifPreloader(),
PublicreportNuisance: buildPublicreportNuisancePreloader(),
PublicreportPool: buildPublicreportPoolPreloader(),
PublicreportPoolImage: buildPublicreportPoolImagePreloader(),
PublicreportQuick: buildPublicreportQuickPreloader(),
@ -182,6 +184,7 @@ type thenLoaders[Q orm.Loadable] struct {
Organization organizationThenLoader[Q]
PublicreportImage publicreportImageThenLoader[Q]
PublicreportImageExif publicreportImageExifThenLoader[Q]
PublicreportNuisance publicreportNuisanceThenLoader[Q]
PublicreportPool publicreportPoolThenLoader[Q]
PublicreportPoolImage publicreportPoolImageThenLoader[Q]
PublicreportQuick publicreportQuickThenLoader[Q]
@ -238,6 +241,7 @@ func getThenLoaders[Q orm.Loadable]() thenLoaders[Q] {
Organization: buildOrganizationThenLoader[Q](),
PublicreportImage: buildPublicreportImageThenLoader[Q](),
PublicreportImageExif: buildPublicreportImageExifThenLoader[Q](),
PublicreportNuisance: buildPublicreportNuisanceThenLoader[Q](),
PublicreportPool: buildPublicreportPoolThenLoader[Q](),
PublicreportPoolImage: buildPublicreportPoolImageThenLoader[Q](),
PublicreportQuick: buildPublicreportQuickThenLoader[Q](),

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,7 @@ package models
import (
"context"
"fmt"
"io"
"time"
@ -19,6 +20,9 @@ import (
"github.com/stephenafamo/bob/dialect/psql/sm"
"github.com/stephenafamo/bob/dialect/psql/um"
"github.com/stephenafamo/bob/expr"
"github.com/stephenafamo/bob/mods"
"github.com/stephenafamo/bob/orm"
"github.com/stephenafamo/bob/types/pgtypes"
)
// PublicreportNuisance is an object representing the database table.
@ -50,6 +54,9 @@ type PublicreportNuisance struct {
Address string `db:"address" `
Location null.Val[string] `db:"location" `
Status enums.PublicreportReportstatustype `db:"status" `
OrganizationID null.Val[int32] `db:"organization_id" `
R publicreportNuisanceR `db:"-" `
}
// PublicreportNuisanceSlice is an alias for a slice of pointers to PublicreportNuisance.
@ -62,10 +69,15 @@ var PublicreportNuisances = psql.NewTablex[*PublicreportNuisance, PublicreportNu
// PublicreportNuisancesQuery is a query on the nuisance table
type PublicreportNuisancesQuery = *psql.ViewQuery[*PublicreportNuisance, PublicreportNuisanceSlice]
// publicreportNuisanceR is where relationships are stored.
type publicreportNuisanceR struct {
Organization *Organization // publicreport.nuisance.nuisance_organization_id_fkey
}
func buildPublicreportNuisanceColumns(alias string) publicreportNuisanceColumns {
return publicreportNuisanceColumns{
ColumnsExpr: expr.NewColumnsExpr(
"id", "additional_info", "created", "duration", "email", "inspection_type", "source_location", "preferred_date_range", "preferred_time", "request_call", "severity", "source_container", "source_description", "source_roof", "source_stagnant", "time_of_day_day", "time_of_day_early", "time_of_day_evening", "time_of_day_night", "public_id", "reporter_address", "reporter_email", "reporter_name", "reporter_phone", "address", "location", "status",
"id", "additional_info", "created", "duration", "email", "inspection_type", "source_location", "preferred_date_range", "preferred_time", "request_call", "severity", "source_container", "source_description", "source_roof", "source_stagnant", "time_of_day_day", "time_of_day_early", "time_of_day_evening", "time_of_day_night", "public_id", "reporter_address", "reporter_email", "reporter_name", "reporter_phone", "address", "location", "status", "organization_id",
).WithParent("publicreport.nuisance"),
tableAlias: alias,
ID: psql.Quote(alias, "id"),
@ -95,6 +107,7 @@ func buildPublicreportNuisanceColumns(alias string) publicreportNuisanceColumns
Address: psql.Quote(alias, "address"),
Location: psql.Quote(alias, "location"),
Status: psql.Quote(alias, "status"),
OrganizationID: psql.Quote(alias, "organization_id"),
}
}
@ -128,6 +141,7 @@ type publicreportNuisanceColumns struct {
Address psql.Expression
Location psql.Expression
Status psql.Expression
OrganizationID psql.Expression
}
func (c publicreportNuisanceColumns) Alias() string {
@ -169,10 +183,11 @@ type PublicreportNuisanceSetter struct {
Address omit.Val[string] `db:"address" `
Location omitnull.Val[string] `db:"location" `
Status omit.Val[enums.PublicreportReportstatustype] `db:"status" `
OrganizationID omitnull.Val[int32] `db:"organization_id" `
}
func (s PublicreportNuisanceSetter) SetColumns() []string {
vals := make([]string, 0, 27)
vals := make([]string, 0, 28)
if s.ID.IsValue() {
vals = append(vals, "id")
}
@ -254,6 +269,9 @@ func (s PublicreportNuisanceSetter) SetColumns() []string {
if s.Status.IsValue() {
vals = append(vals, "status")
}
if !s.OrganizationID.IsUnset() {
vals = append(vals, "organization_id")
}
return vals
}
@ -339,6 +357,9 @@ func (s PublicreportNuisanceSetter) Overwrite(t *PublicreportNuisance) {
if s.Status.IsValue() {
t.Status = s.Status.MustGet()
}
if !s.OrganizationID.IsUnset() {
t.OrganizationID = s.OrganizationID.MustGetNull()
}
}
func (s *PublicreportNuisanceSetter) Apply(q *dialect.InsertQuery) {
@ -347,7 +368,7 @@ func (s *PublicreportNuisanceSetter) Apply(q *dialect.InsertQuery) {
})
q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) {
vals := make([]bob.Expression, 27)
vals := make([]bob.Expression, 28)
if s.ID.IsValue() {
vals[0] = psql.Arg(s.ID.MustGet())
} else {
@ -510,6 +531,12 @@ func (s *PublicreportNuisanceSetter) Apply(q *dialect.InsertQuery) {
vals[26] = psql.Raw("DEFAULT")
}
if !s.OrganizationID.IsUnset() {
vals[27] = psql.Arg(s.OrganizationID.MustGetNull())
} else {
vals[27] = psql.Raw("DEFAULT")
}
return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "")
}))
}
@ -519,7 +546,7 @@ func (s PublicreportNuisanceSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
}
func (s PublicreportNuisanceSetter) Expressions(prefix ...string) []bob.Expression {
exprs := make([]bob.Expression, 0, 27)
exprs := make([]bob.Expression, 0, 28)
if s.ID.IsValue() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
@ -710,6 +737,13 @@ func (s PublicreportNuisanceSetter) Expressions(prefix ...string) []bob.Expressi
}})
}
if !s.OrganizationID.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "organization_id")...),
psql.Arg(s.OrganizationID),
}})
}
return exprs
}
@ -771,6 +805,7 @@ func (o *PublicreportNuisance) Update(ctx context.Context, exec bob.Executor, s
return err
}
o.R = v.R
*o = *v
return nil
@ -790,7 +825,7 @@ func (o *PublicreportNuisance) Reload(ctx context.Context, exec bob.Executor) er
if err != nil {
return err
}
o2.R = o.R
*o = *o2
return nil
@ -837,7 +872,7 @@ func (o PublicreportNuisanceSlice) copyMatchingRows(from ...*PublicreportNuisanc
if new.ID != old.ID {
continue
}
new.R = old.R
o[i] = new
break
}
@ -935,6 +970,78 @@ func (o PublicreportNuisanceSlice) ReloadAll(ctx context.Context, exec bob.Execu
return nil
}
// Organization starts a query for related objects on organization
func (o *PublicreportNuisance) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery {
return Organizations.Query(append(mods,
sm.Where(Organizations.Columns.ID.EQ(psql.Arg(o.OrganizationID))),
)...)
}
func (os PublicreportNuisanceSlice) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery {
pkOrganizationID := make(pgtypes.Array[null.Val[int32]], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkOrganizationID = append(pkOrganizationID, o.OrganizationID)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkOrganizationID), "integer[]")),
))
return Organizations.Query(append(mods,
sm.Where(psql.Group(Organizations.Columns.ID).OP("IN", PKArgExpr)),
)...)
}
func attachPublicreportNuisanceOrganization0(ctx context.Context, exec bob.Executor, count int, publicreportNuisance0 *PublicreportNuisance, organization1 *Organization) (*PublicreportNuisance, error) {
setter := &PublicreportNuisanceSetter{
OrganizationID: omitnull.From(organization1.ID),
}
err := publicreportNuisance0.Update(ctx, exec, setter)
if err != nil {
return nil, fmt.Errorf("attachPublicreportNuisanceOrganization0: %w", err)
}
return publicreportNuisance0, nil
}
func (publicreportNuisance0 *PublicreportNuisance) InsertOrganization(ctx context.Context, exec bob.Executor, related *OrganizationSetter) error {
var err error
organization1, err := Organizations.Insert(related).One(ctx, exec)
if err != nil {
return fmt.Errorf("inserting related objects: %w", err)
}
_, err = attachPublicreportNuisanceOrganization0(ctx, exec, 1, publicreportNuisance0, organization1)
if err != nil {
return err
}
publicreportNuisance0.R.Organization = organization1
organization1.R.Nuisances = append(organization1.R.Nuisances, publicreportNuisance0)
return nil
}
func (publicreportNuisance0 *PublicreportNuisance) AttachOrganization(ctx context.Context, exec bob.Executor, organization1 *Organization) error {
var err error
_, err = attachPublicreportNuisanceOrganization0(ctx, exec, 1, publicreportNuisance0, organization1)
if err != nil {
return err
}
publicreportNuisance0.R.Organization = organization1
organization1.R.Nuisances = append(organization1.R.Nuisances, publicreportNuisance0)
return nil
}
type publicreportNuisanceWhere[Q psql.Filterable] struct {
ID psql.WhereMod[Q, int32]
AdditionalInfo psql.WhereMod[Q, string]
@ -963,6 +1070,7 @@ type publicreportNuisanceWhere[Q psql.Filterable] struct {
Address psql.WhereMod[Q, string]
Location psql.WhereNullMod[Q, string]
Status psql.WhereMod[Q, enums.PublicreportReportstatustype]
OrganizationID psql.WhereNullMod[Q, int32]
}
func (publicreportNuisanceWhere[Q]) AliasedAs(alias string) publicreportNuisanceWhere[Q] {
@ -998,5 +1106,154 @@ func buildPublicreportNuisanceWhere[Q psql.Filterable](cols publicreportNuisance
Address: psql.Where[Q, string](cols.Address),
Location: psql.WhereNull[Q, string](cols.Location),
Status: psql.Where[Q, enums.PublicreportReportstatustype](cols.Status),
OrganizationID: psql.WhereNull[Q, int32](cols.OrganizationID),
}
}
func (o *PublicreportNuisance) Preload(name string, retrieved any) error {
if o == nil {
return nil
}
switch name {
case "Organization":
rel, ok := retrieved.(*Organization)
if !ok {
return fmt.Errorf("publicreportNuisance cannot load %T as %q", retrieved, name)
}
o.R.Organization = rel
if rel != nil {
rel.R.Nuisances = PublicreportNuisanceSlice{o}
}
return nil
default:
return fmt.Errorf("publicreportNuisance has no relationship %q", name)
}
}
type publicreportNuisancePreloader struct {
Organization func(...psql.PreloadOption) psql.Preloader
}
func buildPublicreportNuisancePreloader() publicreportNuisancePreloader {
return publicreportNuisancePreloader{
Organization: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*Organization, OrganizationSlice](psql.PreloadRel{
Name: "Organization",
Sides: []psql.PreloadSide{
{
From: PublicreportNuisances,
To: Organizations,
FromColumns: []string{"organization_id"},
ToColumns: []string{"id"},
},
},
}, Organizations.Columns.Names(), opts...)
},
}
}
type publicreportNuisanceThenLoader[Q orm.Loadable] struct {
Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
}
func buildPublicreportNuisanceThenLoader[Q orm.Loadable]() publicreportNuisanceThenLoader[Q] {
type OrganizationLoadInterface interface {
LoadOrganization(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
return publicreportNuisanceThenLoader[Q]{
Organization: thenLoadBuilder[Q](
"Organization",
func(ctx context.Context, exec bob.Executor, retrieved OrganizationLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadOrganization(ctx, exec, mods...)
},
),
}
}
// LoadOrganization loads the publicreportNuisance's Organization into the .R struct
func (o *PublicreportNuisance) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.Organization = nil
related, err := o.Organization(mods...).One(ctx, exec)
if err != nil {
return err
}
related.R.Nuisances = PublicreportNuisanceSlice{o}
o.R.Organization = related
return nil
}
// LoadOrganization loads the publicreportNuisance's Organization into the .R struct
func (os PublicreportNuisanceSlice) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
organizations, err := os.Organization(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range organizations {
if !o.OrganizationID.IsValue() {
continue
}
if !(o.OrganizationID.IsValue() && o.OrganizationID.MustGet() == rel.ID) {
continue
}
rel.R.Nuisances = append(rel.R.Nuisances, o)
o.R.Organization = rel
break
}
}
return nil
}
type publicreportNuisanceJoins[Q dialect.Joinable] struct {
typ string
Organization modAs[Q, organizationColumns]
}
func (j publicreportNuisanceJoins[Q]) aliasedAs(alias string) publicreportNuisanceJoins[Q] {
return buildPublicreportNuisanceJoins[Q](buildPublicreportNuisanceColumns(alias), j.typ)
}
func buildPublicreportNuisanceJoins[Q dialect.Joinable](cols publicreportNuisanceColumns, typ string) publicreportNuisanceJoins[Q] {
return publicreportNuisanceJoins[Q]{
typ: typ,
Organization: modAs[Q, organizationColumns]{
c: Organizations.Columns,
f: func(to organizationColumns) bob.Mod[Q] {
mods := make(mods.QueryMods[Q], 0, 1)
{
mods = append(mods, dialect.Join[Q](typ, Organizations.Name().As(to.Alias())).On(
to.ID.EQ(cols.OrganizationID),
))
}
return mods
},
},
}
}

View file

@ -59,6 +59,7 @@ type PublicreportPool struct {
ReporterPhone string `db:"reporter_phone" `
Subscribe bool `db:"subscribe" `
Status enums.PublicreportReportstatustype `db:"status" `
OrganizationID null.Val[int32] `db:"organization_id" `
R publicreportPoolR `db:"-" `
@ -77,13 +78,14 @@ type PublicreportPoolsQuery = *psql.ViewQuery[*PublicreportPool, PublicreportPoo
// publicreportPoolR is where relationships are stored.
type publicreportPoolR struct {
Images PublicreportImageSlice // publicreport.pool_image.pool_image_image_id_fkeypublicreport.pool_image.pool_image_pool_id_fkey
Organization *Organization // publicreport.pool.pool_organization_id_fkey
Images PublicreportImageSlice // publicreport.pool_image.pool_image_image_id_fkeypublicreport.pool_image.pool_image_pool_id_fkey
}
func buildPublicreportPoolColumns(alias string) publicreportPoolColumns {
return publicreportPoolColumns{
ColumnsExpr: expr.NewColumnsExpr(
"id", "access_comments", "access_gate", "access_fence", "access_locked", "access_dog", "access_other", "address", "address_country", "address_post_code", "address_place", "address_street", "address_region", "comments", "created", "h3cell", "has_adult", "has_larvae", "has_pupae", "location", "map_zoom", "owner_email", "owner_name", "owner_phone", "public_id", "reporter_email", "reporter_name", "reporter_phone", "subscribe", "status",
"id", "access_comments", "access_gate", "access_fence", "access_locked", "access_dog", "access_other", "address", "address_country", "address_post_code", "address_place", "address_street", "address_region", "comments", "created", "h3cell", "has_adult", "has_larvae", "has_pupae", "location", "map_zoom", "owner_email", "owner_name", "owner_phone", "public_id", "reporter_email", "reporter_name", "reporter_phone", "subscribe", "status", "organization_id",
).WithParent("publicreport.pool"),
tableAlias: alias,
ID: psql.Quote(alias, "id"),
@ -116,6 +118,7 @@ func buildPublicreportPoolColumns(alias string) publicreportPoolColumns {
ReporterPhone: psql.Quote(alias, "reporter_phone"),
Subscribe: psql.Quote(alias, "subscribe"),
Status: psql.Quote(alias, "status"),
OrganizationID: psql.Quote(alias, "organization_id"),
}
}
@ -152,6 +155,7 @@ type publicreportPoolColumns struct {
ReporterPhone psql.Expression
Subscribe psql.Expression
Status psql.Expression
OrganizationID psql.Expression
}
func (c publicreportPoolColumns) Alias() string {
@ -196,10 +200,11 @@ type PublicreportPoolSetter struct {
ReporterPhone omit.Val[string] `db:"reporter_phone" `
Subscribe omit.Val[bool] `db:"subscribe" `
Status omit.Val[enums.PublicreportReportstatustype] `db:"status" `
OrganizationID omitnull.Val[int32] `db:"organization_id" `
}
func (s PublicreportPoolSetter) SetColumns() []string {
vals := make([]string, 0, 30)
vals := make([]string, 0, 31)
if s.ID.IsValue() {
vals = append(vals, "id")
}
@ -290,6 +295,9 @@ func (s PublicreportPoolSetter) SetColumns() []string {
if s.Status.IsValue() {
vals = append(vals, "status")
}
if !s.OrganizationID.IsUnset() {
vals = append(vals, "organization_id")
}
return vals
}
@ -384,6 +392,9 @@ func (s PublicreportPoolSetter) Overwrite(t *PublicreportPool) {
if s.Status.IsValue() {
t.Status = s.Status.MustGet()
}
if !s.OrganizationID.IsUnset() {
t.OrganizationID = s.OrganizationID.MustGetNull()
}
}
func (s *PublicreportPoolSetter) Apply(q *dialect.InsertQuery) {
@ -392,7 +403,7 @@ func (s *PublicreportPoolSetter) Apply(q *dialect.InsertQuery) {
})
q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) {
vals := make([]bob.Expression, 30)
vals := make([]bob.Expression, 31)
if s.ID.IsValue() {
vals[0] = psql.Arg(s.ID.MustGet())
} else {
@ -573,6 +584,12 @@ func (s *PublicreportPoolSetter) Apply(q *dialect.InsertQuery) {
vals[29] = psql.Raw("DEFAULT")
}
if !s.OrganizationID.IsUnset() {
vals[30] = psql.Arg(s.OrganizationID.MustGetNull())
} else {
vals[30] = psql.Raw("DEFAULT")
}
return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "")
}))
}
@ -582,7 +599,7 @@ func (s PublicreportPoolSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
}
func (s PublicreportPoolSetter) Expressions(prefix ...string) []bob.Expression {
exprs := make([]bob.Expression, 0, 30)
exprs := make([]bob.Expression, 0, 31)
if s.ID.IsValue() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
@ -794,6 +811,13 @@ func (s PublicreportPoolSetter) Expressions(prefix ...string) []bob.Expression {
}})
}
if !s.OrganizationID.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "organization_id")...),
psql.Arg(s.OrganizationID),
}})
}
return exprs
}
@ -1020,6 +1044,30 @@ func (o PublicreportPoolSlice) ReloadAll(ctx context.Context, exec bob.Executor)
return nil
}
// Organization starts a query for related objects on organization
func (o *PublicreportPool) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery {
return Organizations.Query(append(mods,
sm.Where(Organizations.Columns.ID.EQ(psql.Arg(o.OrganizationID))),
)...)
}
func (os PublicreportPoolSlice) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery {
pkOrganizationID := make(pgtypes.Array[null.Val[int32]], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkOrganizationID = append(pkOrganizationID, o.OrganizationID)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkOrganizationID), "integer[]")),
))
return Organizations.Query(append(mods,
sm.Where(psql.Group(Organizations.Columns.ID).OP("IN", PKArgExpr)),
)...)
}
// Images starts a query for related objects on publicreport.image
func (o *PublicreportPool) Images(mods ...bob.Mod[*dialect.SelectQuery]) PublicreportImagesQuery {
return PublicreportImages.Query(append(mods,
@ -1049,6 +1097,54 @@ func (os PublicreportPoolSlice) Images(mods ...bob.Mod[*dialect.SelectQuery]) Pu
)...)
}
func attachPublicreportPoolOrganization0(ctx context.Context, exec bob.Executor, count int, publicreportPool0 *PublicreportPool, organization1 *Organization) (*PublicreportPool, error) {
setter := &PublicreportPoolSetter{
OrganizationID: omitnull.From(organization1.ID),
}
err := publicreportPool0.Update(ctx, exec, setter)
if err != nil {
return nil, fmt.Errorf("attachPublicreportPoolOrganization0: %w", err)
}
return publicreportPool0, nil
}
func (publicreportPool0 *PublicreportPool) InsertOrganization(ctx context.Context, exec bob.Executor, related *OrganizationSetter) error {
var err error
organization1, err := Organizations.Insert(related).One(ctx, exec)
if err != nil {
return fmt.Errorf("inserting related objects: %w", err)
}
_, err = attachPublicreportPoolOrganization0(ctx, exec, 1, publicreportPool0, organization1)
if err != nil {
return err
}
publicreportPool0.R.Organization = organization1
organization1.R.PublicreportPool = append(organization1.R.PublicreportPool, publicreportPool0)
return nil
}
func (publicreportPool0 *PublicreportPool) AttachOrganization(ctx context.Context, exec bob.Executor, organization1 *Organization) error {
var err error
_, err = attachPublicreportPoolOrganization0(ctx, exec, 1, publicreportPool0, organization1)
if err != nil {
return err
}
publicreportPool0.R.Organization = organization1
organization1.R.PublicreportPool = append(organization1.R.PublicreportPool, publicreportPool0)
return nil
}
func attachPublicreportPoolImages0(ctx context.Context, exec bob.Executor, count int, publicreportPool0 *PublicreportPool, publicreportImages2 PublicreportImageSlice) (PublicreportPoolImageSlice, error) {
setters := make([]*PublicreportPoolImageSetter, count)
for i := range count {
@ -1145,6 +1241,7 @@ type publicreportPoolWhere[Q psql.Filterable] struct {
ReporterPhone psql.WhereMod[Q, string]
Subscribe psql.WhereMod[Q, bool]
Status psql.WhereMod[Q, enums.PublicreportReportstatustype]
OrganizationID psql.WhereNullMod[Q, int32]
}
func (publicreportPoolWhere[Q]) AliasedAs(alias string) publicreportPoolWhere[Q] {
@ -1183,6 +1280,7 @@ func buildPublicreportPoolWhere[Q psql.Filterable](cols publicreportPoolColumns)
ReporterPhone: psql.Where[Q, string](cols.ReporterPhone),
Subscribe: psql.Where[Q, bool](cols.Subscribe),
Status: psql.Where[Q, enums.PublicreportReportstatustype](cols.Status),
OrganizationID: psql.WhereNull[Q, int32](cols.OrganizationID),
}
}
@ -1192,6 +1290,18 @@ func (o *PublicreportPool) Preload(name string, retrieved any) error {
}
switch name {
case "Organization":
rel, ok := retrieved.(*Organization)
if !ok {
return fmt.Errorf("publicreportPool cannot load %T as %q", retrieved, name)
}
o.R.Organization = rel
if rel != nil {
rel.R.PublicreportPool = PublicreportPoolSlice{o}
}
return nil
case "Images":
rels, ok := retrieved.(PublicreportImageSlice)
if !ok {
@ -1211,22 +1321,48 @@ func (o *PublicreportPool) Preload(name string, retrieved any) error {
}
}
type publicreportPoolPreloader struct{}
type publicreportPoolPreloader struct {
Organization func(...psql.PreloadOption) psql.Preloader
}
func buildPublicreportPoolPreloader() publicreportPoolPreloader {
return publicreportPoolPreloader{}
return publicreportPoolPreloader{
Organization: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*Organization, OrganizationSlice](psql.PreloadRel{
Name: "Organization",
Sides: []psql.PreloadSide{
{
From: PublicreportPools,
To: Organizations,
FromColumns: []string{"organization_id"},
ToColumns: []string{"id"},
},
},
}, Organizations.Columns.Names(), opts...)
},
}
}
type publicreportPoolThenLoader[Q orm.Loadable] struct {
Images func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Images func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
}
func buildPublicreportPoolThenLoader[Q orm.Loadable]() publicreportPoolThenLoader[Q] {
type OrganizationLoadInterface interface {
LoadOrganization(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type ImagesLoadInterface interface {
LoadImages(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
return publicreportPoolThenLoader[Q]{
Organization: thenLoadBuilder[Q](
"Organization",
func(ctx context.Context, exec bob.Executor, retrieved OrganizationLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadOrganization(ctx, exec, mods...)
},
),
Images: thenLoadBuilder[Q](
"Images",
func(ctx context.Context, exec bob.Executor, retrieved ImagesLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
@ -1236,6 +1372,61 @@ func buildPublicreportPoolThenLoader[Q orm.Loadable]() publicreportPoolThenLoade
}
}
// LoadOrganization loads the publicreportPool's Organization into the .R struct
func (o *PublicreportPool) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.Organization = nil
related, err := o.Organization(mods...).One(ctx, exec)
if err != nil {
return err
}
related.R.PublicreportPool = PublicreportPoolSlice{o}
o.R.Organization = related
return nil
}
// LoadOrganization loads the publicreportPool's Organization into the .R struct
func (os PublicreportPoolSlice) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
organizations, err := os.Organization(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range organizations {
if !o.OrganizationID.IsValue() {
continue
}
if !(o.OrganizationID.IsValue() && o.OrganizationID.MustGet() == rel.ID) {
continue
}
rel.R.PublicreportPool = append(rel.R.PublicreportPool, o)
o.R.Organization = rel
break
}
}
return nil
}
// LoadImages loads the publicreportPool's Images into the .R struct
func (o *PublicreportPool) LoadImages(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
@ -1414,8 +1605,9 @@ func (os PublicreportPoolSlice) LoadCountImages(ctx context.Context, exec bob.Ex
}
type publicreportPoolJoins[Q dialect.Joinable] struct {
typ string
Images modAs[Q, publicreportImageColumns]
typ string
Organization modAs[Q, organizationColumns]
Images modAs[Q, publicreportImageColumns]
}
func (j publicreportPoolJoins[Q]) aliasedAs(alias string) publicreportPoolJoins[Q] {
@ -1425,6 +1617,20 @@ func (j publicreportPoolJoins[Q]) aliasedAs(alias string) publicreportPoolJoins[
func buildPublicreportPoolJoins[Q dialect.Joinable](cols publicreportPoolColumns, typ string) publicreportPoolJoins[Q] {
return publicreportPoolJoins[Q]{
typ: typ,
Organization: modAs[Q, organizationColumns]{
c: Organizations.Columns,
f: func(to organizationColumns) bob.Mod[Q] {
mods := make(mods.QueryMods[Q], 0, 1)
{
mods = append(mods, dialect.Join[Q](typ, Organizations.Name().As(to.Alias())).On(
to.ID.EQ(cols.OrganizationID),
))
}
return mods
},
},
Images: modAs[Q, publicreportImageColumns]{
c: PublicreportImages.Columns,
f: func(to publicreportImageColumns) bob.Mod[Q] {

View file

@ -29,16 +29,17 @@ import (
// PublicreportQuick is an object representing the database table.
type PublicreportQuick struct {
ID int32 `db:"id,pk" `
Created time.Time `db:"created" `
Comments string `db:"comments" `
Location null.Val[string] `db:"location" `
H3cell null.Val[string] `db:"h3cell" `
PublicID string `db:"public_id" `
ReporterEmail string `db:"reporter_email" `
ReporterPhone string `db:"reporter_phone" `
Address string `db:"address" `
Status enums.PublicreportReportstatustype `db:"status" `
ID int32 `db:"id,pk" `
Created time.Time `db:"created" `
Comments string `db:"comments" `
Location null.Val[string] `db:"location" `
H3cell null.Val[string] `db:"h3cell" `
PublicID string `db:"public_id" `
ReporterEmail string `db:"reporter_email" `
ReporterPhone string `db:"reporter_phone" `
Address string `db:"address" `
Status enums.PublicreportReportstatustype `db:"status" `
OrganizationID null.Val[int32] `db:"organization_id" `
R publicreportQuickR `db:"-" `
@ -57,41 +58,44 @@ type PublicreportQuicksQuery = *psql.ViewQuery[*PublicreportQuick, PublicreportQ
// publicreportQuickR is where relationships are stored.
type publicreportQuickR struct {
Images PublicreportImageSlice // publicreport.quick_image.quick_image_image_id_fkeypublicreport.quick_image.quick_image_quick_id_fkey
Organization *Organization // publicreport.quick.quick_organization_id_fkey
Images PublicreportImageSlice // publicreport.quick_image.quick_image_image_id_fkeypublicreport.quick_image.quick_image_quick_id_fkey
}
func buildPublicreportQuickColumns(alias string) publicreportQuickColumns {
return publicreportQuickColumns{
ColumnsExpr: expr.NewColumnsExpr(
"id", "created", "comments", "location", "h3cell", "public_id", "reporter_email", "reporter_phone", "address", "status",
"id", "created", "comments", "location", "h3cell", "public_id", "reporter_email", "reporter_phone", "address", "status", "organization_id",
).WithParent("publicreport.quick"),
tableAlias: alias,
ID: psql.Quote(alias, "id"),
Created: psql.Quote(alias, "created"),
Comments: psql.Quote(alias, "comments"),
Location: psql.Quote(alias, "location"),
H3cell: psql.Quote(alias, "h3cell"),
PublicID: psql.Quote(alias, "public_id"),
ReporterEmail: psql.Quote(alias, "reporter_email"),
ReporterPhone: psql.Quote(alias, "reporter_phone"),
Address: psql.Quote(alias, "address"),
Status: psql.Quote(alias, "status"),
tableAlias: alias,
ID: psql.Quote(alias, "id"),
Created: psql.Quote(alias, "created"),
Comments: psql.Quote(alias, "comments"),
Location: psql.Quote(alias, "location"),
H3cell: psql.Quote(alias, "h3cell"),
PublicID: psql.Quote(alias, "public_id"),
ReporterEmail: psql.Quote(alias, "reporter_email"),
ReporterPhone: psql.Quote(alias, "reporter_phone"),
Address: psql.Quote(alias, "address"),
Status: psql.Quote(alias, "status"),
OrganizationID: psql.Quote(alias, "organization_id"),
}
}
type publicreportQuickColumns struct {
expr.ColumnsExpr
tableAlias string
ID psql.Expression
Created psql.Expression
Comments psql.Expression
Location psql.Expression
H3cell psql.Expression
PublicID psql.Expression
ReporterEmail psql.Expression
ReporterPhone psql.Expression
Address psql.Expression
Status psql.Expression
tableAlias string
ID psql.Expression
Created psql.Expression
Comments psql.Expression
Location psql.Expression
H3cell psql.Expression
PublicID psql.Expression
ReporterEmail psql.Expression
ReporterPhone psql.Expression
Address psql.Expression
Status psql.Expression
OrganizationID psql.Expression
}
func (c publicreportQuickColumns) Alias() string {
@ -106,20 +110,21 @@ func (publicreportQuickColumns) AliasedAs(alias string) publicreportQuickColumns
// All values are optional, and do not have to be set
// Generated columns are not included
type PublicreportQuickSetter struct {
ID omit.Val[int32] `db:"id,pk" `
Created omit.Val[time.Time] `db:"created" `
Comments omit.Val[string] `db:"comments" `
Location omitnull.Val[string] `db:"location" `
H3cell omitnull.Val[string] `db:"h3cell" `
PublicID omit.Val[string] `db:"public_id" `
ReporterEmail omit.Val[string] `db:"reporter_email" `
ReporterPhone omit.Val[string] `db:"reporter_phone" `
Address omit.Val[string] `db:"address" `
Status omit.Val[enums.PublicreportReportstatustype] `db:"status" `
ID omit.Val[int32] `db:"id,pk" `
Created omit.Val[time.Time] `db:"created" `
Comments omit.Val[string] `db:"comments" `
Location omitnull.Val[string] `db:"location" `
H3cell omitnull.Val[string] `db:"h3cell" `
PublicID omit.Val[string] `db:"public_id" `
ReporterEmail omit.Val[string] `db:"reporter_email" `
ReporterPhone omit.Val[string] `db:"reporter_phone" `
Address omit.Val[string] `db:"address" `
Status omit.Val[enums.PublicreportReportstatustype] `db:"status" `
OrganizationID omitnull.Val[int32] `db:"organization_id" `
}
func (s PublicreportQuickSetter) SetColumns() []string {
vals := make([]string, 0, 10)
vals := make([]string, 0, 11)
if s.ID.IsValue() {
vals = append(vals, "id")
}
@ -150,6 +155,9 @@ func (s PublicreportQuickSetter) SetColumns() []string {
if s.Status.IsValue() {
vals = append(vals, "status")
}
if !s.OrganizationID.IsUnset() {
vals = append(vals, "organization_id")
}
return vals
}
@ -184,6 +192,9 @@ func (s PublicreportQuickSetter) Overwrite(t *PublicreportQuick) {
if s.Status.IsValue() {
t.Status = s.Status.MustGet()
}
if !s.OrganizationID.IsUnset() {
t.OrganizationID = s.OrganizationID.MustGetNull()
}
}
func (s *PublicreportQuickSetter) Apply(q *dialect.InsertQuery) {
@ -192,7 +203,7 @@ func (s *PublicreportQuickSetter) Apply(q *dialect.InsertQuery) {
})
q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) {
vals := make([]bob.Expression, 10)
vals := make([]bob.Expression, 11)
if s.ID.IsValue() {
vals[0] = psql.Arg(s.ID.MustGet())
} else {
@ -253,6 +264,12 @@ func (s *PublicreportQuickSetter) Apply(q *dialect.InsertQuery) {
vals[9] = psql.Raw("DEFAULT")
}
if !s.OrganizationID.IsUnset() {
vals[10] = psql.Arg(s.OrganizationID.MustGetNull())
} else {
vals[10] = psql.Raw("DEFAULT")
}
return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "")
}))
}
@ -262,7 +279,7 @@ func (s PublicreportQuickSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
}
func (s PublicreportQuickSetter) Expressions(prefix ...string) []bob.Expression {
exprs := make([]bob.Expression, 0, 10)
exprs := make([]bob.Expression, 0, 11)
if s.ID.IsValue() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
@ -334,6 +351,13 @@ func (s PublicreportQuickSetter) Expressions(prefix ...string) []bob.Expression
}})
}
if !s.OrganizationID.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "organization_id")...),
psql.Arg(s.OrganizationID),
}})
}
return exprs
}
@ -560,6 +584,30 @@ func (o PublicreportQuickSlice) ReloadAll(ctx context.Context, exec bob.Executor
return nil
}
// Organization starts a query for related objects on organization
func (o *PublicreportQuick) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery {
return Organizations.Query(append(mods,
sm.Where(Organizations.Columns.ID.EQ(psql.Arg(o.OrganizationID))),
)...)
}
func (os PublicreportQuickSlice) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery {
pkOrganizationID := make(pgtypes.Array[null.Val[int32]], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkOrganizationID = append(pkOrganizationID, o.OrganizationID)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkOrganizationID), "integer[]")),
))
return Organizations.Query(append(mods,
sm.Where(psql.Group(Organizations.Columns.ID).OP("IN", PKArgExpr)),
)...)
}
// Images starts a query for related objects on publicreport.image
func (o *PublicreportQuick) Images(mods ...bob.Mod[*dialect.SelectQuery]) PublicreportImagesQuery {
return PublicreportImages.Query(append(mods,
@ -589,6 +637,54 @@ func (os PublicreportQuickSlice) Images(mods ...bob.Mod[*dialect.SelectQuery]) P
)...)
}
func attachPublicreportQuickOrganization0(ctx context.Context, exec bob.Executor, count int, publicreportQuick0 *PublicreportQuick, organization1 *Organization) (*PublicreportQuick, error) {
setter := &PublicreportQuickSetter{
OrganizationID: omitnull.From(organization1.ID),
}
err := publicreportQuick0.Update(ctx, exec, setter)
if err != nil {
return nil, fmt.Errorf("attachPublicreportQuickOrganization0: %w", err)
}
return publicreportQuick0, nil
}
func (publicreportQuick0 *PublicreportQuick) InsertOrganization(ctx context.Context, exec bob.Executor, related *OrganizationSetter) error {
var err error
organization1, err := Organizations.Insert(related).One(ctx, exec)
if err != nil {
return fmt.Errorf("inserting related objects: %w", err)
}
_, err = attachPublicreportQuickOrganization0(ctx, exec, 1, publicreportQuick0, organization1)
if err != nil {
return err
}
publicreportQuick0.R.Organization = organization1
organization1.R.Quicks = append(organization1.R.Quicks, publicreportQuick0)
return nil
}
func (publicreportQuick0 *PublicreportQuick) AttachOrganization(ctx context.Context, exec bob.Executor, organization1 *Organization) error {
var err error
_, err = attachPublicreportQuickOrganization0(ctx, exec, 1, publicreportQuick0, organization1)
if err != nil {
return err
}
publicreportQuick0.R.Organization = organization1
organization1.R.Quicks = append(organization1.R.Quicks, publicreportQuick0)
return nil
}
func attachPublicreportQuickImages0(ctx context.Context, exec bob.Executor, count int, publicreportQuick0 *PublicreportQuick, publicreportImages2 PublicreportImageSlice) (PublicreportQuickImageSlice, error) {
setters := make([]*PublicreportQuickImageSetter, count)
for i := range count {
@ -655,16 +751,17 @@ func (publicreportQuick0 *PublicreportQuick) AttachImages(ctx context.Context, e
}
type publicreportQuickWhere[Q psql.Filterable] struct {
ID psql.WhereMod[Q, int32]
Created psql.WhereMod[Q, time.Time]
Comments psql.WhereMod[Q, string]
Location psql.WhereNullMod[Q, string]
H3cell psql.WhereNullMod[Q, string]
PublicID psql.WhereMod[Q, string]
ReporterEmail psql.WhereMod[Q, string]
ReporterPhone psql.WhereMod[Q, string]
Address psql.WhereMod[Q, string]
Status psql.WhereMod[Q, enums.PublicreportReportstatustype]
ID psql.WhereMod[Q, int32]
Created psql.WhereMod[Q, time.Time]
Comments psql.WhereMod[Q, string]
Location psql.WhereNullMod[Q, string]
H3cell psql.WhereNullMod[Q, string]
PublicID psql.WhereMod[Q, string]
ReporterEmail psql.WhereMod[Q, string]
ReporterPhone psql.WhereMod[Q, string]
Address psql.WhereMod[Q, string]
Status psql.WhereMod[Q, enums.PublicreportReportstatustype]
OrganizationID psql.WhereNullMod[Q, int32]
}
func (publicreportQuickWhere[Q]) AliasedAs(alias string) publicreportQuickWhere[Q] {
@ -673,16 +770,17 @@ func (publicreportQuickWhere[Q]) AliasedAs(alias string) publicreportQuickWhere[
func buildPublicreportQuickWhere[Q psql.Filterable](cols publicreportQuickColumns) publicreportQuickWhere[Q] {
return publicreportQuickWhere[Q]{
ID: psql.Where[Q, int32](cols.ID),
Created: psql.Where[Q, time.Time](cols.Created),
Comments: psql.Where[Q, string](cols.Comments),
Location: psql.WhereNull[Q, string](cols.Location),
H3cell: psql.WhereNull[Q, string](cols.H3cell),
PublicID: psql.Where[Q, string](cols.PublicID),
ReporterEmail: psql.Where[Q, string](cols.ReporterEmail),
ReporterPhone: psql.Where[Q, string](cols.ReporterPhone),
Address: psql.Where[Q, string](cols.Address),
Status: psql.Where[Q, enums.PublicreportReportstatustype](cols.Status),
ID: psql.Where[Q, int32](cols.ID),
Created: psql.Where[Q, time.Time](cols.Created),
Comments: psql.Where[Q, string](cols.Comments),
Location: psql.WhereNull[Q, string](cols.Location),
H3cell: psql.WhereNull[Q, string](cols.H3cell),
PublicID: psql.Where[Q, string](cols.PublicID),
ReporterEmail: psql.Where[Q, string](cols.ReporterEmail),
ReporterPhone: psql.Where[Q, string](cols.ReporterPhone),
Address: psql.Where[Q, string](cols.Address),
Status: psql.Where[Q, enums.PublicreportReportstatustype](cols.Status),
OrganizationID: psql.WhereNull[Q, int32](cols.OrganizationID),
}
}
@ -692,6 +790,18 @@ func (o *PublicreportQuick) Preload(name string, retrieved any) error {
}
switch name {
case "Organization":
rel, ok := retrieved.(*Organization)
if !ok {
return fmt.Errorf("publicreportQuick cannot load %T as %q", retrieved, name)
}
o.R.Organization = rel
if rel != nil {
rel.R.Quicks = PublicreportQuickSlice{o}
}
return nil
case "Images":
rels, ok := retrieved.(PublicreportImageSlice)
if !ok {
@ -711,22 +821,48 @@ func (o *PublicreportQuick) Preload(name string, retrieved any) error {
}
}
type publicreportQuickPreloader struct{}
type publicreportQuickPreloader struct {
Organization func(...psql.PreloadOption) psql.Preloader
}
func buildPublicreportQuickPreloader() publicreportQuickPreloader {
return publicreportQuickPreloader{}
return publicreportQuickPreloader{
Organization: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*Organization, OrganizationSlice](psql.PreloadRel{
Name: "Organization",
Sides: []psql.PreloadSide{
{
From: PublicreportQuicks,
To: Organizations,
FromColumns: []string{"organization_id"},
ToColumns: []string{"id"},
},
},
}, Organizations.Columns.Names(), opts...)
},
}
}
type publicreportQuickThenLoader[Q orm.Loadable] struct {
Images func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Images func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
}
func buildPublicreportQuickThenLoader[Q orm.Loadable]() publicreportQuickThenLoader[Q] {
type OrganizationLoadInterface interface {
LoadOrganization(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type ImagesLoadInterface interface {
LoadImages(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
return publicreportQuickThenLoader[Q]{
Organization: thenLoadBuilder[Q](
"Organization",
func(ctx context.Context, exec bob.Executor, retrieved OrganizationLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadOrganization(ctx, exec, mods...)
},
),
Images: thenLoadBuilder[Q](
"Images",
func(ctx context.Context, exec bob.Executor, retrieved ImagesLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
@ -736,6 +872,61 @@ func buildPublicreportQuickThenLoader[Q orm.Loadable]() publicreportQuickThenLoa
}
}
// LoadOrganization loads the publicreportQuick's Organization into the .R struct
func (o *PublicreportQuick) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.Organization = nil
related, err := o.Organization(mods...).One(ctx, exec)
if err != nil {
return err
}
related.R.Quicks = PublicreportQuickSlice{o}
o.R.Organization = related
return nil
}
// LoadOrganization loads the publicreportQuick's Organization into the .R struct
func (os PublicreportQuickSlice) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
organizations, err := os.Organization(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range organizations {
if !o.OrganizationID.IsValue() {
continue
}
if !(o.OrganizationID.IsValue() && o.OrganizationID.MustGet() == rel.ID) {
continue
}
rel.R.Quicks = append(rel.R.Quicks, o)
o.R.Organization = rel
break
}
}
return nil
}
// LoadImages loads the publicreportQuick's Images into the .R struct
func (o *PublicreportQuick) LoadImages(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
@ -914,8 +1105,9 @@ func (os PublicreportQuickSlice) LoadCountImages(ctx context.Context, exec bob.E
}
type publicreportQuickJoins[Q dialect.Joinable] struct {
typ string
Images modAs[Q, publicreportImageColumns]
typ string
Organization modAs[Q, organizationColumns]
Images modAs[Q, publicreportImageColumns]
}
func (j publicreportQuickJoins[Q]) aliasedAs(alias string) publicreportQuickJoins[Q] {
@ -925,6 +1117,20 @@ func (j publicreportQuickJoins[Q]) aliasedAs(alias string) publicreportQuickJoin
func buildPublicreportQuickJoins[Q dialect.Joinable](cols publicreportQuickColumns, typ string) publicreportQuickJoins[Q] {
return publicreportQuickJoins[Q]{
typ: typ,
Organization: modAs[Q, organizationColumns]{
c: Organizations.Columns,
f: func(to organizationColumns) bob.Mod[Q] {
mods := make(mods.QueryMods[Q], 0, 1)
{
mods = append(mods, dialect.Join[Q](typ, Organizations.Name().As(to.Alias())).On(
to.ID.EQ(cols.OrganizationID),
))
}
return mods
},
},
Images: modAs[Q, publicreportImageColumns]{
c: PublicreportImages.Columns,
f: func(to publicreportImageColumns) bob.Mod[Q] {

11
go.mod
View file

@ -34,13 +34,19 @@ require (
require (
github.com/ajg/form v1.5.1 // indirect
github.com/beevik/etree v1.1.0 // indirect
github.com/dsoprea/go-exif-extra v0.0.0-20210513050430-a8c8bb657ad5 // indirect
github.com/dsoprea/go-exif/v3 v3.0.1 // indirect
github.com/dsoprea/go-heic-exif-extractor/v2 v2.0.0-20210512044107-62067e44c235 // indirect
github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb // indirect
github.com/dsoprea/go-jpeg-image-structure/v2 v2.0.0-20221012074422-4f3f7e934102 // indirect
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
github.com/dsoprea/go-photoshop-info-format v0.0.0-20200609050348-3db9b63b202c // indirect
github.com/dsoprea/go-png-image-structure/v2 v2.0.0-20210512044023-23bdd883ee8e // indirect
github.com/dsoprea/go-tiff-image-structure/v2 v2.0.0-20210512044046-dc78da6a809b // indirect
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
github.com/dsoprea/go-webp-image-structure v0.0.0-20210512044215-f98af2b0401e // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/evanoberholster/imagemeta v0.3.1 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect
@ -64,20 +70,23 @@ require (
github.com/pkg/errors v0.9.1 // indirect
github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494 // indirect
github.com/rs/xid v1.6.0 // indirect
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect
github.com/sethvargo/go-retry v0.3.0 // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/tetratelabs/wazero v1.9.0 // indirect
github.com/tidwall/geoindex v1.4.4 // indirect
github.com/tidwall/gjson v1.12.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/rtree v1.3.1 // indirect
github.com/tidwall/sjson v1.2.4 // indirect
github.com/tinylib/msgp v1.3.0 // indirect
github.com/twilio/twilio-go v1.29.1 // indirect
github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52 // indirect
go.uber.org/multierr v1.11.0 // indirect
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
golang.org/x/image v0.0.0-20200618115811-c13761719519 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect

224
go.sum
View file

@ -1,7 +1,26 @@
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.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.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
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/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
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/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Gleipnir-Technology/arcgis-go v0.0.5 h1:7UdgFZv7bnmLqkvGLivKurLKICmwZGWctPxESjDjeA8=
github.com/Gleipnir-Technology/arcgis-go v0.0.5/go.mod h1:Stx2sn5Lvuyhy4SaTQpbLNCAfenboDINi/UU5gQvz4k=
github.com/Gleipnir-Technology/go-geojson2h3/v2 v2.0.0 h1:6OMVxoiX9r7dEkIyYYKtSu7I2UDq64dww4JxJTo3p78=
@ -22,6 +41,11 @@ github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
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/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
@ -45,16 +69,25 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dsoprea/go-exif-extra v0.0.0-20210513050430-a8c8bb657ad5 h1:F5HkHi38eOQECRJTJIV1Amn+J5q2atJf2feGPJ8/v+U=
github.com/dsoprea/go-exif-extra v0.0.0-20210513050430-a8c8bb657ad5/go.mod h1:9RNGsP4bsNJg7MDbFLmCw1lovrpGB2xCOjzyugh+4iY=
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
github.com/dsoprea/go-exif/v2 v2.0.0-20200604193436-ca8584a0e1c4/go.mod h1:9EXlPeHfblFFnwu5UOqmP2eoZfJyAZ2Ri/Vki33ajO0=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717071058-9393e7afd446/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-exif/v3 v3.0.0-20210428042052-dca55bf8ca15/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-exif/v3 v3.0.0-20210512043655-120bcdb2a55e/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-exif/v3 v3.0.0-20210512055020-8213cfabc61b/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-exif/v3 v3.0.0-20221003160559-cf5cd88aa559/go.mod h1:rW6DMEv25U9zCtE5ukC7ttBRllXj7g7TAHl7tQrT5No=
github.com/dsoprea/go-exif/v3 v3.0.0-20221003171958-de6cb6e380a8/go.mod h1:akyZEJZ/k5bmbC9gA612ZLQkcED8enS9vuTiuAkENr0=
github.com/dsoprea/go-exif/v3 v3.0.1 h1:/IE4iW7gvY7BablV1XY0unqhMv26EYpOquVMwoBo/wc=
github.com/dsoprea/go-exif/v3 v3.0.1/go.mod h1:10HkA1Wz3h398cDP66L+Is9kKDmlqlIJGPv8pk4EWvc=
github.com/dsoprea/go-heic-exif-extractor/v2 v2.0.0-20210512044107-62067e44c235 h1:a/XFkZdudAjXegNFRIf5vFjsF9LgFbiR5kjfHJZfIRA=
github.com/dsoprea/go-heic-exif-extractor/v2 v2.0.0-20210512044107-62067e44c235/go.mod h1:3mWA3lvkafMCuqoYKYXx/9YQgonsiAXf+KPSNlB/ZtI=
github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb h1:gwjJjUr6FY7zAWVEueFPrcRHhd9+IK81TcItbqw2du4=
github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb/go.mod h1:kYIdx9N9NaOyD7U6D+YtExN7QhRm+5kq7//yOsRXQtM=
github.com/dsoprea/go-jpeg-image-structure/v2 v2.0.0-20210512043942-b434301c6836/go.mod h1:WaARaUjQuSuDCDFAiU/GwzfxMTJBulfEhqEA2Tx6B4Y=
github.com/dsoprea/go-jpeg-image-structure/v2 v2.0.0-20221012074422-4f3f7e934102 h1:gmTXQdSuuuORRFPTS2uaYpAXU5oUNkXdeYSlZe5NvsE=
github.com/dsoprea/go-jpeg-image-structure/v2 v2.0.0-20221012074422-4f3f7e934102/go.mod h1:WaARaUjQuSuDCDFAiU/GwzfxMTJBulfEhqEA2Tx6B4Y=
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA=
@ -63,6 +96,12 @@ github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd h1:l+vLbuxptsC6
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
github.com/dsoprea/go-photoshop-info-format v0.0.0-20200609050348-3db9b63b202c h1:7j5aWACOzROpr+dvMtu8GnI97g9ShLWD72XIELMgn+c=
github.com/dsoprea/go-photoshop-info-format v0.0.0-20200609050348-3db9b63b202c/go.mod h1:pqKB+ijp27cEcrHxhXVgUUMlSDRuGJJp1E+20Lj5H0E=
github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d h1:8+qI8ant/vZkNSsbwSjIR6XJfWcDVTg/qx/3pRUUZNA=
github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d/go.mod h1:yTR3tKgyk20phAFg6IE9ulMA5NjEDD2wyx+okRFLVtw=
github.com/dsoprea/go-png-image-structure/v2 v2.0.0-20210512044023-23bdd883ee8e h1:7xT+Xgi019P9KVdcl+QUnSrgKCwIZWqkPNk5GygFTsw=
github.com/dsoprea/go-png-image-structure/v2 v2.0.0-20210512044023-23bdd883ee8e/go.mod h1:scnx0wQSM7UiCMK66dSdiPZvL2hl6iF5DvpZ7uT59MY=
github.com/dsoprea/go-tiff-image-structure/v2 v2.0.0-20210512044046-dc78da6a809b h1:r5TpplS/qPIevKTw6B9ft3p00FP6Flp3lXizranDiVQ=
github.com/dsoprea/go-tiff-image-structure/v2 v2.0.0-20210512044046-dc78da6a809b/go.mod h1:O3HgJ0u+ZTGEk2HZq4/7OvE8QPXWrDM2I9hrD8Qq0o4=
github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf h1:/w4QxepU4AHh3AuO6/g8y/YIIHH5+aKP3Bj8sg5cqhU=
github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8=
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e/go.mod h1:uAzdkPTub5Y9yQwXe8W4m2XuP0tK4a9Q/dantD0+uaU=
@ -70,10 +109,17 @@ github.com/dsoprea/go-utility/v2 v2.0.0-20221003142440-7a1927d49d9d/go.mod h1:LV
github.com/dsoprea/go-utility/v2 v2.0.0-20221003160719-7bc88537c05e/go.mod h1:VZ7cB0pTjm1ADBWhJUOHESu4ZYy9JN+ZPqjfiW09EPU=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 h1:DilThiXje0z+3UQ5YjYiSRRzVdtamFpvBQXKwMglWqw=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8=
github.com/dsoprea/go-webp-image-structure v0.0.0-20210512044215-f98af2b0401e h1:Hj7L0xxjASwligRr2F2qy7i4UOk422xcZDvWQSU4m8I=
github.com/dsoprea/go-webp-image-structure v0.0.0-20210512044215-f98af2b0401e/go.mod h1:SRCiMUH7zHuGUQAEnxmURDSsXUIQZfCrQiIkywxxnSs=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/eiannone/keyboard v0.0.0-20200508000154-caf4b762e807/go.mod h1:Xoiu5VdKMvbRgHuY7+z64lhu/7lvax/22nzASF6GrO8=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanoberholster/imagemeta v0.3.1 h1:E4GUjXcvlVMjP9joN25+bBNf3Al3MTTfMqCrDOCW+LE=
github.com/evanoberholster/imagemeta v0.3.1/go.mod h1:V0vtDJmjTqvwAYO8r+u33NRVIMXQb0qSqEfImoKEiXM=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
@ -88,6 +134,8 @@ github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWE
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
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-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
@ -109,14 +157,42 @@ github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgR
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
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/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.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
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.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
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/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.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
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-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
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/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/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/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
@ -130,8 +206,12 @@ github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jaswdr/faker/v2 v2.8.1 h1:2AcPgHDBXYQregFUH9LgVZKfFupc4SIquYhp29sf5wQ=
github.com/jaswdr/faker/v2 v2.8.1/go.mod h1:jZq+qzNQr8/P+5fHd9t3txe2GNPnthrTfohtnJ7B+68=
github.com/jdeng/goheif v0.0.0-20200323230657-a0d6a8b3e68f/go.mod h1:G7IyA3/eR9IFmUIPdyP3c0l4ZaqEvXAk876WfaQ8plc=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
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/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@ -205,10 +285,12 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/pressly/goose/v3 v3.26.0 h1:KJakav68jdH0WDvoAcj8+n61WqOIaPGgH0bJWS6jpmM=
github.com/pressly/goose/v3 v3.26.0/go.mod h1:4hC1KrritdCxtuFsqgs1R4AU5bWtTAf+cnWvfhf2DNY=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494 h1:wSmWgpuccqS2IOfmYrbRiUgv+g37W5suLLLxwwniTSc=
github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494/go.mod h1:yipyliwI08eQ6XwDm1fEwKPdF/xdbkiHtrU+1Hg+vc4=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
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.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
@ -216,6 +298,9 @@ github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
github.com/shirou/gopsutil/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQUJAsc=
@ -263,6 +348,8 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/rtree v1.3.1 h1:xu3vJPKJrmGce7YJcFUCoqLrp9DTUEJBnVgdPSXHgHs=
github.com/tidwall/rtree v1.3.1/go.mod h1:S+JSsqPTI8LfWA4xHBo5eXzie8WJLVFeppAutSegl6M=
github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc=
@ -281,10 +368,15 @@ github.com/wasilibs/go-pgquery v0.0.0-20250409022910-10ac41983c07 h1:mJdDDPblDfP
github.com/wasilibs/go-pgquery v0.0.0-20250409022910-10ac41983c07/go.mod h1:Ak17IJ037caFp4jpCw/iQQ7/W74Sqpb1YuKJU6HTKfM=
github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52 h1:OvLBa8SqJnZ6P+mjlzc2K7PM22rRUPE1x32G9DTPrC4=
github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52/go.mod h1:jMeV4Vpbi8osrE/pKUxRZkVaA0EX7NZN0A9/oRzgpgY=
github.com/wayneashleyberry/terminal-dimensions v1.0.0/go.mod h1:PW2XrtV6KmKOPhuf7wbtcmw1/IFnC39mryRET2XbxeE=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
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.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
@ -297,24 +389,67 @@ go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mx
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go4.org v0.0.0-20200411211856-f5505b9728dd h1:BNJlw5kRTzdmyfh5U8F93HA2OwkP7ZGwA51eJ/0wKOU=
go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
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-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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/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-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-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
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-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7UTjd6cgJNdatjPdFWf34=
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
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/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/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.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
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-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-20190724013045-ca1201d0de80/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-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-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/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-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
@ -324,14 +459,35 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
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/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-20210220032951-036812b2e83c/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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/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-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-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-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -355,7 +511,10 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
@ -363,8 +522,32 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
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/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-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-20190425150028-36563e24a262/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-20190911174233-4f2ddba30aff/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-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-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-20200130002326-2f3ba24bd6e7/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.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
@ -372,6 +555,39 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
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=
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/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/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-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
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.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/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
@ -392,6 +608,11 @@ 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=
modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ=
modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
@ -400,3 +621,6 @@ modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek=
modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View file

@ -52,11 +52,11 @@ func main() {
sr := nidussync.Router()
hr.Map("", sr) // default
hr.Map("*", sr) // default
hr.Map(config.URLReport, publicreport.Router()) // report.mosquitoes.online
hr.Map(config.URLSync, sr)
hr.Map(config.DomainRMO, publicreport.Router()) // report.mosquitoes.online
hr.Map(config.DomainNidus, sr)
r.Mount("/", hr)
log.Info().Str("report url", config.URLReport).Str("sync url", config.URLSync).Msg("Serving at URLs")
log.Info().Str("report url", config.DomainRMO).Str("sync url", config.DomainNidus).Msg("Serving at URLs")
// Start up background processes
ctx, cancel := context.WithCancel(context.Background())

View file

@ -2,30 +2,50 @@ package platform
import (
"context"
"errors"
"fmt"
"github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/rs/zerolog/log"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/sm"
)
func DistrictForLocation(ctx context.Context, lng float64, lat float64) (*models.ImportDistrict, error) {
rows, err := models.ImportDistricts.Query(
func DistrictForLocation(ctx context.Context, lng float64, lat float64) (*models.ImportDistrict, *models.Organization, error) {
districts, err := models.ImportDistricts.Query(
sm.Where(
psql.F("ST_Contains", psql.Raw("geom_4326"), psql.F("ST_SetSRID", psql.F("ST_MakePoint", psql.Arg(lng), psql.Arg(lat)), psql.Arg(4326))),
),
).All(ctx, db.PGInstance.BobDB)
log.Debug().Int("len", len(districts)).Float64("lng", lng).Float64("lat", lat).Msg("Attempting district match")
if err != nil {
return nil, fmt.Errorf("failed to query district: %w", err)
return nil, nil, fmt.Errorf("failed to query district: %w", err)
}
switch len(rows) {
switch len(districts) {
case 0:
return nil, nil
return nil, nil, nil
case 1:
return rows[0], nil
district := districts[0]
organizations, err := models.Organizations.Query(
sm.Where(
models.Organizations.Columns.ImportDistrictGid.EQ(psql.Arg(district.Gid)),
),
).All(ctx, db.PGInstance.BobDB)
if err != nil {
return nil, nil, fmt.Errorf("failed to query organization: %w", err)
}
switch len(organizations) {
case 0:
return nil, nil, nil
case 1:
return district, organizations[0], nil
default:
return nil, nil, errors.New("too many organizations")
}
default:
return nil, nil
return nil, nil, errors.New("too many districts")
}
}

View file

@ -8,9 +8,6 @@ import (
"github.com/rs/zerolog/log"
)
type ContextRegisterNotificationsComplete struct {
ReportID string
}
type ContextRoot struct{}
var (

View file

@ -13,21 +13,27 @@ import (
"net/http"
"time"
"github.com/aarondl/opt/omit"
"github.com/dsoprea/go-exif/v3"
exifcommon "github.com/dsoprea/go-exif/v3/common"
//"github.com/dsoprea/go-jpeg-image-structure/v2"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/Gleipnir-Technology/nidus-sync/userfile"
"github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
"github.com/rwcarlsen/goexif/exif"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/um"
//exif "github.com/rwcarlsen/goexif/exif"
//"github.com/dsoprea/go-exif-extra/format"
)
type GPS struct {
Latitude float64
Longitude float64
}
type ExifCollection struct {
GPS *exif.GpsInfo
GPS *GPS
Tags map[string]string
}
@ -42,43 +48,30 @@ type ImageUpload struct {
UUID uuid.UUID
}
func extractExif(file_bytes []byte) (result ExifCollection, err error) {
func extractExif(content_type string, file_bytes []byte) (result ExifCollection, err error) {
/*
Using "github.com/evanoberholster/imagemeta"
meta, err := imagemeta.Decode(bytes.NewReader(file_bytes))
if err != nil {
return result, fmt.Errorf("Failed to decode image meta: %w", err)
}
result.GPS = &GPS{
Latitude: meta.GPS.Latitude(),
Longitude: meta.GPS.Longitude(),
}
return result, err
*/
raw_exif, err := exif.SearchAndExtractExifWithReader(bytes.NewReader(file_bytes))
exif, err := exif.Decode(bytes.NewReader(file_bytes))
if err != nil {
return result, fmt.Errorf("Failed to find exif: %w", err)
return result, fmt.Errorf("Failed to decode image meta: %w", err)
}
im, err := exifcommon.NewIfdMappingWithStandard()
if err != nil {
return result, fmt.Errorf("Failed to create new idf mapping: %w", err)
lat, lng, _ := exif.LatLong()
result.GPS = &GPS{
Latitude: lat,
Longitude: lng,
}
ti := exif.NewTagIndex()
_, index, err := exif.Collect(im, ti, raw_exif)
if err != nil {
return result, fmt.Errorf("Failed to collect exif: %w", err)
}
ifd, err := index.RootIfd.ChildWithIfdPath(exifcommon.IfdGpsInfoStandardIfdIdentity)
if err != nil {
return result, fmt.Errorf("Failed to find gps exif: %w", err)
}
gi, err := ifd.GpsInfo()
if err != nil {
log.Info().Err(err).Msg("Failed to get GPS info for uploaded image")
result.GPS = nil
} else {
result.GPS = gi
}
result.Tags = make(map[string]string, 0)
tags, _, err := exif.GetFlatExifData(raw_exif, &exif.ScanOptions{})
if err != nil {
return result, fmt.Errorf("Failed to gather flat exif: %w", err)
}
for _, t := range tags {
result.Tags[t.TagName] = t.Formatted
}
log.Info().Str("GPS", fmt.Sprintf("%s", gi)).Int("count", len(result.Tags)).Msg("Extracted exif tags")
return result, nil
return result, err
}
func extractImageUpload(headers *multipart.FileHeader) (upload ImageUpload, err error) {
@ -91,11 +84,12 @@ func extractImageUpload(headers *multipart.FileHeader) (upload ImageUpload, err
file_bytes, err := io.ReadAll(file)
content_type := http.DetectContentType(file_bytes)
exif, err := extractExif(file_bytes)
exif, err := extractExif(content_type, file_bytes)
if err != nil {
//return upload, fmt.Errorf("Failed to extract EXIF data: %w", err)
log.Warn().Err(err).Msg("Failed to extract EXIF data")
}
log.Debug().Float64("lat", exif.GPS.Latitude).Float64("lng", exif.GPS.Longitude).Msg("extracted GPS from exif")
i, format, err := image.Decode(bytes.NewReader(file_bytes))
if err != nil {
@ -143,7 +137,8 @@ func saveImageUploads(ctx context.Context, tx bob.Tx, uploads []ImageUpload) (mo
ContentType: omit.From(u.ContentType),
Created: omit.From(time.Now()),
//Location: omitnull.From(nil),
//Location: psql.Raw("NULL"),
Location: omitnull.FromPtr[string](nil),
ResolutionX: omit.From(int32(u.Bounds.Max.X)),
ResolutionY: omit.From(int32(u.Bounds.Max.Y)),
StorageUUID: omit.From(u.UUID),
@ -158,7 +153,7 @@ func saveImageUploads(ctx context.Context, tx bob.Tx, uploads []ImageUpload) (mo
if u.Exif.GPS != nil {
_, err = psql.Update(
um.Table("publicreport.image"),
um.SetCol("location").To(fmt.Sprintf("ST_GeometryFromText('Point(%f %f)')", u.Exif.GPS.Longitude.Decimal(), u.Exif.GPS.Latitude.Decimal())),
um.SetCol("location").To(fmt.Sprintf("ST_GeometryFromText('Point(%f %f)')", u.Exif.GPS.Longitude, u.Exif.GPS.Latitude)),
um.Where(psql.Quote("id").EQ(psql.Arg(image.ID))),
).Exec(ctx, tx)
}
@ -171,9 +166,11 @@ func saveImageUploads(ctx context.Context, tx bob.Tx, uploads []ImageUpload) (mo
Value: omit.From(v),
})
}
_, err = models.PublicreportImageExifs.Insert(bob.ToMods(exif_setters...)).Exec(ctx, tx)
if err != nil {
return images, fmt.Errorf("Failed to create photo exif records: %w", err)
if len(exif_setters) > 0 {
_, err = models.PublicreportImageExifs.Insert(bob.ToMods(exif_setters...)).Exec(ctx, tx)
if err != nil {
return images, fmt.Errorf("Failed to create photo exif records: %w", err)
}
}
images = append(images, image)
log.Info().Int32("id", image.ID).Int("tags", len(u.Exif.Tags)).Msg("Saved an uploaded file to the database")

View file

@ -1,6 +1,7 @@
package publicreport
import (
"context"
"fmt"
"net/http"
"strconv"
@ -8,11 +9,13 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/background"
"github.com/Gleipnir-Technology/nidus-sync/comms"
"github.com/Gleipnir-Technology/nidus-sync/config"
"github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/db/enums"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/Gleipnir-Technology/nidus-sync/h3utils"
"github.com/Gleipnir-Technology/nidus-sync/htmlpage"
"github.com/Gleipnir-Technology/nidus-sync/platform"
"github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull"
"github.com/rs/zerolog/log"
@ -21,10 +24,18 @@ import (
"github.com/stephenafamo/bob/dialect/psql/um"
)
type ContextQuick struct{}
type ContextQuickSubmitComplete struct {
type ContentQuick struct{}
type ContentQuickSubmitComplete struct {
District *District
ReportID string
}
type ContentRegisterNotificationsComplete struct {
ReportID string
}
type District struct {
LogoURL string
Name string
}
var (
quickT = buildTemplate("quick", "base")
@ -36,16 +47,45 @@ func getQuick(w http.ResponseWriter, r *http.Request) {
htmlpage.RenderOrError(
w,
quickT,
ContextQuick{},
ContentQuick{},
)
}
func getQuickSubmitComplete(w http.ResponseWriter, r *http.Request) {
report := r.URL.Query().Get("report")
ctx := r.Context()
report_id := r.URL.Query().Get("report")
report, err := models.PublicreportQuicks.Query(
models.SelectWhere.PublicreportQuicks.PublicID.EQ(report_id),
).One(ctx, db.PGInstance.BobDB)
if err != nil {
respondError(w, "Failed to get report", err, http.StatusInternalServerError)
return
}
var district *District
if !report.OrganizationID.IsNull() {
org_id := report.OrganizationID.MustGet()
org, err := models.Organizations.Query(
models.Preload.Organization.ImportDistrictGidDistrict(),
models.SelectWhere.Organizations.ID.EQ(org_id),
).One(ctx, db.PGInstance.BobDB)
if err != nil {
respondError(w, "Failed to get org", err, http.StatusInternalServerError)
return
}
d := org.R.ImportDistrictGidDistrict
log.Debug().Int32("org_id", org.ID).Int32("d_gid", d.Gid).Msg("Getting district")
if d != nil {
district = &District{
LogoURL: config.MakeURLNidus("/api/district/%d/logo", org_id),
Name: d.Agency.GetOr("Unknown"),
}
}
}
htmlpage.RenderOrError(
w,
quickSubmitCompleteT,
ContextQuickSubmitComplete{
ReportID: report,
ContentQuickSubmitComplete{
District: district,
ReportID: report.PublicID,
},
)
}
@ -54,11 +94,38 @@ func getRegisterNotificationsComplete(w http.ResponseWriter, r *http.Request) {
htmlpage.RenderOrError(
w,
registerNotificationsCompleteT,
ContextRegisterNotificationsComplete{
ContentRegisterNotificationsComplete{
ReportID: report,
},
)
}
func matchDistrict(ctx context.Context, longitude, latitude float64, images []ImageUpload) (*int32, error) {
for _, image := range images {
if image.Exif.GPS == nil {
continue
}
_, org, err := platform.DistrictForLocation(ctx, image.Exif.GPS.Longitude, image.Exif.GPS.Latitude)
if err != nil {
log.Warn().Err(err).Msg("Failed to get district for location")
continue
}
if org != nil {
return &org.ID, nil
}
}
_, org, err := platform.DistrictForLocation(ctx, longitude, latitude)
if err != nil {
log.Warn().Err(err).Msg("Failed to get district for location")
return nil, fmt.Errorf("Failed to get district for location: %w", err)
}
if org == nil {
log.Debug().Err(err).Float64("lng", longitude).Float64("lat", latitude).Msg("No district match by report location")
return nil, nil
}
log.Debug().Err(err).Int32("org_id", org.ID).Float64("lng", longitude).Float64("lat", latitude).Msg("Found district match by report location")
return &org.ID, nil
}
func postQuick(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(32 << 10) // 32 MB buffer
if err != nil {
@ -92,11 +159,30 @@ func postQuick(w http.ResponseWriter, r *http.Request) {
}
defer tx.Rollback(ctx)
uploads, err := extractImageUploads(r)
log.Info().Int("len", len(uploads)).Msg("extracted uploads")
if err != nil {
respondError(w, "Failed to extract image uploads", err, http.StatusInternalServerError)
return
}
images, err := saveImageUploads(ctx, tx, uploads)
if err != nil {
respondError(w, "Failed to save image uploads", err, http.StatusInternalServerError)
return
}
organization_id, err := matchDistrict(ctx, longitude, latitude, uploads)
if err != nil {
log.Warn().Err(err).Msg("Failed to match district")
}
log.Info().Int("len", len(images)).Msg("saved uploads")
c, err := h3utils.GetCell(longitude, latitude, 15)
setter := models.PublicreportQuickSetter{
Address: omit.From(""),
Created: omit.From(time.Now()),
Comments: omit.From(comments),
Address: omit.From(""),
Created: omit.From(time.Now()),
Comments: omit.From(comments),
OrganizationID: omitnull.FromPtr(organization_id),
//Location: omitnull.From(fmt.Sprintf("ST_GeometryFromText(Point(%s %s))", longitude, latitude)),
H3cell: omitnull.From(c.String()),
PublicID: omit.From(u),
@ -119,18 +205,6 @@ func postQuick(w http.ResponseWriter, r *http.Request) {
return
}
log.Info().Float64("latitude", latitude).Float64("longitude", longitude).Msg("Got upload")
uploads, err := extractImageUploads(r)
log.Info().Int("len", len(uploads)).Msg("extracted uploads")
if err != nil {
respondError(w, "Failed to extract image uploads", err, http.StatusInternalServerError)
return
}
images, err := saveImageUploads(ctx, tx, uploads)
if err != nil {
respondError(w, "Failed to save image uploads", err, http.StatusInternalServerError)
return
}
log.Info().Int("len", len(images)).Msg("saved uploads")
if len(images) > 0 {
setters := make([]*models.PublicreportQuickImageSetter, 0)
for _, image := range images {

View file

@ -22,7 +22,7 @@ func getSearch(w http.ResponseWriter, r *http.Request) {
Search,
ContentSearch{
MapboxToken: config.MapboxToken,
URLTegola: config.URLTegola,
URLTegola: config.MakeURLTegola("/"),
},
)
}

View file

@ -38,6 +38,7 @@ type Report struct {
Address string
Comments string
Created time.Time
District string
ID string
Images []Image
Location string // GeoJSON
@ -175,6 +176,7 @@ func contentFromQuick(ctx context.Context, report_id string) (result ContentStat
result.Report.Address = quick.Address
result.Report.Comments = quick.Comments
result.Report.Created = quick.Created
result.Report.District = "Unknown"
result.Report.Reporter.Email = quick.ReporterEmail
result.Report.Reporter.Name = "-"
result.Report.Reporter.Phone = quick.ReporterPhone
@ -183,7 +185,7 @@ func contentFromQuick(ctx context.Context, report_id string) (result ContentStat
for _, image := range images {
result.Report.Images = append(result.Report.Images, Image{
Location: image.LocationJSON,
URL: fmt.Sprintf("https://%s/image/%s", config.RMODomain, image.StorageUUID),
URL: config.MakeURLReport("/image/%s", image.StorageUUID),
})
}
type LocationGeoJSON struct {

View file

@ -29,6 +29,11 @@
<span class="fs-4 fw-bold">{{.ReportID|publicReportID}}</span>
</div>
<p class="text-muted">Please save this ID for your reference.</p>
{{ if not (eq .District nil) }}
<p>Your report has been assigned to</p>
<p><b>{{ .District.Name }}</b></p>
<img src="{{ .District.LogoURL }}" width="256"/>
{{ end }}
</div>
<hr class="my-4">

View file

@ -82,8 +82,8 @@ document.addEventListener("DOMContentLoaded", onLoad);
<span>{{.Report.Created|timeSince}}</span>
</div>
<div class="col-md-4 mb-3">
<strong><i class="fas fa-hourglass-half me-2"></i>Next Step:</strong>
<span>July 19, 2023 (Estimated)</span>
<strong><i class="fas fa-hourglass-half me-2"></i>District:</strong>
<span>{{.Report.District}}</span>
</div>
</div>
</div>

View file

@ -284,7 +284,7 @@ func dashboard(ctx context.Context, w http.ResponseWriter, user *models.User) {
}
data := ContextDashboard{
Config: Config{
URLTegola: config.URLTegola,
URLTegola: config.MakeURLTegola("/"),
},
CountTraps: int(trapCount),
CountMosquitoSources: int(sourceCount),

View file

@ -49,7 +49,7 @@ func getQRCodeReport(w http.ResponseWriter, r *http.Request) {
if code == "" {
respondError(w, "There should always be a code", nil, http.StatusBadRequest)
}
content := config.MakeURLSync("/report/" + code)
content := config.MakeURLNidus("/report/%s", code)
// Get optional size parameter (default to 256)
size := 256
if sizeStr := r.URL.Query().Get("size"); sizeStr != "" {

View file

@ -2,6 +2,8 @@ package sync
import (
"net/http"
"net/url"
"strconv"
"github.com/Gleipnir-Technology/nidus-sync/auth"
"github.com/Gleipnir-Technology/nidus-sync/background"
@ -19,8 +21,33 @@ type ContextOauthPrompt struct {
User User
}
// Build the ArcGIS authorization URL with PKCE
func buildArcGISAuthURL(clientID string) string {
baseURL := "https://www.arcgis.com/sharing/rest/oauth2/authorize/"
params := url.Values{}
params.Add("client_id", clientID)
params.Add("redirect_uri", config.ArcGISOauthRedirectURL())
params.Add("response_type", "code")
//params.Add("code_challenge", generateCodeChallenge(codeVerifier))
//params.Add("code_challenge_method", "S256")
// See https://developers.arcgis.com/rest/users-groups-and-items/token/
// expiration is defined in minutes
var expiration int
if config.IsProductionEnvironment() {
// 2 weeks is the maximum allowed
expiration = 20160
} else {
expiration = 20
}
params.Add("expiration", strconv.Itoa(expiration))
return baseURL + "?" + params.Encode()
}
func getArcgisOauthBegin(w http.ResponseWriter, r *http.Request) {
authURL := config.BuildArcGISAuthURL(config.ClientID)
authURL := buildArcGISAuthURL(config.ClientID)
http.Redirect(w, r, authURL, http.StatusFound)
}
@ -41,7 +68,7 @@ func getArcgisOauthCallback(w http.ResponseWriter, r *http.Request) {
respondError(w, "Failed to handle access code", err, http.StatusInternalServerError)
return
}
http.Redirect(w, r, config.MakeURLSync("/"), http.StatusFound)
http.Redirect(w, r, config.MakeURLNidus("/"), http.StatusFound)
}
func getOAuthRefresh(w http.ResponseWriter, r *http.Request) {

View file

@ -41,11 +41,17 @@ func AudioFileContentWrite(audioUUID uuid.UUID, body io.Reader) error {
log.Info().Str("filepath", filepath).Msg("Save audio file content")
return nil
}
func ImageFileContentPathRaw(uid string) string {
return fmt.Sprintf("%s/%s.raw", config.FilesDirectoryUser, uid)
func ImageFileContentPathRawUser(uid string) string {
return imageFileContentPath(config.FilesDirectoryUser, uid, "raw")
}
func imageFileContentPathLogoPng(uid string) string {
return imageFileContentPath(config.FilesDirectoryLogo, uid, "png")
}
func imageFileContentPath(dir string, uid string, ext string) string {
return fmt.Sprintf("%s/%s.%s", dir, uid, ext)
}
func ImageFileContentWrite(uid uuid.UUID, body io.Reader) error {
filepath := ImageFileContentPathRaw(uid.String())
filepath := ImageFileContentPathRawUser(uid.String())
// Create file in configured directory
dst, err := os.Create(filepath)
@ -61,6 +67,11 @@ func ImageFileContentWrite(uid uuid.UUID, body io.Reader) error {
}
return nil
}
func ImageFileContentWriteLogo(w http.ResponseWriter, uid uuid.UUID) {
image_path := imageFileContentPathLogoPng(uid.String())
writeFileContent(w, image_path)
}
func PublicImageFileContentWrite(uid uuid.UUID, body io.Reader) error {
// Create file in configured directory
filepath := PublicImageFileContentPathRaw(uid.String())
@ -86,7 +97,10 @@ func PublicImageFileContentPathRaw(uid string) string {
func PublicImageFileToResponse(w http.ResponseWriter, uid string) {
image_path := PublicImageFileContentPathRaw(uid)
writeFileContent(w, image_path)
}
func writeFileContent(w http.ResponseWriter, image_path string) {
// Open the file
file, err := os.Open(image_path)
if err != nil {