Skip to content

Commit

Permalink
feat(typegen): add swift type generator (#2484)
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev authored Jul 2, 2024
2 parents 6ea06ec + 422f535 commit 023f0ae
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 10 deletions.
13 changes: 11 additions & 2 deletions cmd/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,18 @@ var (
Allowed: []string{
types.LangTypescript,
types.LangGo,
types.LangSwift,
},
Value: types.LangTypescript,
}
postgrestV9Compat bool
postgrestV9Compat bool
swiftAccessControl = utils.EnumFlag{
Allowed: []string{
types.SwiftInternalAccessControl,
types.SwiftPublicAccessControl,
},
Value: types.SwiftInternalAccessControl,
}

genTypesCmd = &cobra.Command{
Use: "types",
Expand All @@ -79,7 +87,7 @@ var (
return err
}
}
return types.Run(ctx, flags.ProjectRef, flags.DbConfig, lang.Value, schema, postgrestV9Compat, afero.NewOsFs())
return types.Run(ctx, flags.ProjectRef, flags.DbConfig, lang.Value, schema, postgrestV9Compat, swiftAccessControl.Value, afero.NewOsFs())
},
Example: ` supabase gen types --local
supabase gen types --linked --lang=go
Expand Down Expand Up @@ -108,6 +116,7 @@ func init() {
genTypesCmd.MarkFlagsMutuallyExclusive("local", "linked", "project-id", "db-url")
genFlags.Var(&lang, "lang", "Output language of the generated types.")
genFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.")
genFlags.Var(&swiftAccessControl, "swift-access-control", "Access control for Swift generated types.")
genFlags.BoolVar(&postgrestV9Compat, "postgrest-v9-compat", false, "Generate types compatible with PostgREST v9 and below. Only use together with --db-url.")
genTypesCmd.AddCommand(genTypesTypescriptCmd)
genCmd.AddCommand(genTypesCmd)
Expand Down
9 changes: 8 additions & 1 deletion internal/gen/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@ import (
const (
LangTypescript = "typescript"
LangGo = "go"
LangSwift = "swift"
)

func Run(ctx context.Context, projectId string, dbConfig pgconn.Config, lang string, schemas []string, postgrestV9Compat bool, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
const (
SwiftPublicAccessControl = "public"
SwiftInternalAccessControl = "internal"
)

func Run(ctx context.Context, projectId string, dbConfig pgconn.Config, lang string, schemas []string, postgrestV9Compat bool, swiftAccessControl string, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
originalURL := utils.ToPostgresURL(dbConfig)
// Add default schemas if --schema flag is not specified
if len(schemas) == 0 {
Expand Down Expand Up @@ -86,6 +92,7 @@ func Run(ctx context.Context, projectId string, dbConfig pgconn.Config, lang str
"PG_META_DB_URL=" + escaped,
"PG_META_GENERATE_TYPES=" + lang,
"PG_META_GENERATE_TYPES_INCLUDED_SCHEMAS=" + included,
"PG_META_GENERATE_TYPES_SWIFT_ACCESS_CONTROL=" + swiftAccessControl,
fmt.Sprintf("PG_META_GENERATE_TYPES_DETECT_ONE_TO_ONE_RELATIONSHIPS=%v", !postgrestV9Compat),
},
Cmd: []string{"node", "dist/server/server.js"},
Expand Down
37 changes: 30 additions & 7 deletions internal/gen/types/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func TestGenLocalCommand(t *testing.T) {
conn := pgtest.NewConn()
defer conn.Close(t)
// Run test
assert.NoError(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, fsys, conn.Intercept))
assert.NoError(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, "", fsys, conn.Intercept))
// Validate api
assert.Empty(t, apitest.ListUnmatchedRequests())
})
Expand All @@ -63,7 +63,7 @@ func TestGenLocalCommand(t *testing.T) {
Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.DbId).
Reply(http.StatusServiceUnavailable)
// Run test
assert.Error(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, fsys))
assert.Error(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, "", fsys))
// Validate api
assert.Empty(t, apitest.ListUnmatchedRequests())
})
Expand All @@ -83,7 +83,30 @@ func TestGenLocalCommand(t *testing.T) {
Get("/v" + utils.Docker.ClientVersion() + "/images").
Reply(http.StatusServiceUnavailable)
// Run test
assert.Error(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, fsys))
assert.Error(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, "", fsys))
// Validate api
assert.Empty(t, apitest.ListUnmatchedRequests())
})

t.Run("generates swift types", func(t *testing.T) {
const containerId = "test-pgmeta"
imageUrl := utils.GetRegistryImageUrl(utils.PgmetaImage)
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Setup mock docker
require.NoError(t, apitest.MockDocker(utils.Docker))
defer gock.OffAll()
gock.New(utils.Docker.DaemonHost()).
Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.DbId).
Reply(http.StatusOK).
JSON(types.ContainerJSON{})
apitest.MockDockerStart(utils.Docker, imageUrl, containerId)
require.NoError(t, apitest.MockDockerLogs(utils.Docker, containerId, "hello world"))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
// Run test
assert.NoError(t, Run(context.Background(), "", dbConfig, LangSwift, []string{}, true, SwiftInternalAccessControl, fsys, conn.Intercept))
// Validate api
assert.Empty(t, apitest.ListUnmatchedRequests())
})
Expand All @@ -106,7 +129,7 @@ func TestGenLinkedCommand(t *testing.T) {
Reply(200).
JSON(api.TypescriptResponse{Types: ""})
// Run test
assert.NoError(t, Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, fsys))
assert.NoError(t, Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, "", fsys))
// Validate api
assert.Empty(t, apitest.ListUnmatchedRequests())
})
Expand All @@ -121,7 +144,7 @@ func TestGenLinkedCommand(t *testing.T) {
Get("/v1/projects/" + projectId + "/types/typescript").
ReplyError(errNetwork)
// Run test
err := Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, fsys)
err := Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, "", fsys)
// Validate api
assert.ErrorIs(t, err, errNetwork)
assert.Empty(t, apitest.ListUnmatchedRequests())
Expand All @@ -136,7 +159,7 @@ func TestGenLinkedCommand(t *testing.T) {
Get("/v1/projects/" + projectId + "/types/typescript").
Reply(http.StatusServiceUnavailable)
// Run test
assert.Error(t, Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, fsys))
assert.Error(t, Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, "", fsys))
})
}

Expand All @@ -161,7 +184,7 @@ func TestGenRemoteCommand(t *testing.T) {
conn := pgtest.NewConn()
defer conn.Close(t)
// Run test
assert.NoError(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{"public"}, true, afero.NewMemMapFs(), conn.Intercept))
assert.NoError(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{"public"}, true, "", afero.NewMemMapFs(), conn.Intercept))
// Validate api
assert.Empty(t, apitest.ListUnmatchedRequests())
})
Expand Down

0 comments on commit 023f0ae

Please sign in to comment.