diff --git a/backend/controller/controller.go b/backend/controller/controller.go index b99cc9a87a..36a9f5c4d0 100644 --- a/backend/controller/controller.go +++ b/backend/controller/controller.go @@ -383,12 +383,13 @@ func (s *Service) GetSchema(ctx context.Context, c *connect.Request[ftlv1.GetSch if err != nil { return nil, err } - sch := &schemapb.Schema{ - Modules: slices.Map(schemas, func(d *schema.Module) *schemapb.Module { - return d.ToProto().(*schemapb.Module) //nolint:forcetypeassert - }), + modules := []*schemapb.Module{ //nolint:forcetypeassert + schema.Builtins().ToProto().(*schemapb.Module), } - return connect.NewResponse(&ftlv1.GetSchemaResponse{Schema: sch}), nil + modules = append(modules, slices.Map(schemas, func(d *schema.Module) *schemapb.Module { + return d.ToProto().(*schemapb.Module) //nolint:forcetypeassert + })...) + return connect.NewResponse(&ftlv1.GetSchemaResponse{Schema: &schemapb.Schema{Modules: modules}}), nil } func (s *Service) PullSchema(ctx context.Context, req *connect.Request[ftlv1.PullSchemaRequest], stream *connect.ServerStream[ftlv1.PullSchemaResponse]) error { @@ -949,6 +950,19 @@ func (s *Service) watchModuleChanges(ctx context.Context, sendChange func(respon } logger.Infof("Seeded %d deployments", initialCount) + builtins := schema.Builtins().ToProto().(*schemapb.Module) //nolint:forcetypeassert + buildinsResponse := &ftlv1.PullSchemaResponse{ + ModuleName: builtins.Name, + Schema: builtins, + ChangeType: ftlv1.DeploymentChangeType_DEPLOYMENT_ADDED, + More: initialCount > 1, + } + + err = sendChange(buildinsResponse) + if err != nil { + return err + } + // Subscribe to deployment changes. s.dal.DeploymentChanges.Subscribe(deploymentChanges) defer s.dal.DeploymentChanges.Unsubscribe(deploymentChanges) diff --git a/backend/schema/schema_test.go b/backend/schema/schema_test.go index bf74e068fd..4dbe9b37ee 100644 --- a/backend/schema/schema_test.go +++ b/backend/schema/schema_test.go @@ -243,8 +243,8 @@ func TestParsing(t *testing.T) { Decls: []Decl{ &Verb{ Name: "myIngress", - Request: &DataRef{Module: "ftl", Name: "HttpRequest"}, - Response: &DataRef{Module: "ftl", Name: "HttpResponse"}, + Request: &DataRef{Module: "builtin", Name: "HttpRequest"}, + Response: &DataRef{Module: "builtin", Name: "HttpResponse"}, }, }, }}, diff --git a/backend/schema/validate.go b/backend/schema/validate.go index 0f6df4f92a..f93021b247 100644 --- a/backend/schema/validate.go +++ b/backend/schema/validate.go @@ -23,7 +23,7 @@ var ( // BuiltinsSource is the schema source code for built-in types. BuiltinsSource = ` // Built-in types for FTL. -builtin module ftl { +builtin module builtin { // HTTP request structure used for HTTP ingress verbs. data HttpRequest { method String @@ -152,7 +152,7 @@ func resolveRef(localModule *Module, ref *Ref, exist map[string]bool) bool { if ref.Module != "" { return exist[ref.String()] } - for _, module := range []string{localModule.Name, "ftl"} { + for _, module := range []string{localModule.Name, "builtin"} { clone := reflect.DeepCopy(ref) clone.Module = module if exist[clone.String()] { @@ -173,7 +173,7 @@ func ValidateModule(module *Module) error { if !validNameRe.MatchString(module.Name) { merr = append(merr, fmt.Errorf("%s: module name %q is invalid", module.Pos, module.Name)) } - if module.Builtin && module.Name != "ftl" { + if module.Builtin && module.Name != "builtin" { merr = append(merr, fmt.Errorf("%s: only the \"ftl\" module can be marked as builtin", module.Pos)) } err := Visit(module, func(n Node, next func() error) error {