@apso/cli 0.35.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -51,14 +51,48 @@ func (h *<%= it.entityName %>Handler) RegisterRoutes(r *gin.RouterGroup) {
51
51
  // @Param join query string false "Join: relation or relation||field1,field2 (repeatable)"
52
52
  // @Param limit query int false "Page size (max 200)" default(25)
53
53
  // @Param page query int false "Page number" default(1)
54
+ // @Param select query string false "PostgREST projection: col,alias:col"
55
+ // @Param order query string false "PostgREST order: col.asc|desc[.nullsfirst|nullslast]"
56
+ // @Param offset query int false "PostgREST row offset (bare-array response)"
54
57
  // @Success 200 {object} dto.<%= it.entityName %>PaginatedResponse
58
+ // @Failure 400 {object} map[string]string
55
59
  // @Failure 500 {object} map[string]string
56
60
  // @Router /<%= it.kebabPluralName %> [get]
61
+ //
62
+ // Dual-dialect: the nestjsx dialect (filter/sort/join/fields/or) returns the
63
+ // {data,count,total,page,pageCount} envelope; the PostgREST dialect
64
+ // (select/order/col=op.value/or=()/and=()) returns a bare JSON array. The
65
+ // dialect is chosen by the X-Crud-Dialect header or the query-param shape.
57
66
  func (h *<%= it.entityName %>Handler) FindAll(c *gin.Context) {
58
- opts := utils.ParseQueryParams(c.Request.URL.Query())
67
+ opts, err := utils.ParseQuery(c.Request.URL.Query(), c.GetHeader("X-Crud-Dialect"))
68
+ if err != nil {
69
+ // A malformed dialect request (bad header, ambiguous mix, bad operator)
70
+ // is a client error, not a 500 (apso #60).
71
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
72
+ return
73
+ }
74
+
75
+ // PostgREST dialect => bare JSON array (no envelope) — apso #58.
76
+ if opts.Bare {
77
+ rows, err := h.service.FindAllBare(c.Request.Context(), opts)
78
+ if err != nil {
79
+ if qe, ok := utils.AsQueryError(err); ok {
80
+ c.JSON(http.StatusBadRequest, gin.H{"error": qe.Error()})
81
+ return
82
+ }
83
+ c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
84
+ return
85
+ }
86
+ c.JSON(http.StatusOK, rows)
87
+ return
88
+ }
59
89
 
60
90
  result, err := h.service.FindAll(c.Request.Context(), opts)
61
91
  if err != nil {
92
+ if qe, ok := utils.AsQueryError(err); ok {
93
+ c.JSON(http.StatusBadRequest, gin.H{"error": qe.Error()})
94
+ return
95
+ }
62
96
  c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
63
97
  return
64
98
  }
@@ -39,6 +39,7 @@ func New<%= it.entityName %>Service(db *gorm.DB) *<%= it.entityName %>Service {
39
39
  }
40
40
 
41
41
  // FindAll retrieves a paginated list of <%= it.pluralName %> with filtering, sorting, and joins.
42
+ // Used by the nestjsx dialect ({data,count,total,page,pageCount} envelope).
42
43
  func (s *<%= it.entityName %>Service) FindAll(ctx context.Context, opts utils.QueryOptions) (*dto.<%= it.entityName %>PaginatedResponse, error) {
43
44
  var items []models.<%= it.entityName %>
44
45
 
@@ -47,7 +48,10 @@ func (s *<%= it.entityName %>Service) FindAll(ctx context.Context, opts utils.Qu
47
48
  query = query.Preload("<%= assoc.referenceName || assoc.name %>")
48
49
  <% }) %>
49
50
 
50
- query, total, pageCount := utils.ApplyQuery(query, opts, AllowedFields<%= it.entityName %>)
51
+ query, total, pageCount, err := utils.ApplyQueryE(query, opts, AllowedFields<%= it.entityName %>)
52
+ if err != nil {
53
+ return nil, err
54
+ }
51
55
 
52
56
  if err := query.Find(&items).Error; err != nil {
53
57
  return nil, err
@@ -67,6 +71,34 @@ func (s *<%= it.entityName %>Service) FindAll(ctx context.Context, opts utils.Qu
67
71
  }, nil
68
72
  }
69
73
 
74
+ // FindAllBare retrieves <%= it.pluralName %> as a bare slice (no pagination
75
+ // envelope), used by the PostgREST dialect (apso #58). An unknown filter/sort/
76
+ // select column surfaces as a *utils.QueryError so the handler answers 400
77
+ // rather than 500 (apso #60).
78
+ func (s *<%= it.entityName %>Service) FindAllBare(ctx context.Context, opts utils.QueryOptions) ([]dto.<%= it.entityName %>Response, error) {
79
+ var items []models.<%= it.entityName %>
80
+
81
+ query := s.db.WithContext(ctx).Model(&models.<%= it.entityName %>{})
82
+ <% it.associations.filter(a => a.eager).forEach((assoc) => { %>
83
+ query = query.Preload("<%= assoc.referenceName || assoc.name %>")
84
+ <% }) %>
85
+
86
+ query, _, _, err := utils.ApplyQueryE(query, opts, AllowedFields<%= it.entityName %>)
87
+ if err != nil {
88
+ return nil, err
89
+ }
90
+
91
+ if err := query.Find(&items).Error; err != nil {
92
+ return nil, err
93
+ }
94
+
95
+ response := make([]dto.<%= it.entityName %>Response, len(items))
96
+ for i, item := range items {
97
+ response[i] = s.toResponse(&item)
98
+ }
99
+ return response, nil
100
+ }
101
+
70
102
  // FindOne retrieves a single <%= it.entityName %> by ID
71
103
  func (s *<%= it.entityName %>Service) FindOne(ctx context.Context, id string) (*dto.<%= it.entityName %>Response, error) {
72
104
  var item models.<%= it.entityName %>