diff --git a/apps/cli-go/pkg/config/config.go b/apps/cli-go/pkg/config/config.go index e2697ad825..d082a204b7 100644 --- a/apps/cli-go/pkg/config/config.go +++ b/apps/cli-go/pkg/config/config.go @@ -144,7 +144,7 @@ type ( Db db `toml:"db" json:"db"` Realtime realtime `toml:"realtime" json:"realtime"` Studio studio `toml:"studio" json:"studio"` - Inbucket inbucket `toml:"inbucket" json:"inbucket"` + Inbucket inbucket `toml:"local_smtp" json:"local_smtp"` Storage storage `toml:"storage" json:"storage"` Auth auth `toml:"auth" json:"auth"` EdgeRuntime edgeRuntime `toml:"edge_runtime" json:"edge_runtime"` @@ -488,13 +488,17 @@ func (c *config) loadFromFile(filename string, fsys fs.FS) error { viper.ExperimentalBindStruct(), viper.EnvKeyReplacer(strings.NewReplacer(".", "_")), ) + fileConfig := viper.New() v.SetEnvPrefix("SUPABASE") v.AutomaticEnv() if err := c.mergeDefaultValues(v); err != nil { return err } else if err := mergeFileConfig(v, filename, fsys); err != nil { return err + } else if err := mergeFileConfig(fileConfig, filename, fsys); err != nil { + return err } + v = normalizeDeprecatedSMTPConfig(v, fileConfig) // Find [remotes.*] block to override base config idToName := map[string]string{} for name, remote := range v.GetStringMap("remotes") { @@ -514,6 +518,40 @@ func (c *config) loadFromFile(filename string, fsys fs.FS) error { return c.load(v) } +func normalizeDeprecatedSMTPConfig(v, fileConfig *viper.Viper) *viper.Viper { + settings := v.AllSettings() + if fileConfig.IsSet("inbucket") { + fmt.Fprintln(os.Stderr, `WARN: config section [inbucket] is deprecated. Please use [local_smtp] instead.`) + if !fileConfig.IsSet("local_smtp") { + settings["local_smtp"] = settings["inbucket"] + } + delete(settings, "inbucket") + } + if remotes, ok := settings["remotes"].(map[string]any); ok { + for name, raw := range remotes { + remote, ok := raw.(map[string]any) + if !ok || !fileConfig.IsSet(fmt.Sprintf("remotes.%s.inbucket", name)) { + continue + } + fmt.Fprintf( + os.Stderr, + "WARN: config section [remotes.%s.inbucket] is deprecated. Please use [remotes.%s.local_smtp] instead.\n", + name, + name, + ) + if !fileConfig.IsSet(fmt.Sprintf("remotes.%s.local_smtp", name)) { + remote["local_smtp"] = remote["inbucket"] + } + delete(remote, "inbucket") + } + } + u := viper.New() + if err := u.MergeConfigMap(settings); err != nil { + return v + } + return u +} + func (c *config) mergeDefaultValues(v *viper.Viper) error { v.SetConfigType("toml") var buf bytes.Buffer @@ -907,7 +945,7 @@ func (c *config) Validate(fsys fs.FS) error { // Validate smtp config if c.Inbucket.Enabled { if c.Inbucket.Port == 0 { - return errors.New("Missing required field in config: inbucket.port") + return errors.New("Missing required field in config: local_smtp.port") } } // Validate auth config diff --git a/apps/cli-go/pkg/config/templates/config.toml b/apps/cli-go/pkg/config/templates/config.toml index d34c36c9ba..6baa24d887 100644 --- a/apps/cli-go/pkg/config/templates/config.toml +++ b/apps/cli-go/pkg/config/templates/config.toml @@ -96,7 +96,7 @@ openai_api_key = "env(OPENAI_API_KEY)" # Email testing server. Emails sent with the local dev setup are not actually sent - rather, they # are monitored, and you can view the emails that would have been sent from the web interface. -[inbucket] +[local_smtp] enabled = true # Port to use for the email testing server web interface. port = 54324 diff --git a/apps/cli-go/pkg/config/testdata/config.toml b/apps/cli-go/pkg/config/testdata/config.toml index b228a9c073..1c60b8af17 100644 --- a/apps/cli-go/pkg/config/testdata/config.toml +++ b/apps/cli-go/pkg/config/testdata/config.toml @@ -96,7 +96,7 @@ openai_api_key = "env(OPENAI_API_KEY)" # Email testing server. Emails sent with the local dev setup are not actually sent - rather, they # are monitored, and you can view the emails that would have been sent from the web interface. -[inbucket] +[local_smtp] enabled = true # Port to use for the email testing server web interface. port = 54324 diff --git a/packages/config/src/base.ts b/packages/config/src/base.ts index 4a56357209..26e14810e0 100644 --- a/packages/config/src/base.ts +++ b/packages/config/src/base.ts @@ -33,7 +33,7 @@ const baseProjectConfigFields = { db, edge_runtime, functions, - inbucket, + local_smtp: inbucket, realtime, storage, studio, @@ -48,7 +48,7 @@ const remoteProjectConfig = Schema.Struct({ db, edge_runtime, functions, - inbucket, + local_smtp: inbucket, realtime, storage, studio, diff --git a/packages/config/src/io.ts b/packages/config/src/io.ts index 07fbfb8834..b05246ddca 100644 --- a/packages/config/src/io.ts +++ b/packages/config/src/io.ts @@ -149,6 +149,35 @@ function parseProjectConfigDocument(content: string, format: ConfigFormat): unkn return format === "json" ? JSON.parse(content) : SmolToml.parse(content); } +function normalizeDeprecatedSMTPSections(document: unknown): unknown { + if (!isObject(document)) { + return document; + } + const normalized = { ...document }; + if ("inbucket" in normalized) { + if (!("local_smtp" in normalized)) { + normalized.local_smtp = normalized.inbucket; + } + delete normalized.inbucket; + } + if (isObject(normalized.remotes)) { + normalized.remotes = Object.fromEntries( + Object.entries(normalized.remotes).map(([name, remote]) => { + if (!isObject(remote) || !("inbucket" in remote)) { + return [name, remote]; + } + const normalizedRemote = { ...remote }; + if (!("local_smtp" in normalizedRemote)) { + normalizedRemote.local_smtp = normalizedRemote.inbucket; + } + delete normalizedRemote.inbucket; + return [name, normalizedRemote]; + }), + ); + } + return normalized; +} + function getSchemaRef(document: unknown): string | undefined { if (!isObject(document)) { return undefined; @@ -211,7 +240,8 @@ export const loadProjectConfigFile = Effect.fnUntraced(function* (path: string) try: () => parseProjectConfigDocument(content, format), catch: (cause) => new ProjectConfigParseError({ path, format, cause }), }); - const config = yield* parseProjectConfig(document, format, path); + const normalized = normalizeDeprecatedSMTPSections(document); + const config = yield* parseProjectConfig(normalized, format, path); return { path, diff --git a/packages/config/src/io.unit.test.ts b/packages/config/src/io.unit.test.ts index 4b934885c5..2f1fb17870 100644 --- a/packages/config/src/io.unit.test.ts +++ b/packages/config/src/io.unit.test.ts @@ -670,9 +670,11 @@ major_version = 16 const document = Schema.toJsonSchemaDocument(ProjectConfigSchema).schema; const schemaString = JSON.stringify(document); + expect(schemaString).toContain("local_smtp"); expect(schemaString).toContain("remotes"); expect(schemaString).toContain("static_files"); expect(schemaString).toContain("env"); + expect(schemaString).not.toContain("inbucket"); expect(schemaString).not.toContain("versions"); }); });