@stapel/reviews-react 0.1.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 (164) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/MODULE.md +151 -0
  3. package/README.md +207 -0
  4. package/dist/api/generated/schema.d.ts +360 -0
  5. package/dist/api/generated/schema.d.ts.map +1 -0
  6. package/dist/api/generated/schema.js +2 -0
  7. package/dist/api/generated/schema.js.map +1 -0
  8. package/dist/api/reviewsApi.d.ts +89 -0
  9. package/dist/api/reviewsApi.d.ts.map +1 -0
  10. package/dist/api/reviewsApi.js +51 -0
  11. package/dist/api/reviewsApi.js.map +1 -0
  12. package/dist/api/types.d.ts +127 -0
  13. package/dist/api/types.d.ts.map +1 -0
  14. package/dist/api/types.js +2 -0
  15. package/dist/api/types.js.map +1 -0
  16. package/dist/default/ErrorAlert.d.ts +9 -0
  17. package/dist/default/ErrorAlert.d.ts.map +1 -0
  18. package/dist/default/ErrorAlert.js +27 -0
  19. package/dist/default/ErrorAlert.js.map +1 -0
  20. package/dist/default/RatingBadge.d.ts +17 -0
  21. package/dist/default/RatingBadge.d.ts.map +1 -0
  22. package/dist/default/RatingBadge.js +23 -0
  23. package/dist/default/RatingBadge.js.map +1 -0
  24. package/dist/default/ReviewFormCard.d.ts +25 -0
  25. package/dist/default/ReviewFormCard.d.ts.map +1 -0
  26. package/dist/default/ReviewFormCard.js +42 -0
  27. package/dist/default/ReviewFormCard.js.map +1 -0
  28. package/dist/default/ReviewListPanel.d.ts +29 -0
  29. package/dist/default/ReviewListPanel.d.ts.map +1 -0
  30. package/dist/default/ReviewListPanel.js +47 -0
  31. package/dist/default/ReviewListPanel.js.map +1 -0
  32. package/dist/default/ReviewsPanel.d.ts +33 -0
  33. package/dist/default/ReviewsPanel.d.ts.map +1 -0
  34. package/dist/default/ReviewsPanel.js +17 -0
  35. package/dist/default/ReviewsPanel.js.map +1 -0
  36. package/dist/default/index.d.ts +31 -0
  37. package/dist/default/index.d.ts.map +1 -0
  38. package/dist/default/index.js +25 -0
  39. package/dist/default/index.js.map +1 -0
  40. package/dist/default/theme.d.ts +24 -0
  41. package/dist/default/theme.d.ts.map +1 -0
  42. package/dist/default/theme.js +39 -0
  43. package/dist/default/theme.js.map +1 -0
  44. package/dist/default/types.d.ts +12 -0
  45. package/dist/default/types.d.ts.map +1 -0
  46. package/dist/default/types.js +2 -0
  47. package/dist/default/types.js.map +1 -0
  48. package/dist/headless/ReviewAggregate.d.ts +63 -0
  49. package/dist/headless/ReviewAggregate.d.ts.map +1 -0
  50. package/dist/headless/ReviewAggregate.js +55 -0
  51. package/dist/headless/ReviewAggregate.js.map +1 -0
  52. package/dist/headless/ReviewForm.d.ts +83 -0
  53. package/dist/headless/ReviewForm.d.ts.map +1 -0
  54. package/dist/headless/ReviewForm.js +75 -0
  55. package/dist/headless/ReviewForm.js.map +1 -0
  56. package/dist/headless/ReviewList.d.ts +47 -0
  57. package/dist/headless/ReviewList.d.ts.map +1 -0
  58. package/dist/headless/ReviewList.js +51 -0
  59. package/dist/headless/ReviewList.js.map +1 -0
  60. package/dist/headless/ReviewsProvider.d.ts +19 -0
  61. package/dist/headless/ReviewsProvider.d.ts.map +1 -0
  62. package/dist/headless/ReviewsProvider.js +15 -0
  63. package/dist/headless/ReviewsProvider.js.map +1 -0
  64. package/dist/i18n/errorsMap.d.ts +12 -0
  65. package/dist/i18n/errorsMap.d.ts.map +1 -0
  66. package/dist/i18n/errorsMap.js +22 -0
  67. package/dist/i18n/errorsMap.js.map +1 -0
  68. package/dist/i18n/es.d.ts +19 -0
  69. package/dist/i18n/es.d.ts.map +1 -0
  70. package/dist/i18n/es.js +66 -0
  71. package/dist/i18n/es.js.map +1 -0
  72. package/dist/i18n/generated/errors.es.gen.d.ts +16 -0
  73. package/dist/i18n/generated/errors.es.gen.d.ts.map +1 -0
  74. package/dist/i18n/generated/errors.es.gen.js +58 -0
  75. package/dist/i18n/generated/errors.es.gen.js.map +1 -0
  76. package/dist/i18n/generated/errors.gen.d.ts +341 -0
  77. package/dist/i18n/generated/errors.gen.d.ts.map +1 -0
  78. package/dist/i18n/generated/errors.gen.js +174 -0
  79. package/dist/i18n/generated/errors.gen.js.map +1 -0
  80. package/dist/i18n/generated/errors.ru.gen.d.ts +16 -0
  81. package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -0
  82. package/dist/i18n/generated/errors.ru.gen.js +58 -0
  83. package/dist/i18n/generated/errors.ru.gen.js.map +1 -0
  84. package/dist/i18n/keys.d.ts +59 -0
  85. package/dist/i18n/keys.d.ts.map +1 -0
  86. package/dist/i18n/keys.js +115 -0
  87. package/dist/i18n/keys.js.map +1 -0
  88. package/dist/i18n/ru.d.ts +22 -0
  89. package/dist/i18n/ru.d.ts.map +1 -0
  90. package/dist/i18n/ru.js +70 -0
  91. package/dist/i18n/ru.js.map +1 -0
  92. package/dist/index.d.ts +98 -0
  93. package/dist/index.d.ts.map +1 -0
  94. package/dist/index.js +92 -0
  95. package/dist/index.js.map +1 -0
  96. package/dist/model/context.d.ts +11 -0
  97. package/dist/model/context.d.ts.map +1 -0
  98. package/dist/model/context.js +16 -0
  99. package/dist/model/context.js.map +1 -0
  100. package/dist/model/list.d.ts +52 -0
  101. package/dist/model/list.d.ts.map +1 -0
  102. package/dist/model/list.js +60 -0
  103. package/dist/model/list.js.map +1 -0
  104. package/dist/model/mutations.d.ts +32 -0
  105. package/dist/model/mutations.d.ts.map +1 -0
  106. package/dist/model/mutations.js +44 -0
  107. package/dist/model/mutations.js.map +1 -0
  108. package/dist/model/queries.d.ts +65 -0
  109. package/dist/model/queries.d.ts.map +1 -0
  110. package/dist/model/queries.js +80 -0
  111. package/dist/model/queries.js.map +1 -0
  112. package/dist/model/queryKeys.d.ts +27 -0
  113. package/dist/model/queryKeys.d.ts.map +1 -0
  114. package/dist/model/queryKeys.js +14 -0
  115. package/dist/model/queryKeys.js.map +1 -0
  116. package/dist/model/rating.d.ts +57 -0
  117. package/dist/model/rating.d.ts.map +1 -0
  118. package/dist/model/rating.js +47 -0
  119. package/dist/model/rating.js.map +1 -0
  120. package/dist/model/refusals.d.ts +51 -0
  121. package/dist/model/refusals.d.ts.map +1 -0
  122. package/dist/model/refusals.js +103 -0
  123. package/dist/model/refusals.js.map +1 -0
  124. package/dist/model/runtime.d.ts +44 -0
  125. package/dist/model/runtime.d.ts.map +1 -0
  126. package/dist/model/runtime.js +15 -0
  127. package/dist/model/runtime.js.map +1 -0
  128. package/llms.txt +80 -0
  129. package/manifest.json +577 -0
  130. package/package.json +115 -0
  131. package/src/analytics/generated/events.json +7 -0
  132. package/src/api/generated/schema.ts +362 -0
  133. package/src/api/reviewsApi.ts +170 -0
  134. package/src/api/types.ts +140 -0
  135. package/src/default/ErrorAlert.tsx +46 -0
  136. package/src/default/RatingBadge.tsx +81 -0
  137. package/src/default/ReviewFormCard.tsx +139 -0
  138. package/src/default/ReviewListPanel.tsx +204 -0
  139. package/src/default/ReviewsPanel.tsx +74 -0
  140. package/src/default/index.ts +30 -0
  141. package/src/default/theme.tsx +66 -0
  142. package/src/default/types.ts +12 -0
  143. package/src/headless/ReviewAggregate.tsx +94 -0
  144. package/src/headless/ReviewForm.tsx +163 -0
  145. package/src/headless/ReviewList.tsx +99 -0
  146. package/src/headless/ReviewsProvider.tsx +20 -0
  147. package/src/i18n/errorsMap.ts +33 -0
  148. package/src/i18n/es.ts +81 -0
  149. package/src/i18n/generated/errors.es.gen.ts +64 -0
  150. package/src/i18n/generated/errors.gen.ts +205 -0
  151. package/src/i18n/generated/errors.json +387 -0
  152. package/src/i18n/generated/errors.ru.gen.ts +64 -0
  153. package/src/i18n/keys.ts +133 -0
  154. package/src/i18n/ru.ts +85 -0
  155. package/src/index.ts +161 -0
  156. package/src/model/context.tsx +28 -0
  157. package/src/model/list.ts +74 -0
  158. package/src/model/mutations.ts +62 -0
  159. package/src/model/queries.ts +122 -0
  160. package/src/model/queryKeys.ts +45 -0
  161. package/src/model/rating.ts +101 -0
  162. package/src/model/refusals.ts +114 -0
  163. package/src/model/runtime.ts +61 -0
  164. package/tsconfig.json +26 -0
@@ -0,0 +1,360 @@
1
+ export interface paths {
2
+ "/reviews/api/v1/reviews": {
3
+ parameters: {
4
+ query?: never;
5
+ header?: never;
6
+ path?: never;
7
+ cookie?: never;
8
+ };
9
+ /**
10
+ * @description List a target's reviews (anchor-paginated, published-only for
11
+ * non-moderators), or create a review.
12
+ *
13
+ * ``GET`` is anonymously readable (storefront F5 verdict,
14
+ * darom-storefront-design.md §13.8 note 2) — published-only filtering
15
+ * already guarantees a guest sees nothing a moderator would need to hide.
16
+ * ``POST`` still requires a real identity (there is an author to attribute
17
+ * the review to), so the class gate is DRF's own
18
+ * ``IsAuthenticatedOrReadOnly`` (mirrors ``ListingViewSet`` in
19
+ * stapel-listings — the fleet's other read-open/write-authenticated view in
20
+ * a single class) rather than a per-method override.
21
+ *
22
+ * **Permissions:** `IsAuthenticatedOrReadOnly`
23
+ */
24
+ get: operations["reviews_api_v1_reviews_retrieve"];
25
+ put?: never;
26
+ /**
27
+ * @description List a target's reviews (anchor-paginated, published-only for
28
+ * non-moderators), or create a review.
29
+ *
30
+ * ``GET`` is anonymously readable (storefront F5 verdict,
31
+ * darom-storefront-design.md §13.8 note 2) — published-only filtering
32
+ * already guarantees a guest sees nothing a moderator would need to hide.
33
+ * ``POST`` still requires a real identity (there is an author to attribute
34
+ * the review to), so the class gate is DRF's own
35
+ * ``IsAuthenticatedOrReadOnly`` (mirrors ``ListingViewSet`` in
36
+ * stapel-listings — the fleet's other read-open/write-authenticated view in
37
+ * a single class) rather than a per-method override.
38
+ *
39
+ * **Permissions:** `IsAuthenticatedOrReadOnly`
40
+ */
41
+ post: operations["reviews_api_v1_reviews_create"];
42
+ delete?: never;
43
+ options?: never;
44
+ head?: never;
45
+ patch?: never;
46
+ trace?: never;
47
+ };
48
+ "/reviews/api/v1/reviews/{review_id}/moderate": {
49
+ parameters: {
50
+ query?: never;
51
+ header?: never;
52
+ path?: never;
53
+ cookie?: never;
54
+ };
55
+ get?: never;
56
+ put?: never;
57
+ /**
58
+ * @description Hide or publish a review (moderation; owner/moderator-only via the
59
+ * target type's can_moderate callback).
60
+ *
61
+ * **Permissions:** `IsAuthenticated`
62
+ */
63
+ post: operations["reviews_api_v1_reviews_moderate_create"];
64
+ delete?: never;
65
+ options?: never;
66
+ head?: never;
67
+ patch?: never;
68
+ trace?: never;
69
+ };
70
+ "/reviews/api/v1/reviews/{review_id}/response": {
71
+ parameters: {
72
+ query?: never;
73
+ header?: never;
74
+ path?: never;
75
+ cookie?: never;
76
+ };
77
+ get?: never;
78
+ put?: never;
79
+ /**
80
+ * @description Attach the target owner's single reply to a review (owner-only via the
81
+ * target type's can_moderate callback; gated by the allow_response policy).
82
+ *
83
+ * **Permissions:** `IsAuthenticated`
84
+ */
85
+ post: operations["reviews_api_v1_reviews_response_create"];
86
+ delete?: never;
87
+ options?: never;
88
+ head?: never;
89
+ patch?: never;
90
+ trace?: never;
91
+ };
92
+ "/reviews/api/v1/reviews/aggregate": {
93
+ parameters: {
94
+ query?: never;
95
+ header?: never;
96
+ path?: never;
97
+ cookie?: never;
98
+ };
99
+ /**
100
+ * @description The module-owned rating aggregate (avg/count over published reviews)
101
+ * for a target.
102
+ *
103
+ * Anonymously readable for the same reason as the list's ``GET``
104
+ * (storefront F5 verdict, darom-storefront-design.md §13.8 note 2): the
105
+ * aggregate is computed over published reviews only, so a guest learns
106
+ * nothing a moderator would need withheld.
107
+ *
108
+ * **Permissions:** `AllowAny`
109
+ */
110
+ get: operations["reviews_api_v1_reviews_aggregate_retrieve"];
111
+ put?: never;
112
+ post?: never;
113
+ delete?: never;
114
+ options?: never;
115
+ head?: never;
116
+ patch?: never;
117
+ trace?: never;
118
+ };
119
+ }
120
+ export type webhooks = Record<string, never>;
121
+ export interface components {
122
+ schemas: {
123
+ /** @description Rating aggregate for a target over published reviews. */
124
+ AggregateResponse: {
125
+ /** @description The host-registered target-type key */
126
+ target_type: string;
127
+ /** @description Opaque host-owned target identifier */
128
+ target_key: string;
129
+ /**
130
+ * Format: double
131
+ * @description Mean rating (0.0 when count is 0)
132
+ */
133
+ avg: number;
134
+ /** @description Number of published reviews */
135
+ count: number;
136
+ };
137
+ /** @description Moderate a review. */
138
+ ModerateRequest: {
139
+ /** @description hide or publish */
140
+ action: string;
141
+ /** @description Optional moderation reason (carried in the emitted fact) */
142
+ reason?: string;
143
+ };
144
+ /** @description Attach the target owner's reply to a review. */
145
+ RespondRequest: {
146
+ /** @description Reply text */
147
+ body?: string;
148
+ };
149
+ /** @description A target owner's reply to a review. */
150
+ ResponseResponse: {
151
+ /** @description The responder's user id (the target owner) */
152
+ author_id: string;
153
+ /** @description Reply text */
154
+ body: string;
155
+ /**
156
+ * Format: date-time
157
+ * @description When the reply was written
158
+ */
159
+ created_at: string;
160
+ };
161
+ /** @description Create a review. */
162
+ ReviewCreateRequest: {
163
+ /** @description The host-registered target-type key */
164
+ target_type: string;
165
+ /** @description Opaque host-owned target identifier */
166
+ target_key: string;
167
+ /** @description Numeric rating (RATING_MIN..RATING_MAX) */
168
+ rating: number;
169
+ /** @description Optional review body */
170
+ body?: string;
171
+ };
172
+ /**
173
+ * @description The envelope ``GET /reviews`` actually returns — ``AnchorPagination``'s
174
+ * keys (``stapel_core.django.api.pagination.AnchorPagination.
175
+ * get_paginated_response``/``get_paginated_response_schema``) wrapping
176
+ * ``items``. Schema-only: ``ReviewListCreateView`` is a bare ``APIView``
177
+ * (views.py), so drf-spectacular's pagination auto-introspection — which
178
+ * only fires for ``GenericAPIView.pagination_class`` — never sees
179
+ * ``ReviewAnchorPagination``, and the envelope has to be declared by hand
180
+ * or spectacular renders the response as a bare array
181
+ * (darom-storefront-design.md §13.8 note 3).
182
+ */
183
+ ReviewPage: {
184
+ items: components["schemas"]["ReviewResponse"][];
185
+ next_anchor: string | null;
186
+ prev_anchor: string | null;
187
+ has_next: boolean;
188
+ has_prev: boolean;
189
+ count: number;
190
+ };
191
+ /** @description A review of an opaque target. */
192
+ ReviewResponse: {
193
+ /** @description Review id (UUID) */
194
+ id: string;
195
+ /** @description The host-registered target-type key */
196
+ target_type: string;
197
+ /** @description Opaque host-owned target identifier */
198
+ target_key: string;
199
+ /** @description Reviewer's user id */
200
+ author_id: string;
201
+ /** @description Numeric rating (RATING_MIN..RATING_MAX) */
202
+ rating: number;
203
+ /** @description Free-text review body */
204
+ body: string;
205
+ /** @description pending/published/hidden */
206
+ status: string;
207
+ /**
208
+ * Format: date-time
209
+ * @description Creation time
210
+ */
211
+ created_at: string;
212
+ /** @description The owner's reply, if any */
213
+ response?: components["schemas"]["ResponseResponse"] | null;
214
+ };
215
+ };
216
+ responses: never;
217
+ parameters: never;
218
+ requestBodies: never;
219
+ headers: never;
220
+ pathItems: never;
221
+ }
222
+ export type $defs = Record<string, never>;
223
+ export interface operations {
224
+ reviews_api_v1_reviews_retrieve: {
225
+ parameters: {
226
+ query: {
227
+ /** @description Opaque cursor: a `next_anchor`/`prev_anchor` from a previous page (the review's `created_at`). Omit for the first page. */
228
+ anchor?: string;
229
+ /** @description Which side of `anchor` to page toward. Default `next`. */
230
+ direction?: "center" | "next" | "prev";
231
+ /** @description Omit for published-only. `all` additionally asks for pending/hidden reviews, but is honored only for a moderator/owner of the target (the type's can_moderate callback) — a non-moderator asking for `all` is silently narrowed to published, never an error. */
232
+ include?: string;
233
+ /** @description Page size, default 20, max 100. */
234
+ limit?: number;
235
+ /** @description Opaque host-owned target identifier. */
236
+ target_key: string;
237
+ /** @description Host-registered target-type key (registry.py). */
238
+ target_type: string;
239
+ };
240
+ header?: never;
241
+ path?: never;
242
+ cookie?: never;
243
+ };
244
+ requestBody?: never;
245
+ responses: {
246
+ 200: {
247
+ headers: {
248
+ [name: string]: unknown;
249
+ };
250
+ content: {
251
+ "application/json": components["schemas"]["ReviewPage"];
252
+ };
253
+ };
254
+ };
255
+ };
256
+ reviews_api_v1_reviews_create: {
257
+ parameters: {
258
+ query?: never;
259
+ header?: never;
260
+ path?: never;
261
+ cookie?: never;
262
+ };
263
+ requestBody: {
264
+ content: {
265
+ "application/json": components["schemas"]["ReviewCreateRequest"];
266
+ "application/x-www-form-urlencoded": components["schemas"]["ReviewCreateRequest"];
267
+ "multipart/form-data": components["schemas"]["ReviewCreateRequest"];
268
+ };
269
+ };
270
+ responses: {
271
+ 201: {
272
+ headers: {
273
+ [name: string]: unknown;
274
+ };
275
+ content: {
276
+ "application/json": components["schemas"]["ReviewResponse"];
277
+ };
278
+ };
279
+ };
280
+ };
281
+ reviews_api_v1_reviews_moderate_create: {
282
+ parameters: {
283
+ query?: never;
284
+ header?: never;
285
+ path: {
286
+ review_id: string;
287
+ };
288
+ cookie?: never;
289
+ };
290
+ requestBody: {
291
+ content: {
292
+ "application/json": components["schemas"]["ModerateRequest"];
293
+ "application/x-www-form-urlencoded": components["schemas"]["ModerateRequest"];
294
+ "multipart/form-data": components["schemas"]["ModerateRequest"];
295
+ };
296
+ };
297
+ responses: {
298
+ 200: {
299
+ headers: {
300
+ [name: string]: unknown;
301
+ };
302
+ content: {
303
+ "application/json": components["schemas"]["ReviewResponse"];
304
+ };
305
+ };
306
+ };
307
+ };
308
+ reviews_api_v1_reviews_response_create: {
309
+ parameters: {
310
+ query?: never;
311
+ header?: never;
312
+ path: {
313
+ review_id: string;
314
+ };
315
+ cookie?: never;
316
+ };
317
+ requestBody?: {
318
+ content: {
319
+ "application/json": components["schemas"]["RespondRequest"];
320
+ "application/x-www-form-urlencoded": components["schemas"]["RespondRequest"];
321
+ "multipart/form-data": components["schemas"]["RespondRequest"];
322
+ };
323
+ };
324
+ responses: {
325
+ 201: {
326
+ headers: {
327
+ [name: string]: unknown;
328
+ };
329
+ content: {
330
+ "application/json": components["schemas"]["ReviewResponse"];
331
+ };
332
+ };
333
+ };
334
+ };
335
+ reviews_api_v1_reviews_aggregate_retrieve: {
336
+ parameters: {
337
+ query: {
338
+ /** @description Opaque host-owned target identifier. */
339
+ target_key: string;
340
+ /** @description Host-registered target-type key (registry.py). */
341
+ target_type: string;
342
+ };
343
+ header?: never;
344
+ path?: never;
345
+ cookie?: never;
346
+ };
347
+ requestBody?: never;
348
+ responses: {
349
+ 200: {
350
+ headers: {
351
+ [name: string]: unknown;
352
+ };
353
+ content: {
354
+ "application/json": components["schemas"]["AggregateResponse"];
355
+ };
356
+ };
357
+ };
358
+ };
359
+ }
360
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/api/generated/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/api/generated/schema.ts"],"names":[],"mappings":""}
@@ -0,0 +1,89 @@
1
+ import type { StapelClient } from "@stapel/core";
2
+ import type { Review, ReviewAggregate, ReviewListParams, ReviewPage, ReviewTarget } from "./types.js";
3
+ /**
4
+ * The pair's typed operation surface — one method per stapel-reviews endpoint
5
+ * a buyer's or a seller's browser may call, bound to the injected
6
+ * {@link StapelClient} (the per-module override seam of frontend-standard
7
+ * §7.2). Paths are relative to the runtime's `baseUrl` (`/reviews/api/v1`).
8
+ *
9
+ * ── The two reads are ANONYMOUS; the write is not ─────────────────────────
10
+ *
11
+ * Since stapel-reviews 0.3.0: `ReviewListCreateView` is
12
+ * `IsAuthenticatedOrReadOnly` (GET open, POST still needs a real identity —
13
+ * there is an author to attribute the review to) and `AggregateView` is
14
+ * `AllowAny`. Both declare `stapel_anonymous_access = ANONYMOUS_ALLOWED` and
15
+ * both are throttled from the module's own settings namespace
16
+ * (`LIST_THROTTLE` 120/min, `AGGREGATE_THROTTLE` 300/min), not the project's
17
+ * `DEFAULT_THROTTLE_RATES`.
18
+ *
19
+ * Nothing new became visible: both endpoints were already published-only for
20
+ * a non-moderator. What changed for this pair is that a guest on a public
21
+ * listing page now READS the reviews instead of being told to sign in — so
22
+ * `signInRequired` is gone from the two read bags and survives only on the
23
+ * write, where a 401 is still the honest answer.
24
+ *
25
+ * ── The two operations that are NOT here, and why ─────────────────────────
26
+ *
27
+ * `POST /reviews/{id}/moderate` (hide/publish) and `POST /reviews/{id}/response`
28
+ * (the target owner's single reply) are both gated on the target type's
29
+ * `can_moderate` callback, which is **fail-closed**: a type that names no
30
+ * callback denies everyone (`registry.check_can_moderate`). They belong to a
31
+ * seller console and a moderator console, and this pair ships neither
32
+ * (storefront spec §4.4: the owner's reply is DISPLAYED in the MVP and the
33
+ * button to write one does not exist, rather than existing switched off).
34
+ *
35
+ * Both stay in the generated schema and therefore in `manifest.json`, which
36
+ * lists the whole contract — nothing is hidden; they are simply not this
37
+ * pair's surface. Adding them later is additive and needs no change here.
38
+ *
39
+ * These operations will be GENERATED from schema.json operationIds by gen-api
40
+ * v2; until then they are hand-authored here (the ONE legal home of path
41
+ * strings — `stapel/no-string-paths` §2.3 carve-out).
42
+ */
43
+ export interface ReviewsApi {
44
+ readonly client: StapelClient;
45
+ /**
46
+ * A page of a target's reviews, newest first. Anonymous callers welcome.
47
+ *
48
+ * Answers core's `AnchorPagination` envelope — declared as
49
+ * `components/ReviewPage` since 0.3.0, so the shape is generated rather
50
+ * than mirrored here. Anchors are `created_at` timestamps.
51
+ */
52
+ reviews(params: ReviewListParams, options?: {
53
+ readonly signal?: AbortSignal;
54
+ }): Promise<ReviewPage>;
55
+ /**
56
+ * The module-owned rating aggregate for ONE target — mean and count over
57
+ * published reviews. `AllowAny`.
58
+ *
59
+ * There is no batch form on the HTTP surface: `reviews.aggregates_by_keys`
60
+ * is a comm Function for server-side projections, not an endpoint. A
61
+ * storefront that needs a rating per card gets it from the listing rows its
62
+ * own module serves (fed by the composite's projection), not by firing one
63
+ * of these per card.
64
+ */
65
+ aggregate(target: ReviewTarget, options?: {
66
+ readonly signal?: AbortSignal;
67
+ }): Promise<ReviewAggregate>;
68
+ /**
69
+ * Write a review of a target. The one operation here that needs a real
70
+ * identity (`IsAuthenticatedOrReadOnly` refuses an anonymous POST).
71
+ *
72
+ * Refusals worth knowing by name, because their STATUS is not what a reader
73
+ * expects: "you have already reviewed this" is
74
+ * `error.400.reviews_duplicate_review` — a **400**, while the module's only
75
+ * 409 (`error.409.reviews_already_responded`) is about the owner's reply.
76
+ * Branching on the status code would therefore catch the wrong refusal;
77
+ * `model/submit.ts` branches on the code.
78
+ */
79
+ createReview(body: {
80
+ readonly targetType: string;
81
+ readonly targetKey: string;
82
+ readonly rating: number;
83
+ readonly body?: string;
84
+ }, options?: {
85
+ readonly signal?: AbortSignal;
86
+ }): Promise<Review>;
87
+ }
88
+ export declare function createReviewsApi(client: StapelClient): ReviewsApi;
89
+ //# sourceMappingURL=reviewsApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewsApi.d.ts","sourceRoot":"","sources":["../../src/api/reviewsApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAwB,MAAM,cAAc,CAAC;AACvE,OAAO,KAAK,EACV,MAAM,EACN,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,YAAY,EACb,MAAM,YAAY,CAAC;AAuBpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAE9B;;;;;;OAMG;IACH,OAAO,CACL,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC1C,OAAO,CAAC,UAAU,CAAC,CAAC;IAEvB;;;;;;;;;OASG;IACH,SAAS,CACP,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC1C,OAAO,CAAC,eAAe,CAAC,CAAC;IAE5B;;;;;;;;;;OAUG;IACH,YAAY,CACV,IAAI,EAAE;QACJ,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;KACxB,EACD,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC1C,OAAO,CAAC,MAAM,CAAC,CAAC;CACpB;AAOD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU,CA0CjE"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * CSRF rule for cookie-authenticated browser clients (mirrors auth-react and
3
+ * chat-react): the simplest SPA rule is to always send
4
+ * `X-Requested-With: XMLHttpRequest` on mutating requests. Header-token
5
+ * clients ignore it, so it is harmless there and every mutation carries it.
6
+ */
7
+ const CSRF_HEADERS = {
8
+ "X-Requested-With": "XMLHttpRequest",
9
+ };
10
+ function mutating(options) {
11
+ return { ...options, headers: { ...CSRF_HEADERS, ...options?.headers } };
12
+ }
13
+ /** The target pair, as the two endpoints that read it spell it. */
14
+ function targetQuery(target) {
15
+ return { target_type: target.targetType, target_key: target.targetKey };
16
+ }
17
+ const signalOf = (options) => options?.signal !== undefined ? { signal: options.signal } : {};
18
+ export function createReviewsApi(client) {
19
+ return {
20
+ client,
21
+ reviews: (params, options) => client.get("/reviews", {
22
+ query: {
23
+ ...targetQuery(params),
24
+ ...(params.include !== undefined ? { include: params.include } : {}),
25
+ ...(params.anchor !== undefined ? { anchor: params.anchor } : {}),
26
+ ...(params.direction !== undefined
27
+ ? { direction: params.direction }
28
+ : {}),
29
+ ...(params.limit !== undefined ? { limit: params.limit } : {}),
30
+ },
31
+ ...signalOf(options),
32
+ }),
33
+ aggregate: (target, options) => client.get("/reviews/aggregate", {
34
+ query: targetQuery(target),
35
+ ...signalOf(options),
36
+ }),
37
+ createReview: (body, options) => client.post("/reviews", {
38
+ target_type: body.targetType,
39
+ target_key: body.targetKey,
40
+ rating: body.rating,
41
+ // The body defaults to `""` in the request DTO
42
+ // (`dto.ReviewCreateRequest.body: str = ""`) — a rating with no
43
+ // words is a complete review here. Send the field only when there
44
+ // is text, so an empty textarea is not spelled two ways.
45
+ ...(body.body !== undefined && body.body.length > 0
46
+ ? { body: body.body }
47
+ : {}),
48
+ }, mutating(signalOf(options))),
49
+ };
50
+ }
51
+ //# sourceMappingURL=reviewsApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewsApi.js","sourceRoot":"","sources":["../../src/api/reviewsApi.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,MAAM,YAAY,GAA2B;IAC3C,kBAAkB,EAAE,gBAAgB;CACrC,CAAC;AAEF,SAAS,QAAQ,CACf,OAAuD;IAEvD,OAAO,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;AAC3E,CAAC;AAED,mEAAmE;AACnE,SAAS,WAAW,CAAC,MAAoB;IACvC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;AAC1E,CAAC;AA8FD,MAAM,QAAQ,GAAG,CAAC,OAEjB,EAA4B,EAAE,CAC7B,OAAO,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAElE,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,OAAO;QACL,MAAM;QAEN,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAC3B,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE;YACrB,KAAK,EAAE;gBACL,GAAG,WAAW,CAAC,MAAM,CAAC;gBACtB,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjE,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS;oBAChC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE;oBACjC,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC/D;YACD,GAAG,QAAQ,CAAC,OAAO,CAAC;SACrB,CAAC;QAEJ,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAC7B,MAAM,CAAC,GAAG,CAAC,oBAAoB,EAAE;YAC/B,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC;YAC1B,GAAG,QAAQ,CAAC,OAAO,CAAC;SACrB,CAAC;QAEJ,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAC9B,MAAM,CAAC,IAAI,CACT,UAAU,EACV;YACE,WAAW,EAAE,IAAI,CAAC,UAAU;YAC5B,UAAU,EAAE,IAAI,CAAC,SAAS;YAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,+CAA+C;YAC/C,gEAAgE;YAChE,kEAAkE;YAClE,yDAAyD;YACzD,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;gBACjD,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;gBACrB,CAAC,CAAC,EAAE,CAAC;SACR,EACD,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAC5B;KACJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * The pair's public wire types — projected from the GENERATED schema
3
+ * (`api/generated/schema.ts`, emitted by `pnpm gen:api` from stapel-reviews'
4
+ * own `docs/schema.json`), never re-typed by hand.
5
+ *
6
+ * **Two hand-written shapes lived here against the 0.2.2 pin and are gone.**
7
+ * `ReviewPage` and the list's `anchor`/`limit`/`direction` parameters were
8
+ * declared by this file because `ReviewListCreateView` is a bare `APIView`
9
+ * that instantiates its paginator inside `get()`: drf-spectacular's pagination
10
+ * introspection only fires for `GenericAPIView.pagination_class`, so the
11
+ * schema declared `200: ReviewResponse[]` and knew nothing of the three query
12
+ * parameters. **stapel-reviews 0.3.0 declares both** — `components/ReviewPage`
13
+ * and the parameters, `direction` with an enum — so the copies were deleted
14
+ * and everything below comes from codegen. The upstream ask that produced this
15
+ * is recorded in `contract-pins.json`.
16
+ *
17
+ * Two corrections remain, and both are widenings of what the wire can say
18
+ * rather than shapes the schema is missing:
19
+ *
20
+ * 1. **`status` is a bare `string` on the wire** and a three-member lifecycle
21
+ * in the model (`ReviewStatus`). {@link ReviewStatus} names the three
22
+ * WITHOUT narrowing a parsed value: a fourth state added upstream must
23
+ * render as an unknown state, not crash a switch.
24
+ * 2. **`avg` is `0.0` when `count` is `0`.** The type cannot express that, so
25
+ * {@link RatingAggregate} exists as the shape both this module's own
26
+ * aggregate endpoint AND the shop composite's `shop.listing_review_summary`
27
+ * projection answer with — and `model/rating.ts` is the one place allowed
28
+ * to decide what a zero means.
29
+ */
30
+ import type { components, operations } from "./generated/schema.js";
31
+ /** Every component schema stapel-reviews declares. */
32
+ export type Schemas = components["schemas"];
33
+ /** One review of an opaque target, with the owner's reply when there is one. */
34
+ export type Review = Schemas["ReviewResponse"];
35
+ /** The target owner's single reply to a review. */
36
+ export type ReviewOwnerResponse = Schemas["ResponseResponse"];
37
+ /** `POST /reviews` request body. */
38
+ export type ReviewCreateRequest = Schemas["ReviewCreateRequest"];
39
+ /**
40
+ * `GET /reviews/aggregate` 200 body — the module-owned aggregate for ONE
41
+ * target, carrying the target it is about.
42
+ */
43
+ export type ReviewAggregate = Schemas["AggregateResponse"];
44
+ /**
45
+ * The 200 body of `GET /reviews` — core's `AnchorPagination` envelope,
46
+ * generated since 0.3.0 (see this module's header).
47
+ *
48
+ * `count` is the number of rows in THIS page, not the total; the total number
49
+ * of published reviews is the aggregate's `count`, which is a different number
50
+ * computed a different way.
51
+ */
52
+ export type ReviewPage = Schemas["ReviewPage"];
53
+ /** The generated query surface of `GET /reviews`. */
54
+ type ReviewListQuery = NonNullable<operations["reviews_api_v1_reviews_retrieve"]["parameters"]["query"]>;
55
+ /**
56
+ * A review's visibility, as `models.ReviewStatus` spells it.
57
+ *
58
+ * - `published` — visible to everyone and counted in the aggregate.
59
+ * - `pending` — created under PRE-moderation; invisible until a moderator
60
+ * publishes it, **including to its own author**, who therefore cannot see
61
+ * the review they just wrote in the published-only list.
62
+ * - `hidden` — moderated out; invisible and excluded from the aggregate.
63
+ *
64
+ * Only reachable in a list response when the caller asked for `include=all`
65
+ * AND the target type's `can_moderate` callback said yes; a non-moderator's
66
+ * `include=all` is silently narrowed to published (`views.py`).
67
+ */
68
+ export type ReviewStatus = "pending" | "published" | "hidden";
69
+ /**
70
+ * The two halves of the module's opaque address. There is no foreign key
71
+ * anywhere in stapel-reviews: `target_type` is a key the HOST registered in
72
+ * `STAPEL_REVIEWS["TARGET_TYPES"]` (the built-in registry is EMPTY) and
73
+ * `target_key` is a host-owned string the module stores, groups by, and never
74
+ * parses.
75
+ *
76
+ * This package therefore ships no target-type constants — not even
77
+ * `"listing"`. The catalogue shop composite registers that name in its own
78
+ * preset (`stapel_shop/preset.py`), a different deployment registers
79
+ * `"seller"` or `"course"`, and a library that guessed would be wrong for
80
+ * every host but one.
81
+ */
82
+ export interface ReviewTarget {
83
+ readonly targetType: string;
84
+ readonly targetKey: string;
85
+ }
86
+ /** The rating roll-up itself, without the target it belongs to.
87
+ *
88
+ * Deliberately the same two field names the composite's projection uses
89
+ * (`shop.listing_review_summary` → `{avg, count}`, `stapel_shop/models.py`):
90
+ * a seller-level rating is computed by the composite and handed to this
91
+ * pair's display as data, because stapel-reviews can only aggregate ONE
92
+ * `(target_type, target_key)` at a time and has no roll-up endpoint. Same
93
+ * shape in, same rendering out — see {@link ratingSummary}. */
94
+ export interface RatingAggregate {
95
+ /** Mean rating over PUBLISHED reviews. `0` when `count` is `0` — which is
96
+ * "nobody has rated this", never "everyone rated it zero". */
97
+ readonly avg: number;
98
+ /** Number of published reviews. */
99
+ readonly count: number;
100
+ }
101
+ /**
102
+ * Anchor-pagination direction — the enum the schema now carries. The review
103
+ * list is ordered `-created_at`, so:
104
+ *
105
+ * - `next` (default) — reviews OLDER than the anchor (the load-more direction),
106
+ * - `prev` — reviews NEWER than the anchor,
107
+ * - `center` — a window around the anchor.
108
+ */
109
+ export type ReviewAnchorDirection = NonNullable<ReviewListQuery["direction"]>;
110
+ /**
111
+ * Query for `GET /reviews`: the generated parameters, with only the target
112
+ * pair renamed to this package's camelCase {@link ReviewTarget}. Nothing here
113
+ * is hand-typed any more — `include`, `anchor`, `limit` and `direction` are
114
+ * exactly what the contract declares.
115
+ *
116
+ * `target_type`/`target_key` are required by the view (a missing one is
117
+ * `error.400.reviews_unknown_target_type`, not an empty list). `anchor` is a
118
+ * `created_at` ISO timestamp and exclusive. `include` is typed `string`
119
+ * because the schema declares no enum for it: the view acts on the literal
120
+ * `"all"` and treats anything else as published-only, silently — which is why
121
+ * the hook option that offers it (`UseReviewListOptions.include`) narrows to
122
+ * the one value the server actually reads.
123
+ */
124
+ export interface ReviewListParams extends ReviewTarget, Omit<ReviewListQuery, "target_type" | "target_key"> {
125
+ }
126
+ export {};
127
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEpE,sDAAsD;AACtD,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;AAE5C,gFAAgF;AAChF,MAAM,MAAM,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE/C,mDAAmD;AACnD,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAE9D,oCAAoC;AACpC,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;AAEjE;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAE/C,qDAAqD;AACrD,KAAK,eAAe,GAAG,WAAW,CAChC,UAAU,CAAC,iCAAiC,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CACrE,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE9D;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;+DAO+D;AAC/D,MAAM,WAAW,eAAe;IAC9B;kEAC8D;IAC9D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;AAE9E;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,gBACf,SAAQ,YAAY,EAClB,IAAI,CAAC,eAAe,EAAE,aAAa,GAAG,YAAY,CAAC;CAAG"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map