github.com/goravel/framework@v1.13.9/foundation/container.go (about) 1 package foundation 2 3 import ( 4 "fmt" 5 "sync" 6 7 "github.com/gookit/color" 8 9 "github.com/goravel/framework/auth" 10 "github.com/goravel/framework/cache" 11 "github.com/goravel/framework/config" 12 "github.com/goravel/framework/console" 13 authcontract "github.com/goravel/framework/contracts/auth" 14 accesscontract "github.com/goravel/framework/contracts/auth/access" 15 cachecontract "github.com/goravel/framework/contracts/cache" 16 configcontract "github.com/goravel/framework/contracts/config" 17 consolecontract "github.com/goravel/framework/contracts/console" 18 cryptcontract "github.com/goravel/framework/contracts/crypt" 19 ormcontract "github.com/goravel/framework/contracts/database/orm" 20 seerdercontract "github.com/goravel/framework/contracts/database/seeder" 21 eventcontract "github.com/goravel/framework/contracts/event" 22 filesystemcontract "github.com/goravel/framework/contracts/filesystem" 23 foundationcontract "github.com/goravel/framework/contracts/foundation" 24 grpccontract "github.com/goravel/framework/contracts/grpc" 25 hashcontract "github.com/goravel/framework/contracts/hash" 26 httpcontract "github.com/goravel/framework/contracts/http" 27 logcontract "github.com/goravel/framework/contracts/log" 28 mailcontract "github.com/goravel/framework/contracts/mail" 29 queuecontract "github.com/goravel/framework/contracts/queue" 30 routecontract "github.com/goravel/framework/contracts/route" 31 schedulecontract "github.com/goravel/framework/contracts/schedule" 32 testingcontract "github.com/goravel/framework/contracts/testing" 33 validationcontract "github.com/goravel/framework/contracts/validation" 34 "github.com/goravel/framework/crypt" 35 "github.com/goravel/framework/database" 36 "github.com/goravel/framework/event" 37 "github.com/goravel/framework/filesystem" 38 "github.com/goravel/framework/grpc" 39 "github.com/goravel/framework/hash" 40 "github.com/goravel/framework/http" 41 goravellog "github.com/goravel/framework/log" 42 "github.com/goravel/framework/mail" 43 "github.com/goravel/framework/queue" 44 "github.com/goravel/framework/route" 45 "github.com/goravel/framework/schedule" 46 "github.com/goravel/framework/testing" 47 "github.com/goravel/framework/validation" 48 ) 49 50 type instance struct { 51 concrete any 52 shared bool 53 } 54 55 type Container struct { 56 bindings sync.Map 57 instances sync.Map 58 } 59 60 func NewContainer() *Container { 61 return &Container{} 62 } 63 64 func (c *Container) Bind(key any, callback func(app foundationcontract.Application) (any, error)) { 65 c.bindings.Store(key, instance{concrete: callback, shared: false}) 66 } 67 68 func (c *Container) BindWith(key any, callback func(app foundationcontract.Application, parameters map[string]any) (any, error)) { 69 c.bindings.Store(key, instance{concrete: callback, shared: false}) 70 } 71 72 func (c *Container) Instance(key any, ins any) { 73 c.bindings.Store(key, instance{concrete: ins, shared: true}) 74 } 75 76 func (c *Container) Make(key any) (any, error) { 77 return c.make(key, nil) 78 } 79 80 func (c *Container) MakeArtisan() consolecontract.Artisan { 81 instance, err := c.Make(console.Binding) 82 if err != nil { 83 color.Redln(err) 84 return nil 85 } 86 87 return instance.(consolecontract.Artisan) 88 } 89 90 func (c *Container) MakeAuth() authcontract.Auth { 91 instance, err := c.Make(auth.BindingAuth) 92 if err != nil { 93 color.Redln(err) 94 return nil 95 } 96 97 return instance.(authcontract.Auth) 98 } 99 100 func (c *Container) MakeCache() cachecontract.Cache { 101 instance, err := c.Make(cache.Binding) 102 if err != nil { 103 color.Redln(err) 104 return nil 105 } 106 107 return instance.(cachecontract.Cache) 108 } 109 110 func (c *Container) MakeConfig() configcontract.Config { 111 instance, err := c.Make(config.Binding) 112 if err != nil { 113 color.Redln(err) 114 return nil 115 } 116 117 return instance.(configcontract.Config) 118 } 119 120 func (c *Container) MakeCrypt() cryptcontract.Crypt { 121 instance, err := c.Make(crypt.Binding) 122 if err != nil { 123 color.Redln(err) 124 return nil 125 } 126 127 return instance.(cryptcontract.Crypt) 128 } 129 130 func (c *Container) MakeEvent() eventcontract.Instance { 131 instance, err := c.Make(event.Binding) 132 if err != nil { 133 color.Redln(err) 134 return nil 135 } 136 137 return instance.(eventcontract.Instance) 138 } 139 140 func (c *Container) MakeGate() accesscontract.Gate { 141 instance, err := c.Make(auth.BindingGate) 142 if err != nil { 143 color.Redln(err) 144 return nil 145 } 146 147 return instance.(accesscontract.Gate) 148 } 149 150 func (c *Container) MakeGrpc() grpccontract.Grpc { 151 instance, err := c.Make(grpc.Binding) 152 if err != nil { 153 color.Redln(err) 154 return nil 155 } 156 157 return instance.(grpccontract.Grpc) 158 } 159 160 func (c *Container) MakeHash() hashcontract.Hash { 161 instance, err := c.Make(hash.Binding) 162 if err != nil { 163 color.Redln(err) 164 return nil 165 } 166 167 return instance.(hashcontract.Hash) 168 } 169 170 func (c *Container) MakeLog() logcontract.Log { 171 instance, err := c.Make(goravellog.Binding) 172 if err != nil { 173 color.Redln(err) 174 return nil 175 } 176 177 return instance.(logcontract.Log) 178 } 179 180 func (c *Container) MakeMail() mailcontract.Mail { 181 instance, err := c.Make(mail.Binding) 182 if err != nil { 183 color.Redln(err) 184 return nil 185 } 186 187 return instance.(mailcontract.Mail) 188 } 189 190 func (c *Container) MakeOrm() ormcontract.Orm { 191 instance, err := c.Make(database.BindingOrm) 192 if err != nil { 193 color.Redln(err) 194 return nil 195 } 196 197 return instance.(ormcontract.Orm) 198 } 199 200 func (c *Container) MakeQueue() queuecontract.Queue { 201 instance, err := c.Make(queue.Binding) 202 if err != nil { 203 color.Redln(err) 204 return nil 205 } 206 207 return instance.(queuecontract.Queue) 208 } 209 210 func (c *Container) MakeRateLimiter() httpcontract.RateLimiter { 211 instance, err := c.Make(http.BindingRateLimiter) 212 if err != nil { 213 color.Redln(err) 214 return nil 215 } 216 217 return instance.(httpcontract.RateLimiter) 218 } 219 220 func (c *Container) MakeRoute() routecontract.Route { 221 instance, err := c.Make(route.Binding) 222 if err != nil { 223 color.Redln(err) 224 return nil 225 } 226 227 return instance.(routecontract.Route) 228 } 229 230 func (c *Container) MakeSchedule() schedulecontract.Schedule { 231 instance, err := c.Make(schedule.Binding) 232 if err != nil { 233 color.Redln(err) 234 return nil 235 } 236 237 return instance.(schedulecontract.Schedule) 238 } 239 240 func (c *Container) MakeStorage() filesystemcontract.Storage { 241 instance, err := c.Make(filesystem.Binding) 242 if err != nil { 243 color.Redln(err) 244 return nil 245 } 246 247 return instance.(filesystemcontract.Storage) 248 } 249 250 func (c *Container) MakeTesting() testingcontract.Testing { 251 instance, err := c.Make(testing.Binding) 252 if err != nil { 253 color.Redln(err) 254 return nil 255 } 256 257 return instance.(testingcontract.Testing) 258 } 259 260 func (c *Container) MakeValidation() validationcontract.Validation { 261 instance, err := c.Make(validation.Binding) 262 if err != nil { 263 color.Redln(err) 264 return nil 265 } 266 267 return instance.(validationcontract.Validation) 268 } 269 270 func (c *Container) MakeView() httpcontract.View { 271 instance, err := c.Make(http.BindingView) 272 if err != nil { 273 color.Redln(err) 274 return nil 275 } 276 277 return instance.(httpcontract.View) 278 } 279 280 func (c *Container) MakeSeeder() seerdercontract.Facade { 281 instance, err := c.Make(database.BindingSeeder) 282 283 if err != nil { 284 color.Redln(err) 285 return nil 286 } 287 288 return instance.(seerdercontract.Facade) 289 } 290 291 func (c *Container) MakeWith(key any, parameters map[string]any) (any, error) { 292 return c.make(key, parameters) 293 } 294 295 func (c *Container) Singleton(key any, callback func(app foundationcontract.Application) (any, error)) { 296 c.bindings.Store(key, instance{concrete: callback, shared: true}) 297 } 298 299 func (c *Container) make(key any, parameters map[string]any) (any, error) { 300 binding, ok := c.bindings.Load(key) 301 if !ok { 302 return nil, fmt.Errorf("binding not found: %+v", key) 303 } 304 305 if parameters == nil { 306 instance, ok := c.instances.Load(key) 307 if ok { 308 return instance, nil 309 } 310 } 311 312 bindingImpl := binding.(instance) 313 switch concrete := bindingImpl.concrete.(type) { 314 case func(app foundationcontract.Application) (any, error): 315 concreteImpl, err := concrete(App) 316 if err != nil { 317 return nil, err 318 } 319 if bindingImpl.shared { 320 c.instances.Store(key, concreteImpl) 321 } 322 323 return concreteImpl, nil 324 case func(app foundationcontract.Application, parameters map[string]any) (any, error): 325 concreteImpl, err := concrete(App, parameters) 326 if err != nil { 327 return nil, err 328 } 329 330 return concreteImpl, nil 331 default: 332 c.instances.Store(key, concrete) 333 334 return concrete, nil 335 } 336 }