@antelopejs/interface-data-api 0.4.0 → 0.6.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.
Files changed (165) hide show
  1. package/README.md +26 -22
  2. package/dist/antelope.test.js +1 -5
  3. package/dist/antelope.test.js.map +1 -1
  4. package/dist/components.d.ts +67 -39
  5. package/dist/components.js +106 -685
  6. package/dist/components.js.map +1 -1
  7. package/dist/index.d.ts +57 -68
  8. package/dist/index.js +114 -100
  9. package/dist/index.js.map +1 -1
  10. package/dist/internal/computed.d.ts +6 -0
  11. package/dist/internal/computed.js +51 -0
  12. package/dist/internal/computed.js.map +1 -0
  13. package/dist/internal/controller-types.d.ts +34 -0
  14. package/dist/internal/controller-types.js +4 -0
  15. package/dist/internal/controller-types.js.map +1 -0
  16. package/dist/internal/default-filter.d.ts +4 -0
  17. package/dist/internal/default-filter.js +29 -0
  18. package/dist/internal/default-filter.js.map +1 -0
  19. package/dist/internal/deferred-joined-stream.d.ts +11 -0
  20. package/dist/internal/deferred-joined-stream.js +125 -0
  21. package/dist/internal/deferred-joined-stream.js.map +1 -0
  22. package/dist/internal/extractors.d.ts +25 -0
  23. package/dist/internal/extractors.js +31 -0
  24. package/dist/internal/extractors.js.map +1 -0
  25. package/dist/internal/field-types.d.ts +199 -0
  26. package/dist/internal/field-types.js +4 -0
  27. package/dist/internal/field-types.js.map +1 -0
  28. package/dist/internal/filters.d.ts +6 -0
  29. package/dist/internal/filters.js +22 -0
  30. package/dist/internal/filters.js.map +1 -0
  31. package/dist/internal/foreign.d.ts +6 -0
  32. package/dist/internal/foreign.js +116 -0
  33. package/dist/internal/foreign.js.map +1 -0
  34. package/dist/internal/guards.d.ts +39 -0
  35. package/dist/internal/guards.js +116 -0
  36. package/dist/internal/guards.js.map +1 -0
  37. package/dist/internal/joined.d.ts +28 -0
  38. package/dist/internal/joined.js +127 -0
  39. package/dist/internal/joined.js.map +1 -0
  40. package/dist/internal/list.d.ts +16 -0
  41. package/dist/internal/list.js +182 -0
  42. package/dist/internal/list.js.map +1 -0
  43. package/dist/internal/meta-records.d.ts +19 -0
  44. package/dist/internal/meta-records.js +78 -0
  45. package/dist/internal/meta-records.js.map +1 -0
  46. package/dist/internal/properties.d.ts +4 -0
  47. package/dist/internal/properties.js +45 -0
  48. package/dist/internal/properties.js.map +1 -0
  49. package/dist/internal/prototypes.d.ts +14 -0
  50. package/dist/internal/prototypes.js +38 -0
  51. package/dist/internal/prototypes.js.map +1 -0
  52. package/dist/internal/read-properties.d.ts +3 -0
  53. package/dist/internal/read-properties.js +29 -0
  54. package/dist/internal/read-properties.js.map +1 -0
  55. package/dist/internal/table-reference.d.ts +11 -0
  56. package/dist/internal/table-reference.js +46 -0
  57. package/dist/internal/table-reference.js.map +1 -0
  58. package/dist/internal/tables.d.ts +28 -0
  59. package/dist/internal/tables.js +48 -0
  60. package/dist/internal/tables.js.map +1 -0
  61. package/dist/internal/validation.d.ts +12 -0
  62. package/dist/internal/validation.js +100 -0
  63. package/dist/internal/validation.js.map +1 -0
  64. package/dist/metadata.d.ts +27 -228
  65. package/dist/metadata.js +84 -213
  66. package/dist/metadata.js.map +1 -1
  67. package/dist/tests/components/access_control.test.js +28 -20
  68. package/dist/tests/components/access_control.test.js.map +1 -1
  69. package/dist/tests/components/computed.test.js +36 -27
  70. package/dist/tests/components/computed.test.js.map +1 -1
  71. package/dist/tests/components/cross_instance.test.js +8 -6
  72. package/dist/tests/components/cross_instance.test.js.map +1 -1
  73. package/dist/tests/components/deferred_joined.test.js +57 -54
  74. package/dist/tests/components/deferred_joined.test.js.map +1 -1
  75. package/dist/tests/components/extract_generic.test.d.ts +1 -0
  76. package/dist/tests/components/extract_generic.test.js +64 -0
  77. package/dist/tests/components/extract_generic.test.js.map +1 -0
  78. package/dist/tests/components/filter_comparisons.test.d.ts +1 -0
  79. package/dist/tests/components/filter_comparisons.test.js +34 -0
  80. package/dist/tests/components/filter_comparisons.test.js.map +1 -0
  81. package/dist/tests/components/filter_list_route.test.d.ts +1 -0
  82. package/dist/tests/components/filter_list_route.test.js +182 -0
  83. package/dist/tests/components/filter_list_route.test.js.map +1 -0
  84. package/dist/tests/components/filter_options.test.js +11 -10
  85. package/dist/tests/components/filter_options.test.js.map +1 -1
  86. package/dist/tests/components/foreign_computed.test.js +23 -14
  87. package/dist/tests/components/foreign_computed.test.js.map +1 -1
  88. package/dist/tests/components/foreign_joined.test.js +31 -27
  89. package/dist/tests/components/foreign_joined.test.js.map +1 -1
  90. package/dist/tests/components/joined.test.js +59 -45
  91. package/dist/tests/components/joined.test.js.map +1 -1
  92. package/dist/tests/components/listable.test.js +78 -58
  93. package/dist/tests/components/listable.test.js.map +1 -1
  94. package/dist/tests/components/localized_sort.test.js +14 -11
  95. package/dist/tests/components/localized_sort.test.js.map +1 -1
  96. package/dist/tests/components/mandatory.test.js +25 -25
  97. package/dist/tests/components/mandatory.test.js.map +1 -1
  98. package/dist/tests/components/modifier_key.test.js +27 -18
  99. package/dist/tests/components/modifier_key.test.js.map +1 -1
  100. package/dist/tests/components/parse_body.test.d.ts +1 -0
  101. package/dist/tests/components/parse_body.test.js +76 -0
  102. package/dist/tests/components/parse_body.test.js.map +1 -0
  103. package/dist/tests/components/parsed_value.test.js +23 -21
  104. package/dist/tests/components/parsed_value.test.js.map +1 -1
  105. package/dist/tests/components/partial_edit.test.js +38 -32
  106. package/dist/tests/components/partial_edit.test.js.map +1 -1
  107. package/dist/tests/components/per_action_access.test.js +20 -12
  108. package/dist/tests/components/per_action_access.test.js.map +1 -1
  109. package/dist/tests/components/prototype_named_filter.test.d.ts +1 -0
  110. package/dist/tests/components/prototype_named_filter.test.js +87 -0
  111. package/dist/tests/components/prototype_named_filter.test.js.map +1 -0
  112. package/dist/tests/components/validator.test.js +45 -37
  113. package/dist/tests/components/validator.test.js.map +1 -1
  114. package/dist/tests/components/written_row.test.d.ts +1 -0
  115. package/dist/tests/components/written_row.test.js +99 -0
  116. package/dist/tests/components/written_row.test.js.map +1 -0
  117. package/dist/tests/helpers/other-instance.d.ts +11 -1
  118. package/dist/tests/helpers/other-instance.js +35 -9
  119. package/dist/tests/helpers/other-instance.js.map +1 -1
  120. package/dist/tests/index/field_decorator_target.test.d.ts +1 -0
  121. package/dist/tests/index/field_decorator_target.test.js +20 -0
  122. package/dist/tests/index/field_decorator_target.test.js.map +1 -0
  123. package/dist/tests/index/get_guard.test.js +6 -6
  124. package/dist/tests/index/get_guard.test.js.map +1 -1
  125. package/dist/tests/index/inheritance.test.js +14 -9
  126. package/dist/tests/index/inheritance.test.js.map +1 -1
  127. package/dist/tests/index/metadata_names.test.d.ts +1 -0
  128. package/dist/tests/index/metadata_names.test.js +91 -0
  129. package/dist/tests/index/metadata_names.test.js.map +1 -0
  130. package/dist/tests/index/routes.test.js +49 -44
  131. package/dist/tests/index/routes.test.js.map +1 -1
  132. package/dist/tests/integration.test.d.ts +1 -1
  133. package/dist/tests/integration.test.js +66 -729
  134. package/dist/tests/integration.test.js.map +1 -1
  135. package/dist/tests/internal/controller-fields.test.d.ts +1 -0
  136. package/dist/tests/internal/controller-fields.test.js +25 -0
  137. package/dist/tests/internal/controller-fields.test.js.map +1 -0
  138. package/dist/tests/internal/http.d.ts +35 -0
  139. package/dist/tests/internal/http.js +56 -0
  140. package/dist/tests/internal/http.js.map +1 -0
  141. package/dist/tests/internal/shop-api.d.ts +1 -0
  142. package/dist/tests/internal/shop-api.js +331 -0
  143. package/dist/tests/internal/shop-api.js.map +1 -0
  144. package/dist/tests/internal/shop-schema.d.ts +162 -0
  145. package/dist/tests/internal/shop-schema.js +387 -0
  146. package/dist/tests/internal/shop-schema.js.map +1 -0
  147. package/dist/tests/utils.d.ts +8 -10
  148. package/dist/tests/utils.js +1 -3
  149. package/dist/tests/utils.js.map +1 -1
  150. package/dist/tests/utils.test.js +10 -11
  151. package/dist/tests/utils.test.js.map +1 -1
  152. package/docs/1.introduction.md +38 -35
  153. package/docs/10.joined.md +51 -40
  154. package/docs/11.computed.md +91 -47
  155. package/docs/2.data-controllers.md +50 -42
  156. package/docs/3.routes.md +156 -134
  157. package/docs/4.access-rights.md +48 -44
  158. package/docs/5.validators.md +65 -47
  159. package/docs/6.listable.md +53 -49
  160. package/docs/7.foreign-keys.md +55 -48
  161. package/docs/8.filters.md +65 -54
  162. package/docs/9.modifiers.md +29 -25
  163. package/package.json +34 -13
  164. package/skills/data-api-interface/SKILL.md +13 -3
  165. package/skills/data-api-interface/cases.json +99 -0
@@ -118,9 +118,11 @@ This exposes `GET /tasks/get?id=`, `GET /tasks/list`, `POST /tasks/new`, `PUT /t
118
118
  - `list` responds `{ results, total, offset, limit }`. `limit` defaults to 10 and is capped at 100
119
119
  (`maxPage`). Sorting uses `sortKey`/`sortDirection` query params and requires `@Sortable` on the
120
120
  field (400 otherwise). List responses only include `@Listable` fields unless `noPluck` is set.
121
- - Filters come from `filter_<name>=<mode>:<value>` query params (plain value means `eq`); modes are
122
- `eq|ne|gt|ge|lt|le` (the default filter compares the raw query-string value — pass a custom filter
123
- function to cast for numeric ranges). Only fields declared with `@Filter()` are filterable.
121
+ - Filters come from `filter_<name>=<mode>:<value>` query params (plain value means `eq`). `mode` is
122
+ text: the default filter accepts `eq|ne|gt|ge|lt|le` and answers 400 for anything else (it compares
123
+ the raw query-string value — pass a custom filter function to cast for numeric ranges), and a custom
124
+ filter receives it unchecked and defines its own modes. Only fields declared with `@Filter()` are
125
+ filterable.
124
126
  Repeating a field's filter (`filter_age=ge:18&filter_age=lt:65`) keeps the rows passing them all;
125
127
  the route then receives a list of tuples for it (`FieldFilter`, read with `FilterValuesOf`).
126
128
  - `@Joined` and `@Computed` fields are materialized in-database, so `@Sortable` and `@Filter()` work
@@ -134,12 +136,20 @@ This exposes `GET /tasks/get?id=`, `GET /tasks/list`, `POST /tasks/new`, `PUT /t
134
136
  - A custom list route reads its page with `Query.ListPage(db, meta, query, options)` (`offset`,
135
137
  `limit`, `filters`, `sortKey`, `pluck`, `noForeign`, `deferredJoined`): joined, then computed, then
136
138
  foreign, then pluck.
139
+ - A route is `DataControllerCallback<O, R, A>`: `A` is the tuple `func` receives, one element per
140
+ `args` entry. The default routes declare theirs (`Get` takes `[RequestContext, GetParameters]`), so a
141
+ wrapper generic over `[RequestContext, P, ...Rest]` calls `route.func.call(this, ctx, params, ...rest)`
142
+ typed; without `A` its parameters are not checked.
137
143
  - `new` answers the created row as `get` reads it, with its `_id`; `edit` answers the stored row after
138
144
  the update. Both accept a body already parsed (`Validation.WrittenBody`), so a wrapping route can
139
145
  amend it before the write.
140
146
  - `edit` is a partial update: a field absent from the body is left unchanged, `null` clears it, and
141
147
  setters only run for the fields present. `@Mandatory("edit")` rejects a field cleared by the body
142
148
  (`null`, `""`, `[]`), not an absent one. `new` still writes every writable field and runs every setter.
149
+ - A parsed request body is `FieldValues` (fields by name; a `FieldValue` is JSON or a `Date`). A
150
+ `@Validator` receives `FieldValue | undefined`, and `Validation.ParseBody` answers 400 for a body that
151
+ holds anything else, even one a wrapping route already parsed. The default routes run with the
152
+ controller as `this` (`DataControllerInstance`); a wrapper calls `route.func.call(this, ...)`.
143
153
  - A `@Validator` may return a parse result `{ success, data }` (e.g. zod's `safeParseAsync(value)`)
144
154
  instead of a boolean: `data` is then written in place of the raw value.
145
155
 
@@ -0,0 +1,99 @@
1
+ {
2
+ "version": 1,
3
+ "cases": [
4
+ {
5
+ "id": "data-api-interface-crud-endpoints",
6
+ "area": "framework",
7
+ "style": "clean",
8
+ "prompt": "Expose my orders table as REST endpoints for get, list, create, update and delete. Only the status column should be sortable and customer filterable.",
9
+ "expect": {
10
+ "skills": ["data-api-interface"],
11
+ "acceptable": [
12
+ "api-interface",
13
+ "database-decorators-interface",
14
+ "database-interface",
15
+ "ajs-consume-interface",
16
+ "antelopejs"
17
+ ],
18
+ "mustMention": [
19
+ "DataController",
20
+ "RegisterDataController",
21
+ "Sortable",
22
+ "Filter"
23
+ ]
24
+ }
25
+ },
26
+ {
27
+ "id": "data-api-interface-crud-casual",
28
+ "area": "framework",
29
+ "style": "casual",
30
+ "prompt": "can i get a crud api straight from my table without writing every route",
31
+ "expect": {
32
+ "skills": ["data-api-interface"],
33
+ "acceptable": [
34
+ "api-interface",
35
+ "database-decorators-interface",
36
+ "database-interface",
37
+ "antelopejs"
38
+ ],
39
+ "mustMention": ["DataController", "DefaultRoutes"]
40
+ }
41
+ },
42
+ {
43
+ "id": "data-api-interface-field-hidden",
44
+ "area": "framework",
45
+ "style": "clean",
46
+ "prompt": "The list endpoint I generated from my table never returns the email field and I cannot write to it either. Why?",
47
+ "expect": {
48
+ "skills": ["data-api-interface"],
49
+ "acceptable": [
50
+ "api-interface",
51
+ "database-decorators-interface",
52
+ "ajs-consume-interface"
53
+ ],
54
+ "mustMention": ["Access"]
55
+ }
56
+ },
57
+ {
58
+ "id": "data-api-interface-sort-400-casual",
59
+ "area": "framework",
60
+ "style": "casual",
61
+ "prompt": "sorting the list by createdAt gives me a 400",
62
+ "expect": {
63
+ "skills": ["data-api-interface"],
64
+ "acceptable": ["api-interface", "database-decorators-interface"],
65
+ "mustMention": ["Sortable"]
66
+ }
67
+ },
68
+ {
69
+ "id": "data-api-interface-table-neighbour",
70
+ "area": "framework",
71
+ "style": "clean",
72
+ "prompt": "Add a hashed passphrase and an encrypted supplier code to my chef table class, plus created and updated timestamps.",
73
+ "expect": {
74
+ "skills": ["database-decorators-interface"],
75
+ "acceptable": [
76
+ "database-interface",
77
+ "antelopejs",
78
+ "ajs-consume-interface"
79
+ ],
80
+ "avoid": ["data-api-interface"]
81
+ }
82
+ },
83
+ {
84
+ "id": "data-api-interface-wrap-new-stamp",
85
+ "area": "framework",
86
+ "style": "clean",
87
+ "prompt": "I want the generated create route to stamp a source field on every body before it is validated and written. How do I wrap it, and what type does the parsed body have?",
88
+ "expect": {
89
+ "skills": ["data-api-interface"],
90
+ "acceptable": [
91
+ "api-interface",
92
+ "database-decorators-interface",
93
+ "ajs-consume-interface"
94
+ ],
95
+ "mustMention": ["ParseBody", "WrittenBody", "FieldValues"]
96
+ }
97
+ }
98
+ ]
99
+ }