You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/references/gofrcli/page.md
+353Lines changed: 353 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,7 @@ Managing repetitive tasks and maintaining consistency across large-scale applica
6
6
7
7
* All-in-one command-line tool designed specifically for GoFr applications
8
8
* Simplifies **database migrations** management
9
+
***Store Layer Generator** for type-safe data access code from YAML configurations
9
10
* Abstracts **tracing**, **metrics** and structured **logging** for GoFr's gRPC server/client
10
11
* Enforces standard **GoFr conventions** in new projects
11
12
@@ -206,3 +207,355 @@ func main() {
206
207
```
207
208
For detailed instruction on setting up a gRPC server with GoFr see the [gRPC Client Documentation](https://gofr.dev/docs/advanced-guide/grpc#generating-tracing-enabled-g-rpc-client-using)
208
209
For more examples refer [gRPC Examples](https://github.com/gofr-dev/gofr/tree/main/examples/grpc)
210
+
211
+
---
212
+
## 4. ***`store`***
213
+
214
+
> **Available since:**`gofr-cli`**v0.8.1**
215
+
216
+
The `gofr store` command is a code generator that creates type-safe data access layers from YAML configuration files. It eliminates boilerplate code while maintaining GoFr's best practices for observability and context management.
217
+
218
+
### **Features**
219
+
220
+
***YAML-Driven Configuration**: Define your data models and queries in a simple, declarative format.
221
+
***Type-Safe Code Generation**: Generates Go interfaces and implementation boilerplates.
222
+
***GoFr Context Integration**: Generated methods work with `*gofr.Context` for built-in observability.
223
+
***Multiple Stores**: Define all stores in a single YAML file — each gets its own directory.
224
+
***Store Registry**: Centralized factory management of all generated stores via `stores/all.go`.
225
+
226
+
### **Commands**
227
+
228
+
#### **Initialize Store Configuration**
229
+
230
+
Create a new store directory and a `store.yaml` configuration template. **The `-name` flag is required.**
231
+
232
+
```bash
233
+
gofr store init -name=<store-name>
234
+
```
235
+
236
+
**Example:**
237
+
```bash
238
+
gofr store init -name=user
239
+
```
240
+
241
+
This creates the following structure:
242
+
-`stores/store.yaml` — Configuration file template (shared across all stores).
243
+
-`stores/all.go` — Store registry factory (auto-generated, DO NOT EDIT).
244
+
-`stores/user/interface.go` — Initial interface stub (DO NOT EDIT — regenerated by `generate`).
You can define all stores in a single YAML file. Each store gets its own output directory and all are registered into the same `stores/all.go` registry.
359
+
360
+
```yaml
361
+
version: "1.0"
362
+
363
+
stores:
364
+
- name: "user"
365
+
package: "user"
366
+
output_dir: "stores/user"
367
+
interface: "UserStore"
368
+
implementation: "userStore"
369
+
queries: [...]
370
+
371
+
- name: "product"
372
+
package: "product"
373
+
output_dir: "stores/product"
374
+
interface: "ProductStore"
375
+
implementation: "productStore"
376
+
queries: [...]
377
+
378
+
models:
379
+
- name: "User"
380
+
fields: [...]
381
+
- name: "Product"
382
+
fields: [...]
383
+
```
384
+
385
+
**Generated structure:**
386
+
```
387
+
stores/
388
+
├── all.go
389
+
├── user/
390
+
│ ├── interface.go
391
+
│ ├── userStore.go
392
+
│ └── user.go
393
+
└── product/
394
+
├── interface.go
395
+
├── productStore.go
396
+
└── product.go
397
+
```
398
+
399
+
**Using the registry with multiple stores:**
400
+
```go
401
+
import (
402
+
"your-project/stores"
403
+
"your-project/stores/user"
404
+
"your-project/stores/product"
405
+
)
406
+
407
+
// stores.GetStore returns a factory-created instance
> **💡 Note:**`stores.All()` returns a `map[string]func() any` — a map of **factory functions**, not active instances. `stores.GetStore(name)` calls the factory for you and returns the instance.
413
+
414
+
---
415
+
416
+
### **Configuration Reference**
417
+
418
+
#### **Store Configuration**
419
+
420
+
| Field | Description | Required |
421
+
|-------|-------------|----------|
422
+
|`name`| Store identifier used in the registry key. |**Yes**|
423
+
|`package`| Go package name for generated code. |**Yes**|
424
+
|`output_dir`| Directory path where files will be generated. | Optional (defaults to `stores/<name>`) |
425
+
|`interface`| Interface name — **recommended: `<Name>Store`** (e.g., `UserStore`). | Optional (defaults to `<Name>Store`) |
426
+
|`implementation`| Private struct name for the implementation (e.g., `userStore`). | Optional (defaults to `<name>Store`) |
427
+
|`queries`| List of database queries. | Optional |
428
+
429
+
> **⚠️ Naming Convention:** The registry (`stores/all.go`) uses a hardcoded `<Name>Store` pattern when generating constructor calls (e.g., `NewUserStore()`). Always name your interface as `<Name>Store` to avoid compilation errors.
430
+
431
+
#### **Query Types**
432
+
433
+
***`select`** — SELECT queries.
434
+
***`insert`** — INSERT queries.
435
+
***`update`** — UPDATE queries.
436
+
***`delete`** — DELETE queries.
437
+
438
+
#### **Return Types**
439
+
440
+
***`single`** — Returns `(Model, error)`.
441
+
***`multiple`** — Returns `([]Model, error)`.
442
+
***`count`** — Returns `(int64, error)`.
443
+
***`custom`** — Returns `(any, error)`.
444
+
445
+
#### **Query Parameters**
446
+
447
+
```yaml
448
+
params:
449
+
- name: "id"
450
+
type: "int64"
451
+
- name: "email"
452
+
type: "string"
453
+
```
454
+
455
+
Supported parameter types include all Go primitive types, `time.Time`, and pointer types (e.g., `*int64`).
func (s *userStore) GetAllUsers(ctx *gofr.Context) ([]User, error) {
540
+
// TODO: Implement using ctx.SQL()
541
+
return []User{}, nil
542
+
}
543
+
```
544
+
545
+
---
546
+
547
+
### **Best Practices**
548
+
549
+
1. **Implement the TODOs**: The generator creates method **signatures and boilerplate only**. You must fill in the `// TODO: Implement` sections with actual SQL execution using `ctx.SQL()` methods.
550
+
2. **Use `<Name>Store` Interface Names**: The registry assumes this convention. E.g., `interface: "UserStore"` results in the constructor `NewUserStore()` and type assertion `.(user.UserStore)`.
551
+
3. **One YAML, Many Stores**: Define all your stores in a single `store.yaml` to keep your data access layer centrally configured.
552
+
4. **Know Which Files Are Auto-Generated**: Only `interface.go` and `all.go` are marked `DO NOT EDIT` and are overwritten on every `gofr store generate`. The implementation stub (`<name>.go`) created by `gofr store init` is editable — this is where you add your SQL logic. The `userStore.go` generated by `gofr store generate` is also editable boilerplate.
553
+
5. **Version Control**: Always commit your `store.yaml`. Re-run `gofr store generate` after any configuration change to sync the generated interfaces.
554
+
555
+
---
556
+
557
+
### **Complete Example**
558
+
559
+
For a complete working example of the store generator, see the [store example](https://github.com/gofr-dev/gofr-cli/tree/main/store/example.yaml) in the gofr-cli repository.
560
+
561
+
For detailed configuration options and advanced usage, refer to the [Store Generator README](https://github.com/gofr-dev/gofr-cli/blob/main/store/README.md).
0 commit comments