@apso/cli 0.7.4 → 0.8.3

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.
Files changed (203) hide show
  1. package/dist/autogen/index.d.ts +2 -0
  2. package/dist/autogen/index.js +3 -0
  3. package/dist/commands/server/new.d.ts +4 -1
  4. package/dist/commands/server/new.js +115 -22
  5. package/dist/commands/server/scaffold.d.ts +10 -0
  6. package/dist/commands/server/scaffold.js +200 -10
  7. package/dist/lib/api/client.d.ts +65 -0
  8. package/dist/lib/api/client.js +305 -0
  9. package/dist/lib/api/index.d.ts +8 -0
  10. package/dist/lib/api/index.js +22 -0
  11. package/dist/lib/api/services.d.ts +166 -0
  12. package/dist/lib/api/services.js +202 -0
  13. package/dist/lib/api/types.d.ts +212 -0
  14. package/dist/lib/api/types.js +7 -0
  15. package/dist/lib/apsorc-parser.d.ts +3 -0
  16. package/dist/lib/apsorc-parser.js +4 -0
  17. package/dist/lib/config/index.d.ts +8 -0
  18. package/dist/lib/config/index.js +17 -0
  19. package/dist/lib/config/manager.d.ts +127 -0
  20. package/dist/lib/config/manager.js +304 -0
  21. package/dist/lib/config/paths.d.ts +65 -0
  22. package/dist/lib/config/paths.js +127 -0
  23. package/dist/lib/config/types.d.ts +230 -0
  24. package/dist/lib/config/types.js +30 -0
  25. package/dist/lib/generators/base.d.ts +93 -0
  26. package/dist/lib/generators/base.js +90 -0
  27. package/dist/lib/generators/go.d.ts +37 -0
  28. package/dist/lib/generators/go.js +340 -0
  29. package/dist/lib/generators/index.d.ts +21 -0
  30. package/dist/lib/generators/index.js +51 -0
  31. package/dist/lib/generators/python.d.ts +21 -0
  32. package/dist/lib/generators/python.js +253 -0
  33. package/dist/lib/generators/typescript.d.ts +25 -0
  34. package/dist/lib/generators/typescript.js +373 -0
  35. package/dist/lib/index.d.ts +2 -0
  36. package/dist/lib/index.js +9 -1
  37. package/dist/lib/templates/entities/entity-col-timestamp.eta +9 -2
  38. package/dist/lib/templates/entities/entity-col-timestamptz.eta +9 -2
  39. package/dist/lib/templates/entities/entity.eta +16 -3
  40. package/dist/lib/templates/go/dto/dto-col-array.eta +7 -0
  41. package/dist/lib/templates/go/dto/dto-col-boolean.eta +7 -0
  42. package/dist/lib/templates/go/dto/dto-col-date.eta +7 -0
  43. package/dist/lib/templates/go/dto/dto-col-decimal.eta +7 -0
  44. package/dist/lib/templates/go/dto/dto-col-enum.eta +8 -0
  45. package/dist/lib/templates/go/dto/dto-col-float.eta +7 -0
  46. package/dist/lib/templates/go/dto/dto-col-integer.eta +7 -0
  47. package/dist/lib/templates/go/dto/dto-col-json.eta +7 -0
  48. package/dist/lib/templates/go/dto/dto-col-jsonb.eta +7 -0
  49. package/dist/lib/templates/go/dto/dto-col-numeric.eta +7 -0
  50. package/dist/lib/templates/go/dto/dto-col-string.eta +7 -0
  51. package/dist/lib/templates/go/dto/dto-col-text.eta +7 -0
  52. package/dist/lib/templates/go/dto/dto-col-timestamp.eta +7 -0
  53. package/dist/lib/templates/go/dto/dto-col-timestamptz.eta +7 -0
  54. package/dist/lib/templates/go/dto/dto-col-uuid.eta +7 -0
  55. package/dist/lib/templates/go/dto/dto-col-varchar.eta +7 -0
  56. package/dist/lib/templates/go/dto/dto.eta +78 -0
  57. package/dist/lib/templates/go/enums.eta +44 -0
  58. package/dist/lib/templates/go/handlers/handler.eta +212 -0
  59. package/dist/lib/templates/go/header.eta +3 -0
  60. package/dist/lib/templates/go/index-module.eta +53 -0
  61. package/dist/lib/templates/go/middleware/auth.eta +101 -0
  62. package/dist/lib/templates/go/models/model-col-array.eta +1 -0
  63. package/dist/lib/templates/go/models/model-col-boolean.eta +1 -0
  64. package/dist/lib/templates/go/models/model-col-date.eta +1 -0
  65. package/dist/lib/templates/go/models/model-col-decimal.eta +1 -0
  66. package/dist/lib/templates/go/models/model-col-enum.eta +2 -0
  67. package/dist/lib/templates/go/models/model-col-float.eta +1 -0
  68. package/dist/lib/templates/go/models/model-col-integer.eta +1 -0
  69. package/dist/lib/templates/go/models/model-col-json.eta +1 -0
  70. package/dist/lib/templates/go/models/model-col-jsonb.eta +1 -0
  71. package/dist/lib/templates/go/models/model-col-numeric.eta +1 -0
  72. package/dist/lib/templates/go/models/model-col-string.eta +1 -0
  73. package/dist/lib/templates/go/models/model-col-text.eta +1 -0
  74. package/dist/lib/templates/go/models/model-col-timestamp.eta +1 -0
  75. package/dist/lib/templates/go/models/model-col-timestamptz.eta +1 -0
  76. package/dist/lib/templates/go/models/model-col-uuid.eta +1 -0
  77. package/dist/lib/templates/go/models/model-col-varchar.eta +1 -0
  78. package/dist/lib/templates/go/models/model.eta +53 -0
  79. package/dist/lib/templates/go/services/service.eta +190 -0
  80. package/dist/lib/templates/python/enums.eta +10 -0
  81. package/dist/lib/templates/python/header.eta +6 -0
  82. package/dist/lib/templates/python/index-module.eta +18 -0
  83. package/dist/lib/templates/python/models/model-col-array.eta +4 -0
  84. package/dist/lib/templates/python/models/model-col-boolean.eta +5 -0
  85. package/dist/lib/templates/python/models/model-col-date.eta +4 -0
  86. package/dist/lib/templates/python/models/model-col-decimal.eta +4 -0
  87. package/dist/lib/templates/python/models/model-col-enum.eta +16 -0
  88. package/dist/lib/templates/python/models/model-col-float.eta +5 -0
  89. package/dist/lib/templates/python/models/model-col-integer.eta +6 -0
  90. package/dist/lib/templates/python/models/model-col-json.eta +4 -0
  91. package/dist/lib/templates/python/models/model-col-jsonb.eta +4 -0
  92. package/dist/lib/templates/python/models/model-col-numeric.eta +4 -0
  93. package/dist/lib/templates/python/models/model-col-string.eta +6 -0
  94. package/dist/lib/templates/python/models/model-col-text.eta +6 -0
  95. package/dist/lib/templates/python/models/model-col-timestamp.eta +11 -0
  96. package/dist/lib/templates/python/models/model-col-timestamptz.eta +11 -0
  97. package/dist/lib/templates/python/models/model-col-uuid.eta +5 -0
  98. package/dist/lib/templates/python/models/model-col-varchar.eta +6 -0
  99. package/dist/lib/templates/python/models/model.eta +124 -0
  100. package/dist/lib/templates/python/routers/router.eta +206 -0
  101. package/dist/lib/templates/python/schemas/schema-col-array.eta +1 -0
  102. package/dist/lib/templates/python/schemas/schema-col-boolean.eta +1 -0
  103. package/dist/lib/templates/python/schemas/schema-col-date.eta +1 -0
  104. package/dist/lib/templates/python/schemas/schema-col-decimal.eta +1 -0
  105. package/dist/lib/templates/python/schemas/schema-col-enum.eta +6 -0
  106. package/dist/lib/templates/python/schemas/schema-col-float.eta +1 -0
  107. package/dist/lib/templates/python/schemas/schema-col-integer.eta +1 -0
  108. package/dist/lib/templates/python/schemas/schema-col-json.eta +1 -0
  109. package/dist/lib/templates/python/schemas/schema-col-jsonb.eta +1 -0
  110. package/dist/lib/templates/python/schemas/schema-col-numeric.eta +1 -0
  111. package/dist/lib/templates/python/schemas/schema-col-string.eta +1 -0
  112. package/dist/lib/templates/python/schemas/schema-col-text.eta +1 -0
  113. package/dist/lib/templates/python/schemas/schema-col-timestamp.eta +1 -0
  114. package/dist/lib/templates/python/schemas/schema-col-timestamptz.eta +1 -0
  115. package/dist/lib/templates/python/schemas/schema-col-uuid.eta +1 -0
  116. package/dist/lib/templates/python/schemas/schema-col-varchar.eta +1 -0
  117. package/dist/lib/templates/python/schemas/schema.eta +87 -0
  118. package/dist/lib/templates/python/services/service.eta +163 -0
  119. package/dist/lib/templates/rest/controller-rest.eta +13 -12
  120. package/dist/lib/templates/rest/dto-rest.eta +173 -59
  121. package/dist/lib/types/generator.d.ts +241 -0
  122. package/dist/lib/types/generator.js +2 -0
  123. package/dist/lib/types/index.d.ts +1 -0
  124. package/dist/lib/utils/casing.d.ts +1 -0
  125. package/dist/lib/utils/casing.js +11 -1
  126. package/oclif.manifest.json +32 -3
  127. package/package.json +4 -2
  128. package/dist/lib/utils/relationships/parse.spec.d.ts +0 -1
  129. package/dist/lib/utils/relationships/parse.spec.js +0 -402
  130. package/dist/tests/templates/entities/types/array-template.spec.d.ts +0 -1
  131. package/dist/tests/templates/entities/types/array-template.spec.js +0 -82
  132. package/dist/tests/templates/entities/types/bigint-template.spec.d.ts +0 -1
  133. package/dist/tests/templates/entities/types/bigint-template.spec.js +0 -82
  134. package/dist/tests/templates/entities/types/boolean-template.spec.d.ts +0 -1
  135. package/dist/tests/templates/entities/types/boolean-template.spec.js +0 -77
  136. package/dist/tests/templates/entities/types/bytea-template.spec.d.ts +0 -1
  137. package/dist/tests/templates/entities/types/bytea-template.spec.js +0 -68
  138. package/dist/tests/templates/entities/types/char-template.spec.d.ts +0 -1
  139. package/dist/tests/templates/entities/types/char-template.spec.js +0 -68
  140. package/dist/tests/templates/entities/types/date-template.spec.d.ts +0 -1
  141. package/dist/tests/templates/entities/types/date-template.spec.js +0 -56
  142. package/dist/tests/templates/entities/types/decimal-field-validation.spec.d.ts +0 -1
  143. package/dist/tests/templates/entities/types/decimal-field-validation.spec.js +0 -100
  144. package/dist/tests/templates/entities/types/decimal-template.spec.d.ts +0 -1
  145. package/dist/tests/templates/entities/types/decimal-template.spec.js +0 -86
  146. package/dist/tests/templates/entities/types/double-template.spec.d.ts +0 -1
  147. package/dist/tests/templates/entities/types/double-template.spec.js +0 -70
  148. package/dist/tests/templates/entities/types/enum-template.spec.d.ts +0 -1
  149. package/dist/tests/templates/entities/types/enum-template.spec.js +0 -85
  150. package/dist/tests/templates/entities/types/float-template.spec.d.ts +0 -1
  151. package/dist/tests/templates/entities/types/float-template.spec.js +0 -70
  152. package/dist/tests/templates/entities/types/geometry-template.spec.d.ts +0 -1
  153. package/dist/tests/templates/entities/types/geometry-template.spec.js +0 -58
  154. package/dist/tests/templates/entities/types/inet-template.spec.d.ts +0 -1
  155. package/dist/tests/templates/entities/types/inet-template.spec.js +0 -69
  156. package/dist/tests/templates/entities/types/int4range-template.spec.d.ts +0 -1
  157. package/dist/tests/templates/entities/types/int4range-template.spec.js +0 -72
  158. package/dist/tests/templates/entities/types/integer-template.spec.d.ts +0 -1
  159. package/dist/tests/templates/entities/types/integer-template.spec.js +0 -79
  160. package/dist/tests/templates/entities/types/interval-template.spec.d.ts +0 -1
  161. package/dist/tests/templates/entities/types/interval-template.spec.js +0 -68
  162. package/dist/tests/templates/entities/types/json-plain-template.spec.d.ts +0 -1
  163. package/dist/tests/templates/entities/types/json-plain-template.spec.js +0 -54
  164. package/dist/tests/templates/entities/types/json-template.spec.d.ts +0 -1
  165. package/dist/tests/templates/entities/types/json-template.spec.js +0 -40
  166. package/dist/tests/templates/entities/types/jsonb-template.spec.d.ts +0 -1
  167. package/dist/tests/templates/entities/types/jsonb-template.spec.js +0 -40
  168. package/dist/tests/templates/entities/types/money-template.spec.d.ts +0 -1
  169. package/dist/tests/templates/entities/types/money-template.spec.js +0 -68
  170. package/dist/tests/templates/entities/types/numeric-template.spec.d.ts +0 -1
  171. package/dist/tests/templates/entities/types/numeric-template.spec.js +0 -84
  172. package/dist/tests/templates/entities/types/point-template.spec.d.ts +0 -1
  173. package/dist/tests/templates/entities/types/point-template.spec.js +0 -64
  174. package/dist/tests/templates/entities/types/polygon-template.spec.d.ts +0 -1
  175. package/dist/tests/templates/entities/types/polygon-template.spec.js +0 -70
  176. package/dist/tests/templates/entities/types/real-template.spec.d.ts +0 -1
  177. package/dist/tests/templates/entities/types/real-template.spec.js +0 -67
  178. package/dist/tests/templates/entities/types/serial-template.spec.d.ts +0 -1
  179. package/dist/tests/templates/entities/types/serial-template.spec.js +0 -113
  180. package/dist/tests/templates/entities/types/smallint-template.spec.d.ts +0 -1
  181. package/dist/tests/templates/entities/types/smallint-template.spec.js +0 -82
  182. package/dist/tests/templates/entities/types/string-template.spec.d.ts +0 -1
  183. package/dist/tests/templates/entities/types/string-template.spec.js +0 -111
  184. package/dist/tests/templates/entities/types/text-template.spec.d.ts +0 -1
  185. package/dist/tests/templates/entities/types/text-template.spec.js +0 -70
  186. package/dist/tests/templates/entities/types/time-template.spec.d.ts +0 -1
  187. package/dist/tests/templates/entities/types/time-template.spec.js +0 -68
  188. package/dist/tests/templates/entities/types/timestamp-template.spec.d.ts +0 -1
  189. package/dist/tests/templates/entities/types/timestamp-template.spec.js +0 -74
  190. package/dist/tests/templates/entities/types/timetz-template.spec.d.ts +0 -1
  191. package/dist/tests/templates/entities/types/timetz-template.spec.js +0 -68
  192. package/dist/tests/templates/entities/types/tsvector-template.spec.d.ts +0 -1
  193. package/dist/tests/templates/entities/types/tsvector-template.spec.js +0 -55
  194. package/dist/tests/templates/entities/types/uuid-template.spec.d.ts +0 -1
  195. package/dist/tests/templates/entities/types/uuid-template.spec.js +0 -82
  196. package/dist/tests/templates/entities/types/varchar-template.spec.d.ts +0 -1
  197. package/dist/tests/templates/entities/types/varchar-template.spec.js +0 -105
  198. package/dist/tests/templates/entities/types/xml-template.spec.d.ts +0 -1
  199. package/dist/tests/templates/entities/types/xml-template.spec.js +0 -55
  200. package/dist/tests/templates/entities/uuid-entity-template.spec.d.ts +0 -1
  201. package/dist/tests/templates/entities/uuid-entity-template.spec.js +0 -277
  202. package/dist/tests/utils/relationship-deduplication.spec.d.ts +0 -1
  203. package/dist/tests/utils/relationship-deduplication.spec.js +0 -98
@@ -0,0 +1,78 @@
1
+ <%~ includeFile('../../header.eta', it) %>
2
+
3
+ package dto
4
+
5
+ import (
6
+ "time"
7
+ <% if (it.importEnums) { %>
8
+ "app/models/enums"
9
+ <% } %>
10
+ )
11
+
12
+ // <%= it.entityName %>Response represents the response DTO for <%= it.entityName %>
13
+ type <%= it.entityName %>Response struct {
14
+ <% if (it.addDefaultPKProperty) { %>
15
+ <% if (it.primaryKeyType === 'uuid') { %>
16
+ ID string `json:"id"`
17
+ <% } else { %>
18
+ ID uint `json:"id"`
19
+ <% } %>
20
+ <% } %>
21
+ <% it.columns.forEach((column) => { %>
22
+ <%~ includeFile('./dto-col-' + column.type + '.eta', { column, mode: 'response' }) %>
23
+ <% }) %>
24
+ <% if (it.createdAt) { %>
25
+ CreatedAt time.Time `json:"createdAt"`
26
+ <% } %>
27
+ <% if (it.updatedAt) { %>
28
+ UpdatedAt time.Time `json:"updatedAt"`
29
+ <% } %>
30
+ <% it.associations.forEach((assoc) => { %>
31
+ <% if (assoc.type === 'OneToMany') { %>
32
+ <%= assoc.pluralName %> []<%= assoc.name %>Response `json:"<%= assoc.camelPluralName %>,omitempty"`
33
+ <% } else if (assoc.type === 'ManyToOne') { %>
34
+ <%= assoc.referenceName || assoc.name %>ID <%= assoc.primaryKeyGoType || 'uint' %> `json:"<%= assoc.camelReferenceName || assoc.camelName %>Id"`
35
+ <%= assoc.referenceName || assoc.name %> *<%= assoc.name %>Response `json:"<%= assoc.camelReferenceName || assoc.camelName %>,omitempty"`
36
+ <% } else if (assoc.type === 'OneToOne') { %>
37
+ <% if (assoc.isOwner) { %>
38
+ <%= assoc.referenceName || assoc.name %>ID <%= assoc.primaryKeyGoType || 'uint' %> `json:"<%= assoc.camelReferenceName || assoc.camelName %>Id"`
39
+ <% } %>
40
+ <%= assoc.referenceName || assoc.name %> *<%= assoc.name %>Response `json:"<%= assoc.camelReferenceName || assoc.camelName %>,omitempty"`
41
+ <% } else if (assoc.type === 'ManyToMany') { %>
42
+ <%= assoc.pluralName %> []<%= assoc.name %>Response `json:"<%= assoc.camelPluralName %>,omitempty"`
43
+ <% } %>
44
+ <% }) %>
45
+ }
46
+
47
+ // <%= it.entityName %>Create represents the create DTO for <%= it.entityName %>
48
+ type <%= it.entityName %>Create struct {
49
+ <% it.columns.forEach((column) => { %>
50
+ <%~ includeFile('./dto-col-' + column.type + '.eta', { column, mode: 'create' }) %>
51
+ <% }) %>
52
+ <% it.associations.forEach((assoc) => { %>
53
+ <% if (assoc.type === 'ManyToOne' || (assoc.type === 'OneToOne' && assoc.isOwner)) { %>
54
+ <%= assoc.referenceName || assoc.name %>ID <%= assoc.primaryKeyGoType || 'uint' %> `json:"<%= assoc.camelReferenceName || assoc.camelName %>Id" validate:"required"`
55
+ <% } %>
56
+ <% }) %>
57
+ }
58
+
59
+ // <%= it.entityName %>Update represents the update DTO for <%= it.entityName %>
60
+ type <%= it.entityName %>Update struct {
61
+ <% it.columns.forEach((column) => { %>
62
+ <%~ includeFile('./dto-col-' + column.type + '.eta', { column, mode: 'update' }) %>
63
+ <% }) %>
64
+ <% it.associations.forEach((assoc) => { %>
65
+ <% if (assoc.type === 'ManyToOne' || (assoc.type === 'OneToOne' && assoc.isOwner)) { %>
66
+ <%= assoc.referenceName || assoc.name %>ID *<%= assoc.primaryKeyGoType || 'uint' %> `json:"<%= assoc.camelReferenceName || assoc.camelName %>Id,omitempty"`
67
+ <% } %>
68
+ <% }) %>
69
+ }
70
+
71
+ // PaginatedResponse wraps paginated results for <%= it.entityName %>
72
+ type <%= it.entityName %>PaginatedResponse struct {
73
+ Data []<%= it.entityName %>Response `json:"data"`
74
+ Total int64 `json:"total"`
75
+ Page int `json:"page"`
76
+ PageSize int `json:"pageSize"`
77
+ TotalPages int `json:"totalPages"`
78
+ }
@@ -0,0 +1,44 @@
1
+ <%~ includeFile('./header.eta', it) %>
2
+
3
+ package enums
4
+
5
+ <% it.enums.forEach((enumDef) => { %>
6
+ // <%= enumDef.name %> represents the <%= enumDef.name %> enum type
7
+ type <%= enumDef.name %> string
8
+
9
+ const (
10
+ <% enumDef.values.forEach((value, index) => { %>
11
+ <% if (index === 0) { %>
12
+ <%= enumDef.name %><%= value.pascalCase %> <%= enumDef.name %> = "<%= value.value %>"
13
+ <% } else { %>
14
+ <%= enumDef.name %><%= value.pascalCase %> <%= enumDef.name %> = "<%= value.value %>"
15
+ <% } %>
16
+ <% }) %>
17
+ )
18
+
19
+ // Valid<%= enumDef.name %>Values returns all valid values for <%= enumDef.name %>
20
+ func Valid<%= enumDef.name %>Values() []<%= enumDef.name %> {
21
+ return []<%= enumDef.name %>{
22
+ <% enumDef.values.forEach((value) => { %>
23
+ <%= enumDef.name %><%= value.pascalCase %>,
24
+ <% }) %>
25
+ }
26
+ }
27
+
28
+ // IsValid checks if the value is a valid <%= enumDef.name %>
29
+ func (e <%= enumDef.name %>) IsValid() bool {
30
+ switch e {
31
+ <% enumDef.values.forEach((value) => { %>
32
+ case <%= enumDef.name %><%= value.pascalCase %>:
33
+ return true
34
+ <% }) %>
35
+ }
36
+ return false
37
+ }
38
+
39
+ // String returns the string representation of <%= enumDef.name %>
40
+ func (e <%= enumDef.name %>) String() string {
41
+ return string(e)
42
+ }
43
+
44
+ <% }) %>
@@ -0,0 +1,212 @@
1
+ <%~ includeFile('../../header.eta', it) %>
2
+
3
+ package handlers
4
+
5
+ import (
6
+ "net/http"
7
+ "strconv"
8
+
9
+ "app/dto"
10
+ "app/services"
11
+ "github.com/gin-gonic/gin"
12
+ "github.com/go-playground/validator/v10"
13
+ )
14
+
15
+ type <%= it.entityName %>Handler struct {
16
+ service *services.<%= it.entityName %>Service
17
+ validate *validator.Validate
18
+ }
19
+
20
+ func New<%= it.entityName %>Handler(service *services.<%= it.entityName %>Service) *<%= it.entityName %>Handler {
21
+ return &<%= it.entityName %>Handler{
22
+ service: service,
23
+ validate: validator.New(),
24
+ }
25
+ }
26
+
27
+ // RegisterRoutes registers all routes for <%= it.entityName %>
28
+ func (h *<%= it.entityName %>Handler) RegisterRoutes(r *gin.RouterGroup) {
29
+ group := r.Group("/<%= it.kebabPluralName %>")
30
+ {
31
+ group.GET("", h.FindAll)
32
+ group.GET("/:id", h.FindOne)
33
+ group.POST("", h.Create)
34
+ group.PUT("/:id", h.Update)
35
+ group.PATCH("/:id", h.Update)
36
+ group.DELETE("/:id", h.Delete)
37
+ }
38
+ }
39
+
40
+ // FindAll godoc
41
+ // @Summary List all <%= it.pluralName %>
42
+ // @Description Get a paginated list of <%= it.pluralName %>
43
+ // @Tags <%= it.pluralName %>
44
+ // @Accept json
45
+ // @Produce json
46
+ // @Param page query int false "Page number" default(1)
47
+ // @Param pageSize query int false "Page size" default(10)
48
+ // @Success 200 {object} dto.<%= it.entityName %>PaginatedResponse
49
+ // @Failure 500 {object} map[string]string
50
+ // @Router /<%= it.kebabPluralName %> [get]
51
+ func (h *<%= it.entityName %>Handler) FindAll(c *gin.Context) {
52
+ page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
53
+ pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))
54
+
55
+ if page < 1 {
56
+ page = 1
57
+ }
58
+ if pageSize < 1 || pageSize > 100 {
59
+ pageSize = 10
60
+ }
61
+
62
+ result, err := h.service.FindAll(c.Request.Context(), page, pageSize)
63
+ if err != nil {
64
+ c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
65
+ return
66
+ }
67
+
68
+ c.JSON(http.StatusOK, result)
69
+ }
70
+
71
+ // FindOne godoc
72
+ // @Summary Get a <%= it.entityName %>
73
+ // @Description Get a <%= it.entityName %> by ID
74
+ // @Tags <%= it.pluralName %>
75
+ // @Accept json
76
+ // @Produce json
77
+ // @Param id path <%= it.primaryKeySwaggerType || 'integer' %> true "<%= it.entityName %> ID"
78
+ // @Success 200 {object} dto.<%= it.entityName %>Response
79
+ // @Failure 404 {object} map[string]string
80
+ // @Failure 500 {object} map[string]string
81
+ // @Router /<%= it.kebabPluralName %>/{id} [get]
82
+ func (h *<%= it.entityName %>Handler) FindOne(c *gin.Context) {
83
+ id := c.Param("id")
84
+ <% if (it.primaryKeyType === 'uuid') { %>
85
+ // UUID primary key
86
+ <% } else { %>
87
+ idInt, err := strconv.ParseUint(id, 10, 32)
88
+ if err != nil {
89
+ c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID format"})
90
+ return
91
+ }
92
+ id = strconv.FormatUint(idInt, 10)
93
+ <% } %>
94
+
95
+ result, err := h.service.FindOne(c.Request.Context(), id)
96
+ if err != nil {
97
+ c.JSON(http.StatusNotFound, gin.H{"error": "<%= it.entityName %> not found"})
98
+ return
99
+ }
100
+
101
+ c.JSON(http.StatusOK, result)
102
+ }
103
+
104
+ // Create godoc
105
+ // @Summary Create a <%= it.entityName %>
106
+ // @Description Create a new <%= it.entityName %>
107
+ // @Tags <%= it.pluralName %>
108
+ // @Accept json
109
+ // @Produce json
110
+ // @Param body body dto.<%= it.entityName %>Create true "<%= it.entityName %> data"
111
+ // @Success 201 {object} dto.<%= it.entityName %>Response
112
+ // @Failure 400 {object} map[string]string
113
+ // @Failure 500 {object} map[string]string
114
+ // @Router /<%= it.kebabPluralName %> [post]
115
+ func (h *<%= it.entityName %>Handler) Create(c *gin.Context) {
116
+ var input dto.<%= it.entityName %>Create
117
+ if err := c.ShouldBindJSON(&input); err != nil {
118
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
119
+ return
120
+ }
121
+
122
+ if err := h.validate.Struct(input); err != nil {
123
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
124
+ return
125
+ }
126
+
127
+ result, err := h.service.Create(c.Request.Context(), &input)
128
+ if err != nil {
129
+ c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
130
+ return
131
+ }
132
+
133
+ c.JSON(http.StatusCreated, result)
134
+ }
135
+
136
+ // Update godoc
137
+ // @Summary Update a <%= it.entityName %>
138
+ // @Description Update an existing <%= it.entityName %>
139
+ // @Tags <%= it.pluralName %>
140
+ // @Accept json
141
+ // @Produce json
142
+ // @Param id path <%= it.primaryKeySwaggerType || 'integer' %> true "<%= it.entityName %> ID"
143
+ // @Param body body dto.<%= it.entityName %>Update true "<%= it.entityName %> data"
144
+ // @Success 200 {object} dto.<%= it.entityName %>Response
145
+ // @Failure 400 {object} map[string]string
146
+ // @Failure 404 {object} map[string]string
147
+ // @Failure 500 {object} map[string]string
148
+ // @Router /<%= it.kebabPluralName %>/{id} [put]
149
+ func (h *<%= it.entityName %>Handler) Update(c *gin.Context) {
150
+ id := c.Param("id")
151
+ <% if (it.primaryKeyType === 'uuid') { %>
152
+ // UUID primary key
153
+ <% } else { %>
154
+ idInt, err := strconv.ParseUint(id, 10, 32)
155
+ if err != nil {
156
+ c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID format"})
157
+ return
158
+ }
159
+ id = strconv.FormatUint(idInt, 10)
160
+ <% } %>
161
+
162
+ var input dto.<%= it.entityName %>Update
163
+ if err := c.ShouldBindJSON(&input); err != nil {
164
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
165
+ return
166
+ }
167
+
168
+ if err := h.validate.Struct(input); err != nil {
169
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
170
+ return
171
+ }
172
+
173
+ result, err := h.service.Update(c.Request.Context(), id, &input)
174
+ if err != nil {
175
+ c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
176
+ return
177
+ }
178
+
179
+ c.JSON(http.StatusOK, result)
180
+ }
181
+
182
+ // Delete godoc
183
+ // @Summary Delete a <%= it.entityName %>
184
+ // @Description Delete a <%= it.entityName %> by ID
185
+ // @Tags <%= it.pluralName %>
186
+ // @Accept json
187
+ // @Produce json
188
+ // @Param id path <%= it.primaryKeySwaggerType || 'integer' %> true "<%= it.entityName %> ID"
189
+ // @Success 204
190
+ // @Failure 404 {object} map[string]string
191
+ // @Failure 500 {object} map[string]string
192
+ // @Router /<%= it.kebabPluralName %>/{id} [delete]
193
+ func (h *<%= it.entityName %>Handler) Delete(c *gin.Context) {
194
+ id := c.Param("id")
195
+ <% if (it.primaryKeyType === 'uuid') { %>
196
+ // UUID primary key
197
+ <% } else { %>
198
+ idInt, err := strconv.ParseUint(id, 10, 32)
199
+ if err != nil {
200
+ c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID format"})
201
+ return
202
+ }
203
+ id = strconv.FormatUint(idInt, 10)
204
+ <% } %>
205
+
206
+ if err := h.service.Delete(c.Request.Context(), id); err != nil {
207
+ c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
208
+ return
209
+ }
210
+
211
+ c.Status(http.StatusNoContent)
212
+ }
@@ -0,0 +1,3 @@
1
+ // Code generated by APSO CLI. DO NOT EDIT.
2
+ // This file is auto-generated - any changes will be overwritten.
3
+ // Generated at: <%= new Date().toISOString() %>
@@ -0,0 +1,53 @@
1
+ <%~ includeFile('./header.eta', it) %>
2
+
3
+ package routes
4
+
5
+ import (
6
+ "app/handlers"
7
+ "app/services"
8
+ "github.com/gin-gonic/gin"
9
+ "gorm.io/gorm"
10
+ )
11
+
12
+ // RegisterAllRoutes registers all entity routes
13
+ func RegisterAllRoutes(r *gin.RouterGroup, db *gorm.DB) {
14
+ <% it.entities.forEach((entity) => { %>
15
+ // <%= entity.name %> routes
16
+ <%= entity.camelName %>Service := services.New<%= entity.name %>Service(db)
17
+ <%= entity.camelName %>Handler := handlers.New<%= entity.name %>Handler(<%= entity.camelName %>Service)
18
+ <%= entity.camelName %>Handler.RegisterRoutes(r)
19
+
20
+ <% }) %>
21
+ }
22
+
23
+ // Services holds all service instances
24
+ type Services struct {
25
+ <% it.entities.forEach((entity) => { %>
26
+ <%= entity.name %>Service *services.<%= entity.name %>Service
27
+ <% }) %>
28
+ }
29
+
30
+ // NewServices creates all service instances
31
+ func NewServices(db *gorm.DB) *Services {
32
+ return &Services{
33
+ <% it.entities.forEach((entity) => { %>
34
+ <%= entity.name %>Service: services.New<%= entity.name %>Service(db),
35
+ <% }) %>
36
+ }
37
+ }
38
+
39
+ // Handlers holds all handler instances
40
+ type Handlers struct {
41
+ <% it.entities.forEach((entity) => { %>
42
+ <%= entity.name %>Handler *handlers.<%= entity.name %>Handler
43
+ <% }) %>
44
+ }
45
+
46
+ // NewHandlers creates all handler instances
47
+ func NewHandlers(s *Services) *Handlers {
48
+ return &Handlers{
49
+ <% it.entities.forEach((entity) => { %>
50
+ <%= entity.name %>Handler: handlers.New<%= entity.name %>Handler(s.<%= entity.name %>Service),
51
+ <% }) %>
52
+ }
53
+ }
@@ -0,0 +1,101 @@
1
+ <%~ includeFile('../../header.eta', it) %>
2
+
3
+ package middleware
4
+
5
+ import (
6
+ "net/http"
7
+ "strings"
8
+
9
+ "github.com/gin-gonic/gin"
10
+ )
11
+
12
+ // AuthMiddleware provides authentication middleware for protected routes
13
+ func AuthMiddleware() gin.HandlerFunc {
14
+ return func(c *gin.Context) {
15
+ authHeader := c.GetHeader("Authorization")
16
+ if authHeader == "" {
17
+ c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Authorization header required"})
18
+ return
19
+ }
20
+
21
+ parts := strings.SplitN(authHeader, " ", 2)
22
+ if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" {
23
+ c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid authorization header format"})
24
+ return
25
+ }
26
+
27
+ token := parts[1]
28
+
29
+ // TODO: Validate the token
30
+ // This is a placeholder - implement your actual token validation logic
31
+ if token == "" {
32
+ c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
33
+ return
34
+ }
35
+
36
+ // Set user info in context if token is valid
37
+ // c.Set("user_id", userId)
38
+ // c.Set("user_roles", roles)
39
+
40
+ c.Next()
41
+ }
42
+ }
43
+
44
+ <% if (it.auth && it.auth.roles && it.auth.roles.length > 0) { %>
45
+ // RoleMiddleware checks if the user has the required role
46
+ func RoleMiddleware(allowedRoles ...string) gin.HandlerFunc {
47
+ return func(c *gin.Context) {
48
+ // Get user roles from context (set by AuthMiddleware)
49
+ userRoles, exists := c.Get("user_roles")
50
+ if !exists {
51
+ c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "No roles found"})
52
+ return
53
+ }
54
+
55
+ roles, ok := userRoles.([]string)
56
+ if !ok {
57
+ c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "Invalid roles format"})
58
+ return
59
+ }
60
+
61
+ // Check if user has any of the allowed roles
62
+ for _, userRole := range roles {
63
+ for _, allowedRole := range allowedRoles {
64
+ if userRole == allowedRole {
65
+ c.Next()
66
+ return
67
+ }
68
+ }
69
+ }
70
+
71
+ c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "Insufficient permissions"})
72
+ }
73
+ }
74
+
75
+ // Role constants
76
+ const (
77
+ <% it.auth.roles.forEach((role) => { %>
78
+ Role<%= role.charAt(0).toUpperCase() + role.slice(1) %> = "<%= role %>"
79
+ <% }) %>
80
+ )
81
+ <% } %>
82
+
83
+ <% if (it.auth && it.auth.multiTenant) { %>
84
+ // TenantMiddleware extracts and validates tenant from requests
85
+ func TenantMiddleware() gin.HandlerFunc {
86
+ return func(c *gin.Context) {
87
+ tenantID := c.GetHeader("X-Tenant-ID")
88
+ if tenantID == "" {
89
+ tenantID = c.Query("tenantId")
90
+ }
91
+
92
+ if tenantID == "" {
93
+ c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Tenant ID required"})
94
+ return
95
+ }
96
+
97
+ c.Set("tenant_id", tenantID)
98
+ c.Next()
99
+ }
100
+ }
101
+ <% } %>
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> []<%= it.column.arrayItemType || 'string' %> `gorm:"type:<%= it.column.arrayItemType || 'text' %>[];serializer:json<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>bool `gorm:"type:boolean<% if (!it.column.required) { %>;default:null<% } else if (it.column.default !== undefined) { %>;default:<%= it.column.default %><% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>time.Time `gorm:"type:date<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>float64 `gorm:"type:decimal(<%= it.column.precision || 10 %>,<%= it.column.scale || 2 %>)<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1,2 @@
1
+ <% const enumTypeName = it.column.enumType || (it.column.pascalName + 'Enum'); %>
2
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>enums.<%= enumTypeName %> `gorm:"type:varchar(50)<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>float64 `gorm:"type:float<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>int <% if (it.column.primary) { %>`gorm:"primaryKey;autoIncrement" json:"<%= it.column.name %>"`<% } else { %>`gorm:"type:integer<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`<% } %>
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>map[string]interface{} `gorm:"type:json<% if (!it.column.required) { %>;default:null<% } %>;serializer:json" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>map[string]interface{} `gorm:"type:jsonb<% if (!it.column.required) { %>;default:null<% } %>;serializer:json" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>float64 `gorm:"type:numeric(<%= it.column.precision || 10 %>,<%= it.column.scale || 2 %>)<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>string `gorm:"type:varchar(<%= it.column.length || 255 %>)<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>string `gorm:"type:text<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>time.Time `gorm:"type:timestamp<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>time.Time `gorm:"type:timestamptz<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>string <% if (it.column.primary) { %>`gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"<%= it.column.name %>"`<% } else { %>`gorm:"type:uuid<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`<% } %>
@@ -0,0 +1 @@
1
+ <%= it.column.pascalName %> <% if (!it.column.required) { %>*<% } %>string `gorm:"type:varchar(<%= it.column.length || 255 %>)<% if (!it.column.required) { %>;default:null<% } %>" json:"<%= it.column.name %><% if (!it.column.required) { %>,omitempty<% } %>"`
@@ -0,0 +1,53 @@
1
+ <%~ includeFile('../../header.eta', it) %>
2
+
3
+ package models
4
+
5
+ import (
6
+ "time"
7
+ <% if (it.importEnums) { %>
8
+ "app/models/enums"
9
+ <% } %>
10
+ "gorm.io/gorm"
11
+ )
12
+
13
+ // <%= it.name %> represents the <%= it.snakeCasedName %> table
14
+ type <%= it.name %> struct {
15
+ <% if (it.createPrimaryKey) { %>
16
+ <% if (it.primaryKeyType === 'uuid') { %>
17
+ ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"id"`
18
+ <% } else { %>
19
+ ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
20
+ <% } %>
21
+ <% } %>
22
+ <% it.columns.forEach((column) => { %>
23
+ <%~ includeFile('./model-col-' + column.type + '.eta', { column }) %>
24
+ <% }) %>
25
+ <% if (it.createdAt) { %>
26
+ CreatedAt time.Time `gorm:"autoCreateTime" json:"createdAt"`
27
+ <% } %>
28
+ <% if (it.updatedAt) { %>
29
+ UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updatedAt"`
30
+ <% } %>
31
+ <% it.associations.forEach((assoc) => { %>
32
+ <% if (assoc.type === 'OneToMany') { %>
33
+ <%= assoc.pluralName %> []<%= assoc.name %> `gorm:"foreignKey:<%= assoc.inverseName %>ID" json:"<%= assoc.camelPluralName %>,omitempty"`
34
+ <% } else if (assoc.type === 'ManyToOne') { %>
35
+ <%= assoc.referenceName || assoc.name %>ID <%= assoc.primaryKeyGoType || 'uint' %> `gorm:"index" json:"<%= assoc.camelReferenceName || assoc.camelName %>Id"`
36
+ <%= assoc.referenceName || assoc.name %> *<%= assoc.name %> `gorm:"foreignKey:<%= assoc.referenceName || assoc.name %>ID" json:"<%= assoc.camelReferenceName || assoc.camelName %>,omitempty"`
37
+ <% } else if (assoc.type === 'OneToOne') { %>
38
+ <% if (assoc.isOwner) { %>
39
+ <%= assoc.referenceName || assoc.name %>ID <%= assoc.primaryKeyGoType || 'uint' %> `gorm:"uniqueIndex" json:"<%= assoc.camelReferenceName || assoc.camelName %>Id"`
40
+ <%= assoc.referenceName || assoc.name %> *<%= assoc.name %> `gorm:"foreignKey:<%= assoc.referenceName || assoc.name %>ID" json:"<%= assoc.camelReferenceName || assoc.camelName %>,omitempty"`
41
+ <% } else { %>
42
+ <%= assoc.referenceName || assoc.name %> *<%= assoc.name %> `json:"<%= assoc.camelReferenceName || assoc.camelName %>,omitempty"`
43
+ <% } %>
44
+ <% } else if (assoc.type === 'ManyToMany') { %>
45
+ <%= assoc.pluralName %> []<%= assoc.name %> `gorm:"many2many:<%= assoc.joinTable %>;" json:"<%= assoc.camelPluralName %>,omitempty"`
46
+ <% } %>
47
+ <% }) %>
48
+ }
49
+
50
+ // TableName overrides the table name
51
+ func (<%= it.name %>) TableName() string {
52
+ return "<%= it.snakeCasedName %>"
53
+ }