i-love-flamingo / flamingo-commerce

Flexible E-Commerce Framework on top of Flamingo. Used to build E-Commerce "Portals" and connect it with the help of individual Adapters to other services.
https://www.flamingo.me/flamingo-commerce.html
MIT License
506 stars 81 forks source link

how to use product module? in hello world #383

Closed flexmeKim closed 7 months ago

flexmeKim commented 2 years ago

my code error here

2022-06-09T17:37:22.319+0900    INFO    runtime/module.go:32    maxprocs: Leaving GOMAXPROCS=10: CPU quota undefined    {"area": "root", "module": "core.runtime", "category": "module"}
2022-06-09T17:37:22.320+0900    INFO    v3@v3.3.0/app.go:365    Starting HTTP Server at :3322 .....     {"area": "root"}
panic: "web.routesProvider": injecting into flamingo.me/flamingo-commerce/v3/product.<*product.routes Value>:
injecting into flamingo.me/flamingo-commerce/v3/product/interfaces/controller.<controller.View Value>:
can not instantiate interface flamingo.me/flamingo-commerce/v3/product/domain.ProductService

goroutine 1 [running]:
flamingo.me/dingo.(*Injector).createProvider.func1.1({0x0?, 0x0?, 0x17a7780?}, {0x1a370a0, 0xc000482940})
        /Users/flexmekim/go/pkg/mod/flamingo.me/dingo@v0.2.9/dingo.go:417 +0x22e
flamingo.me/dingo.(*Injector).createProvider.func1({0x0?, 0x0?, 0x0?})
        /Users/flexmekim/go/pkg/mod/flamingo.me/dingo@v0.2.9/dingo.go:427 +0x43b
flamingo.me/flamingo/v3/framework/web.(*Router).Handler(0xc0002468c0)
        /Users/flexmekim/go/pkg/mod/flamingo.me/flamingo/v3@v3.3.0/framework/web/router.go:118 +0xf0
flamingo.me/flamingo/v3.serveProvider.func1(0xc000535680?, {0x18d7e95?, 0x0?, 0x0?})
        /Users/flexmekim/go/pkg/mod/flamingo.me/flamingo/v3@v3.3.0/app.go:366 +0xff
github.com/spf13/cobra.(*Command).execute(0xc000535680, {0xc000032050, 0x0, 0x0})
        /Users/flexmekim/go/pkg/mod/github.com/spf13/cobra@v1.4.0/command.go:860 +0x663
github.com/spf13/cobra.(*Command).ExecuteC(0xc00042e000)
        /Users/flexmekim/go/pkg/mod/github.com/spf13/cobra@v1.4.0/command.go:974 +0x3b4
github.com/spf13/cobra.(*Command).Execute(...)
        /Users/flexmekim/go/pkg/mod/github.com/spf13/cobra@v1.4.0/command.go:902
flamingo.me/flamingo/v3.(*Application).Run(0xc00049a200)
        /Users/flexmekim/go/pkg/mod/flamingo.me/flamingo/v3@v3.3.0/app.go:234 +0x1e9
flamingo.me/flamingo/v3.App({0xc00030a180?, 0x1004c51?, 0x10014e0?}, {0x0?, 0x0?, 0x17ae5e0?})
        /Users/flexmekim/go/pkg/mod/flamingo.me/flamingo/v3@v3.3.0/app.go:208 +0x65
main.main()
        /Users/flexmekim/go/src/github.com/flexmekim/flamingo-example/hello/main.go:12 +0x8c
exit status 2

and my project here

package main

import (
    "hello/helloworld"

    "flamingo.me/dingo"
    "flamingo.me/flamingo-commerce/v3/product"
    "flamingo.me/flamingo/v3"
)

func main() {
    flamingo.App([]dingo.Module{
        new(helloworld.Module),
        new(product.Module),
    })
}

and product module here

package product

import (
    "flamingo.me/dingo"
    "flamingo.me/flamingo-commerce/v3/price"
    "flamingo.me/flamingo-commerce/v3/product/domain"
    "flamingo.me/flamingo-commerce/v3/product/infrastructure/fake"
    "flamingo.me/flamingo-commerce/v3/product/interfaces/controller"
    productgraphql "flamingo.me/flamingo-commerce/v3/product/interfaces/graphql"
    "flamingo.me/flamingo-commerce/v3/product/interfaces/templatefunctions"
    "flamingo.me/flamingo-commerce/v3/search"
    "flamingo.me/flamingo/v3/framework/flamingo"
    "flamingo.me/flamingo/v3/framework/web"
    "flamingo.me/graphql"
)

type Module struct {
    fakeService bool
    api         bool
}

// Inject module configuration
func (m *Module) Inject(
    cfg *struct {
        FakeService bool `inject:"config:commerce.product.fakeservice.enabled,optional"`
        API         bool `inject:"config:commerce.product.api.enabled,optional"`
    },
) *Module {
    if cfg != nil {
        m.api = cfg.API
        m.fakeService = cfg.FakeService
    }

    return m
}

// Configure the product module
func (m *Module) Configure(injector *dingo.Injector) {
    flamingo.BindTemplateFunc(injector, "getProduct", new(templatefunctions.GetProduct))
    flamingo.BindTemplateFunc(injector, "getProductUrl", new(templatefunctions.GetProductURL))
    flamingo.BindTemplateFunc(injector, "findProducts", new(templatefunctions.FindProducts))

    web.BindRoutes(injector, new(routes))
    if m.api {
        web.BindRoutes(injector, new(apiRoutes))
    }

    injector.BindMulti(new(graphql.Service)).To(new(productgraphql.Service))
    if m.fakeService {
        injector.Override((*domain.ProductService)(nil), "").To(fake.ProductService{}).In(dingo.ChildSingleton)
        injector.Override((*domain.SearchService)(nil), "").To(fake.SearchService{}).In(dingo.ChildSingleton)
    }

}

// Depends adds our dependencies
func (*Module) Depends() []dingo.Module {
    return []dingo.Module{
        new(price.Module),
        new(search.Module),
    }
}

// CueConfig defines the product module configuration
func (*Module) CueConfig() string {
    // language=cue
    return `
commerce: {
    product: {
        view:  {
            template: *"product/product" | !=""
        }
        priceIsGross: bool | *true
        generateSlug: bool | *true
        slugAttributeCode: string | *"urlSlug"
        fakeservice: {
            enabled: bool | *false
            currency: *"€" | !=""
            defaultProducts: bool | *true
            if enabled {
              jsonTestDataFolder?: string & !=""
              jsonTestDataLiveSearch?: string & !=""
            }
        }
        api: {
            enabled: bool | *true
        }
        pagination: defaultPageSize: number | *commerce.pagination.defaultPageSize
    }
}`
}

type routes struct {
    controller *controller.View
}

func (r *routes) Inject(controller *controller.View) {
    r.controller = controller
}

func (r *routes) Routes(registry *web.RouterRegistry) {
    registry.HandleGet("product.view", r.controller.Get)
    h := registry.MustRoute("/product/:marketplacecode/:name.html", `product.view(marketplacecode, name, backurl?="")`)
    h.Normalize("name")
    h = registry.MustRoute("/product/:marketplacecode/:variantcode/:name.html", `product.view(marketplacecode, variantcode, name, backurl?="")`)
    h.Normalize("name")
}

type apiRoutes struct {
    apiController *controller.APIController
}

func (r *apiRoutes) Inject(apiController *controller.APIController) {
    r.apiController = apiController
}

func (r *apiRoutes) Routes(registry *web.RouterRegistry) {
    registry.MustRoute("/api/v1/products/:marketplacecode", "products.api.get")
    registry.HandleGet("products.api.get", r.apiController.Get)
}

I don't know what else to do.

Cobalt0s commented 1 year ago

Check the readme file for this project: https://github.com/i-love-flamingo/example-commerce They explain how to see all the configs used by the app (I found it useful to see all possible configuration options) and what should be included in config.yaml to resolve the "bean" for ProductService. Thats what it says in the first paragraph of the error.