@intlayer/backend-contract 0.0.0-stage → 9.7.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 (252) hide show
  1. package/dist/cjs/ai.cjs +267 -0
  2. package/dist/cjs/ai.cjs.map +1 -0
  3. package/dist/cjs/analytics.cjs +175 -0
  4. package/dist/cjs/analytics.cjs.map +1 -0
  5. package/dist/cjs/asset.cjs +88 -0
  6. package/dist/cjs/asset.cjs.map +1 -0
  7. package/dist/cjs/blogComment.cjs +98 -0
  8. package/dist/cjs/blogComment.cjs.map +1 -0
  9. package/dist/cjs/cliSessionToken.cjs +40 -0
  10. package/dist/cjs/cliSessionToken.cjs.map +1 -0
  11. package/dist/cjs/common.cjs +42 -0
  12. package/dist/cjs/common.cjs.map +1 -0
  13. package/dist/cjs/defineRoute.cjs +26 -0
  14. package/dist/cjs/defineRoute.cjs.map +1 -0
  15. package/dist/cjs/demo.cjs +22 -0
  16. package/dist/cjs/demo.cjs.map +1 -0
  17. package/dist/cjs/dictionary.cjs +168 -0
  18. package/dist/cjs/dictionary.cjs.map +1 -0
  19. package/dist/cjs/environment.cjs +91 -0
  20. package/dist/cjs/environment.cjs.map +1 -0
  21. package/dist/cjs/eventListener.cjs +19 -0
  22. package/dist/cjs/eventListener.cjs.map +1 -0
  23. package/dist/cjs/gitProviders.cjs +361 -0
  24. package/dist/cjs/gitProviders.cjs.map +1 -0
  25. package/dist/cjs/newsletter.cjs +50 -0
  26. package/dist/cjs/newsletter.cjs.map +1 -0
  27. package/dist/cjs/oAuth2.cjs +62 -0
  28. package/dist/cjs/oAuth2.cjs.map +1 -0
  29. package/dist/cjs/organization.cjs +226 -0
  30. package/dist/cjs/organization.cjs.map +1 -0
  31. package/dist/cjs/project.cjs +401 -0
  32. package/dist/cjs/project.cjs.map +1 -0
  33. package/dist/cjs/public.cjs +60 -0
  34. package/dist/cjs/public.cjs.map +1 -0
  35. package/dist/cjs/responseData.cjs +33 -0
  36. package/dist/cjs/responseData.cjs.map +1 -0
  37. package/dist/cjs/reviewer.cjs +401 -0
  38. package/dist/cjs/reviewer.cjs.map +1 -0
  39. package/dist/cjs/scan.cjs +235 -0
  40. package/dist/cjs/scan.cjs.map +1 -0
  41. package/dist/cjs/search.cjs +40 -0
  42. package/dist/cjs/search.cjs.map +1 -0
  43. package/dist/cjs/session.cjs +56 -0
  44. package/dist/cjs/session.cjs.map +1 -0
  45. package/dist/cjs/showcaseProject.cjs +185 -0
  46. package/dist/cjs/showcaseProject.cjs.map +1 -0
  47. package/dist/cjs/stripe.cjs +388 -0
  48. package/dist/cjs/stripe.cjs.map +1 -0
  49. package/dist/cjs/tag.cjs +83 -0
  50. package/dist/cjs/tag.cjs.map +1 -0
  51. package/dist/cjs/translation.cjs +54 -0
  52. package/dist/cjs/translation.cjs.map +1 -0
  53. package/dist/cjs/user.cjs +153 -0
  54. package/dist/cjs/user.cjs.map +1 -0
  55. package/dist/esm/ai.mjs +261 -0
  56. package/dist/esm/ai.mjs.map +1 -0
  57. package/dist/esm/analytics.mjs +168 -0
  58. package/dist/esm/analytics.mjs.map +1 -0
  59. package/dist/esm/asset.mjs +86 -0
  60. package/dist/esm/asset.mjs.map +1 -0
  61. package/dist/esm/blogComment.mjs +94 -0
  62. package/dist/esm/blogComment.mjs.map +1 -0
  63. package/dist/esm/cliSessionToken.mjs +39 -0
  64. package/dist/esm/cliSessionToken.mjs.map +1 -0
  65. package/dist/esm/common.mjs +35 -0
  66. package/dist/esm/common.mjs.map +1 -0
  67. package/dist/esm/defineRoute.mjs +23 -0
  68. package/dist/esm/defineRoute.mjs.map +1 -0
  69. package/dist/esm/demo.mjs +21 -0
  70. package/dist/esm/demo.mjs.map +1 -0
  71. package/dist/esm/dictionary.mjs +163 -0
  72. package/dist/esm/dictionary.mjs.map +1 -0
  73. package/dist/esm/environment.mjs +90 -0
  74. package/dist/esm/environment.mjs.map +1 -0
  75. package/dist/esm/eventListener.mjs +18 -0
  76. package/dist/esm/eventListener.mjs.map +1 -0
  77. package/dist/esm/gitProviders.mjs +352 -0
  78. package/dist/esm/gitProviders.mjs.map +1 -0
  79. package/dist/esm/newsletter.mjs +49 -0
  80. package/dist/esm/newsletter.mjs.map +1 -0
  81. package/dist/esm/oAuth2.mjs +60 -0
  82. package/dist/esm/oAuth2.mjs.map +1 -0
  83. package/dist/esm/organization.mjs +219 -0
  84. package/dist/esm/organization.mjs.map +1 -0
  85. package/dist/esm/project.mjs +387 -0
  86. package/dist/esm/project.mjs.map +1 -0
  87. package/dist/esm/public.mjs +58 -0
  88. package/dist/esm/public.mjs.map +1 -0
  89. package/dist/esm/responseData.mjs +30 -0
  90. package/dist/esm/responseData.mjs.map +1 -0
  91. package/dist/esm/reviewer.mjs +390 -0
  92. package/dist/esm/reviewer.mjs.map +1 -0
  93. package/dist/esm/scan.mjs +225 -0
  94. package/dist/esm/scan.mjs.map +1 -0
  95. package/dist/esm/search.mjs +38 -0
  96. package/dist/esm/search.mjs.map +1 -0
  97. package/dist/esm/session.mjs +53 -0
  98. package/dist/esm/session.mjs.map +1 -0
  99. package/dist/esm/showcaseProject.mjs +182 -0
  100. package/dist/esm/showcaseProject.mjs.map +1 -0
  101. package/dist/esm/stripe.mjs +379 -0
  102. package/dist/esm/stripe.mjs.map +1 -0
  103. package/dist/esm/tag.mjs +81 -0
  104. package/dist/esm/tag.mjs.map +1 -0
  105. package/dist/esm/translation.mjs +53 -0
  106. package/dist/esm/translation.mjs.map +1 -0
  107. package/dist/esm/user.mjs +149 -0
  108. package/dist/esm/user.mjs.map +1 -0
  109. package/dist/types/@intlayer/config/dist/types/defaultValues/dictionary.d.ts +1 -0
  110. package/dist/types/@intlayer/config/dist/types/defaultValues/index.d.ts +3 -0
  111. package/dist/types/@intlayer/config/dist/types/defaultValues/internationalization.d.ts +2 -0
  112. package/dist/types/@intlayer/config/dist/types/defaultValues/routing.d.ts +1 -0
  113. package/dist/types/@intlayer/core/dist/types/dictionaryManipulator/plainDynamicLoader.d.ts +2 -0
  114. package/dist/types/@intlayer/core/dist/types/dictionaryManipulator/qualifiedDynamicLoader.d.ts +2 -0
  115. package/dist/types/@intlayer/core/dist/types/formatters/compact.d.ts +1 -0
  116. package/dist/types/@intlayer/core/dist/types/formatters/currency.d.ts +1 -0
  117. package/dist/types/@intlayer/core/dist/types/formatters/date.d.ts +1 -0
  118. package/dist/types/@intlayer/core/dist/types/formatters/index.d.ts +9 -0
  119. package/dist/types/@intlayer/core/dist/types/formatters/list.d.ts +1 -0
  120. package/dist/types/@intlayer/core/dist/types/formatters/number.d.ts +1 -0
  121. package/dist/types/@intlayer/core/dist/types/formatters/percentage.d.ts +1 -0
  122. package/dist/types/@intlayer/core/dist/types/formatters/relativeTime.d.ts +1 -0
  123. package/dist/types/@intlayer/core/dist/types/formatters/units.d.ts +1 -0
  124. package/dist/types/@intlayer/core/dist/types/interpreter/dictionaryTransformCache.d.ts +4 -0
  125. package/dist/types/@intlayer/core/dist/types/interpreter/getCondition.d.ts +2 -0
  126. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/deepTransform.d.ts +1 -0
  127. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/getContent.d.ts +3 -0
  128. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/index.d.ts +3 -0
  129. package/dist/types/@intlayer/core/dist/types/interpreter/getContent/plugins.d.ts +7 -0
  130. package/dist/types/@intlayer/core/dist/types/interpreter/getDictionary.d.ts +4 -0
  131. package/dist/types/@intlayer/core/dist/types/interpreter/getDictionaryAsync.d.ts +6 -0
  132. package/dist/types/@intlayer/core/dist/types/interpreter/getEnumeration.d.ts +2 -0
  133. package/dist/types/@intlayer/core/dist/types/interpreter/getGender.d.ts +2 -0
  134. package/dist/types/@intlayer/core/dist/types/interpreter/getInsertion.d.ts +2 -0
  135. package/dist/types/@intlayer/core/dist/types/interpreter/getIntlayer.d.ts +4 -0
  136. package/dist/types/@intlayer/core/dist/types/interpreter/getIntlayerAsync.d.ts +4 -0
  137. package/dist/types/@intlayer/core/dist/types/interpreter/getNesting.d.ts +6 -0
  138. package/dist/types/@intlayer/core/dist/types/interpreter/getPlural.d.ts +3 -0
  139. package/dist/types/@intlayer/core/dist/types/interpreter/getSelect.d.ts +2 -0
  140. package/dist/types/@intlayer/core/dist/types/interpreter/getTranslation.d.ts +1 -0
  141. package/dist/types/@intlayer/core/dist/types/interpreter/index.d.ts +19 -0
  142. package/dist/types/@intlayer/core/dist/types/interpreter/interpolableNode.d.ts +2 -0
  143. package/dist/types/@intlayer/core/dist/types/interpreter/resolveInterpreterLocale.d.ts +1 -0
  144. package/dist/types/@intlayer/core/dist/types/localization/comparePaths.d.ts +1 -0
  145. package/dist/types/@intlayer/core/dist/types/localization/domainUtils.d.ts +2 -0
  146. package/dist/types/@intlayer/core/dist/types/localization/generateSitemap.d.ts +2 -0
  147. package/dist/types/@intlayer/core/dist/types/localization/getBrowserLocale.d.ts +1 -0
  148. package/dist/types/@intlayer/core/dist/types/localization/getCanonicalPath.d.ts +2 -0
  149. package/dist/types/@intlayer/core/dist/types/localization/getHTMLTextDir.d.ts +1 -0
  150. package/dist/types/@intlayer/core/dist/types/localization/getLocale.d.ts +1 -0
  151. package/dist/types/@intlayer/core/dist/types/localization/getLocaleFromPath.d.ts +2 -0
  152. package/dist/types/@intlayer/core/dist/types/localization/getLocaleFromRequest.d.ts +1 -0
  153. package/dist/types/@intlayer/core/dist/types/localization/getLocaleLang.d.ts +1 -0
  154. package/dist/types/@intlayer/core/dist/types/localization/getLocaleName.d.ts +1 -0
  155. package/dist/types/@intlayer/core/dist/types/localization/getLocalizedPath.d.ts +2 -0
  156. package/dist/types/@intlayer/core/dist/types/localization/getLocalizedUrl.d.ts +2 -0
  157. package/dist/types/@intlayer/core/dist/types/localization/getMultilingualUrls.d.ts +2 -0
  158. package/dist/types/@intlayer/core/dist/types/localization/getPathWithoutLocale.d.ts +1 -0
  159. package/dist/types/@intlayer/core/dist/types/localization/getPrefix.d.ts +2 -0
  160. package/dist/types/@intlayer/core/dist/types/localization/index.d.ts +23 -0
  161. package/dist/types/@intlayer/core/dist/types/localization/localeDetector.d.ts +2 -0
  162. package/dist/types/@intlayer/core/dist/types/localization/localeMapper.d.ts +1 -0
  163. package/dist/types/@intlayer/core/dist/types/localization/localeResolver.d.ts +1 -0
  164. package/dist/types/@intlayer/core/dist/types/localization/resolveBrowserLocale.d.ts +2 -0
  165. package/dist/types/@intlayer/core/dist/types/localization/rewriteMatch.d.ts +1 -0
  166. package/dist/types/@intlayer/core/dist/types/localization/rewriteUtils.d.ts +2 -0
  167. package/dist/types/@intlayer/core/dist/types/localization/validatePrefix.d.ts +2 -0
  168. package/dist/types/@intlayer/core/dist/types/markdown/index.d.ts +2 -0
  169. package/dist/types/@intlayer/core/dist/types/transpiler/condition/condition.d.ts +1 -0
  170. package/dist/types/@intlayer/core/dist/types/transpiler/condition/index.d.ts +1 -0
  171. package/dist/types/@intlayer/core/dist/types/transpiler/enumeration/enumeration.d.ts +1 -0
  172. package/dist/types/@intlayer/core/dist/types/transpiler/enumeration/index.d.ts +1 -0
  173. package/dist/types/@intlayer/core/dist/types/transpiler/file/file.d.ts +1 -0
  174. package/dist/types/@intlayer/core/dist/types/transpiler/file/index.d.ts +1 -0
  175. package/dist/types/@intlayer/core/dist/types/transpiler/gender/gender.d.ts +1 -0
  176. package/dist/types/@intlayer/core/dist/types/transpiler/gender/index.d.ts +1 -0
  177. package/dist/types/@intlayer/core/dist/types/transpiler/html/html.d.ts +1 -0
  178. package/dist/types/@intlayer/core/dist/types/transpiler/html/index.d.ts +1 -0
  179. package/dist/types/@intlayer/core/dist/types/transpiler/index.d.ts +22 -0
  180. package/dist/types/@intlayer/core/dist/types/transpiler/insertion/index.d.ts +1 -0
  181. package/dist/types/@intlayer/core/dist/types/transpiler/insertion/insertion.d.ts +1 -0
  182. package/dist/types/@intlayer/core/dist/types/transpiler/markdown/index.d.ts +1 -0
  183. package/dist/types/@intlayer/core/dist/types/transpiler/markdown/markdown.d.ts +1 -0
  184. package/dist/types/@intlayer/core/dist/types/transpiler/nesting/index.d.ts +1 -0
  185. package/dist/types/@intlayer/core/dist/types/transpiler/nesting/nesting.d.ts +4 -0
  186. package/dist/types/@intlayer/core/dist/types/transpiler/plural/index.d.ts +1 -0
  187. package/dist/types/@intlayer/core/dist/types/transpiler/plural/plural.d.ts +1 -0
  188. package/dist/types/@intlayer/core/dist/types/transpiler/select/index.d.ts +1 -0
  189. package/dist/types/@intlayer/core/dist/types/transpiler/select/select.d.ts +1 -0
  190. package/dist/types/@intlayer/core/dist/types/transpiler/translation/index.d.ts +1 -0
  191. package/dist/types/@intlayer/core/dist/types/transpiler/translation/translation.d.ts +2 -0
  192. package/dist/types/@intlayer/core/dist/types/utils/index.d.ts +3 -0
  193. package/dist/types/@intlayer/core/dist/types/utils/intl.d.ts +1 -0
  194. package/dist/types/@intlayer/core/dist/types/utils/isSameKeyPath.d.ts +1 -0
  195. package/dist/types/@intlayer/core/dist/types/utils/localeStorage.d.ts +2 -0
  196. package/dist/types/ai.d.ts +549 -0
  197. package/dist/types/ai.d.ts.map +1 -0
  198. package/dist/types/analytics.d.ts +378 -0
  199. package/dist/types/analytics.d.ts.map +1 -0
  200. package/dist/types/asset.d.ts +207 -0
  201. package/dist/types/asset.d.ts.map +1 -0
  202. package/dist/types/blogComment.d.ts +241 -0
  203. package/dist/types/blogComment.d.ts.map +1 -0
  204. package/dist/types/cliSessionToken.d.ts +264 -0
  205. package/dist/types/cliSessionToken.d.ts.map +1 -0
  206. package/dist/types/common.d.ts +32 -0
  207. package/dist/types/common.d.ts.map +1 -0
  208. package/dist/types/defineRoute.d.ts +57 -0
  209. package/dist/types/defineRoute.d.ts.map +1 -0
  210. package/dist/types/demo.d.ts +21 -0
  211. package/dist/types/demo.d.ts.map +1 -0
  212. package/dist/types/dictionary.d.ts +360 -0
  213. package/dist/types/dictionary.d.ts.map +1 -0
  214. package/dist/types/environment.d.ts +285 -0
  215. package/dist/types/environment.d.ts.map +1 -0
  216. package/dist/types/eventListener.d.ts +17 -0
  217. package/dist/types/eventListener.d.ts.map +1 -0
  218. package/dist/types/gitProviders.d.ts +807 -0
  219. package/dist/types/gitProviders.d.ts.map +1 -0
  220. package/dist/types/intlayer/dist/types/index.d.ts +13 -0
  221. package/dist/types/newsletter.d.ts +165 -0
  222. package/dist/types/newsletter.d.ts.map +1 -0
  223. package/dist/types/oAuth2.d.ts +482 -0
  224. package/dist/types/oAuth2.d.ts.map +1 -0
  225. package/dist/types/organization.d.ts +1069 -0
  226. package/dist/types/organization.d.ts.map +1 -0
  227. package/dist/types/project.d.ts +1735 -0
  228. package/dist/types/project.d.ts.map +1 -0
  229. package/dist/types/public.d.ts +109 -0
  230. package/dist/types/public.d.ts.map +1 -0
  231. package/dist/types/responseData.d.ts +68 -0
  232. package/dist/types/responseData.d.ts.map +1 -0
  233. package/dist/types/reviewer.d.ts +1239 -0
  234. package/dist/types/reviewer.d.ts.map +1 -0
  235. package/dist/types/scan.d.ts +625 -0
  236. package/dist/types/scan.d.ts.map +1 -0
  237. package/dist/types/search.d.ts +55 -0
  238. package/dist/types/search.d.ts.map +1 -0
  239. package/dist/types/session.d.ts +286 -0
  240. package/dist/types/session.d.ts.map +1 -0
  241. package/dist/types/showcaseProject.d.ts +550 -0
  242. package/dist/types/showcaseProject.d.ts.map +1 -0
  243. package/dist/types/stripe.d.ts +1219 -0
  244. package/dist/types/stripe.d.ts.map +1 -0
  245. package/dist/types/tag.d.ts +193 -0
  246. package/dist/types/tag.d.ts.map +1 -0
  247. package/dist/types/translation.d.ts +162 -0
  248. package/dist/types/translation.d.ts.map +1 -0
  249. package/dist/types/user.d.ts +447 -0
  250. package/dist/types/user.d.ts.map +1 -0
  251. package/package.json +300 -4
  252. package/README.md +0 -3
@@ -0,0 +1,153 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_common = require('./common.cjs');
3
+ const require_defineRoute = require('./defineRoute.cjs');
4
+ const require_responseData = require('./responseData.cjs');
5
+ let zod_mini = require("zod/mini");
6
+
7
+ //#region src/user.ts
8
+ /** Mailing lists a user can subscribe to. */
9
+ const emailsListSchema = zod_mini.z.enum(["newsLetter"]);
10
+ /** Mailing list names, usable as values (`EmailsList.NEWS_LETTER`). */
11
+ const EmailsList = { NEWS_LETTER: "newsLetter" };
12
+ /** User as returned by the API (auth provider and session internals stripped). */
13
+ const userSchema = zod_mini.z.looseObject({
14
+ id: zod_mini.z.string(),
15
+ email: zod_mini.z.string(),
16
+ emailVerified: zod_mini.z.boolean(),
17
+ name: zod_mini.z.string(),
18
+ image: zod_mini.z.optional(zod_mini.z.nullable(zod_mini.z.string())),
19
+ phone: zod_mini.z.optional(zod_mini.z.string()),
20
+ dateOfBirth: zod_mini.z.optional(require_common.dateTimeSchema),
21
+ emailsList: zod_mini.z.optional(zod_mini.z.partialRecord(emailsListSchema, zod_mini.z.boolean())),
22
+ /** Stripe customer id. */
23
+ customerId: zod_mini.z.optional(zod_mini.z.string()),
24
+ role: zod_mini.z.optional(zod_mini.z.nullable(zod_mini.z.string())),
25
+ lastLoginMethod: zod_mini.z.optional(zod_mini.z.enum([
26
+ "email",
27
+ "google",
28
+ "github",
29
+ "passkey"
30
+ ])),
31
+ lang: zod_mini.z.optional(zod_mini.z.string()),
32
+ lastActiveOrganizationId: zod_mini.z.optional(zod_mini.z.nullable(zod_mini.z.string())),
33
+ lastActiveProjectId: zod_mini.z.optional(zod_mini.z.nullable(zod_mini.z.string())),
34
+ createdAt: require_common.dateTimeSchema,
35
+ updatedAt: require_common.dateTimeSchema
36
+ });
37
+ const userIdParamsSchema = zod_mini.z.object({ userId: require_common.objectIdSchema });
38
+ /** REST contract of the `/api/user` routes. */
39
+ const userContract = require_defineRoute.defineRouteGroup({
40
+ prefix: "/api/user",
41
+ tag: "User",
42
+ routes: {
43
+ getSetupStatus: require_defineRoute.defineRoute({
44
+ method: "GET",
45
+ path: "/setup",
46
+ summary: "Whether the instance still needs its first admin (self-hosted)",
47
+ schemas: { response: { 200: require_responseData.responseDataSchema(zod_mini.z.object({ isSetupRequired: zod_mini.z.boolean() })) } }
48
+ }),
49
+ getUsers: require_defineRoute.defineRoute({
50
+ method: "GET",
51
+ path: "/",
52
+ summary: "List users (organization members, or all for admins)",
53
+ schemas: {
54
+ querystring: zod_mini.z.looseObject({
55
+ ...require_common.paginationQueryShape,
56
+ ids: zod_mini.z.optional(require_common.repeatableQueryValueSchema),
57
+ firstName: zod_mini.z.optional(zod_mini.z.string()),
58
+ lastName: zod_mini.z.optional(zod_mini.z.string()),
59
+ email: zod_mini.z.optional(zod_mini.z.string()),
60
+ emailVerified: zod_mini.z.optional(zod_mini.z.string()),
61
+ role: zod_mini.z.optional(zod_mini.z.string()),
62
+ search: zod_mini.z.optional(zod_mini.z.string()),
63
+ sortBy: zod_mini.z.optional(zod_mini.z.string()),
64
+ sortOrder: zod_mini.z.optional(zod_mini.z.string()),
65
+ /** Admin only: list every user. */
66
+ fetchAll: zod_mini.z.optional(zod_mini.z.enum(["true", "false"]))
67
+ }),
68
+ response: { 200: require_responseData.paginatedResponseSchema(userSchema) }
69
+ }
70
+ }),
71
+ updateUser: require_defineRoute.defineRoute({
72
+ method: "PUT",
73
+ path: "/",
74
+ summary: "Update a user profile",
75
+ schemas: {
76
+ /**
77
+ * Allow-list. `role`, `emailVerified` and `email` are honoured for
78
+ * admins only (users change their email through the verified auth
79
+ * flow). A new `email` is unverified unless `emailVerified` is sent.
80
+ */
81
+ body: zod_mini.z.object({
82
+ id: require_common.objectIdSchema,
83
+ name: zod_mini.z.optional(zod_mini.z.string().check(zod_mini.z.minLength(1))),
84
+ email: zod_mini.z.optional(zod_mini.z.string().check(zod_mini.z.email())),
85
+ phone: zod_mini.z.optional(zod_mini.z.string()),
86
+ image: zod_mini.z.optional(zod_mini.z.nullable(zod_mini.z.string())),
87
+ lang: zod_mini.z.optional(zod_mini.z.string()),
88
+ emailVerified: zod_mini.z.optional(zod_mini.z.boolean()),
89
+ role: zod_mini.z.optional(zod_mini.z.nullable(zod_mini.z.string()))
90
+ }),
91
+ response: { 200: require_responseData.responseDataSchema(userSchema) }
92
+ }
93
+ }),
94
+ createUser: require_defineRoute.defineRoute({
95
+ method: "POST",
96
+ path: "/",
97
+ summary: "Admin only: create a user (sign-up goes through auth)",
98
+ schemas: {
99
+ body: zod_mini.z.object({
100
+ email: zod_mini.z.string().check(zod_mini.z.minLength(1)),
101
+ name: zod_mini.z.optional(zod_mini.z.string())
102
+ }),
103
+ response: { 200: require_responseData.responseDataSchema(userSchema) }
104
+ }
105
+ }),
106
+ getUserById: require_defineRoute.defineRoute({
107
+ method: "GET",
108
+ path: "/:userId",
109
+ summary: "Get a user",
110
+ schemas: {
111
+ params: userIdParamsSchema,
112
+ response: { 200: require_responseData.responseDataSchema(userSchema) }
113
+ }
114
+ }),
115
+ getUserByEmail: require_defineRoute.defineRoute({
116
+ method: "GET",
117
+ path: "/email/:email",
118
+ summary: "Get a user by email",
119
+ schemas: {
120
+ params: zod_mini.z.object({ email: zod_mini.z.string().check(zod_mini.z.minLength(1)) }),
121
+ response: { 200: require_responseData.responseDataSchema(userSchema) }
122
+ }
123
+ }),
124
+ deleteUser: require_defineRoute.defineRoute({
125
+ method: "DELETE",
126
+ path: "/:userId",
127
+ summary: "Delete a user",
128
+ schemas: {
129
+ params: userIdParamsSchema,
130
+ response: { 200: require_responseData.responseDataSchema(userSchema) }
131
+ }
132
+ }),
133
+ verifyEmailStatusSSE: require_defineRoute.defineRoute({
134
+ method: "GET",
135
+ path: "/verify-email-status/:userId",
136
+ summary: "Email verification status (server-sent events stream)",
137
+ schemas: { params: userIdParamsSchema }
138
+ }),
139
+ uploadAvatar: require_defineRoute.defineRoute({
140
+ method: "POST",
141
+ path: "/avatar",
142
+ summary: "Upload the avatar of the signed-in user (raw image body)",
143
+ schemas: { response: { 200: require_responseData.responseDataSchema(userSchema) } }
144
+ })
145
+ }
146
+ });
147
+
148
+ //#endregion
149
+ exports.EmailsList = EmailsList;
150
+ exports.emailsListSchema = emailsListSchema;
151
+ exports.userContract = userContract;
152
+ exports.userSchema = userSchema;
153
+ //# sourceMappingURL=user.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user.cjs","names":["z","dateTimeSchema","objectIdSchema","defineRouteGroup","defineRoute","responseDataSchema","paginationQueryShape","repeatableQueryValueSchema","paginatedResponseSchema"],"sources":["../../src/user.ts"],"sourcesContent":["import { z } from 'zod/mini';\nimport {\n dateTimeSchema,\n objectIdSchema,\n paginationQueryShape,\n repeatableQueryValueSchema,\n} from './common';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBodyInput,\n type RouteParams,\n type RouteQuerystring,\n} from './defineRoute';\nimport {\n type PaginatedResponse,\n paginatedResponseSchema,\n type ResponseData,\n responseDataSchema,\n} from './responseData';\n\n/** Mailing lists a user can subscribe to. */\nexport const emailsListSchema = z.enum(['newsLetter']);\n\n/** Mailing list names, usable as values (`EmailsList.NEWS_LETTER`). */\nexport const EmailsList = { NEWS_LETTER: 'newsLetter' } as const;\nexport type EmailsList = z.output<typeof emailsListSchema>;\n\n/** User as returned by the API (auth provider and session internals stripped). */\nexport const userSchema = z.looseObject({\n id: z.string(),\n email: z.string(),\n emailVerified: z.boolean(),\n name: z.string(),\n image: z.optional(z.nullable(z.string())),\n phone: z.optional(z.string()),\n dateOfBirth: z.optional(dateTimeSchema),\n emailsList: z.optional(z.partialRecord(emailsListSchema, z.boolean())),\n /** Stripe customer id. */\n customerId: z.optional(z.string()),\n role: z.optional(z.nullable(z.string())),\n lastLoginMethod: z.optional(z.enum(['email', 'google', 'github', 'passkey'])),\n lang: z.optional(z.string()),\n lastActiveOrganizationId: z.optional(z.nullable(z.string())),\n lastActiveProjectId: z.optional(z.nullable(z.string())),\n createdAt: dateTimeSchema,\n updatedAt: dateTimeSchema,\n});\n\nexport type UserAPI = z.output<typeof userSchema>;\n\nconst userIdParamsSchema = z.object({ userId: objectIdSchema });\n\n/** REST contract of the `/api/user` routes. */\nexport const userContract = defineRouteGroup({\n prefix: '/api/user',\n tag: 'User',\n routes: {\n getSetupStatus: defineRoute({\n method: 'GET',\n path: '/setup',\n summary: 'Whether the instance still needs its first admin (self-hosted)',\n schemas: {\n response: {\n 200: responseDataSchema(z.object({ isSetupRequired: z.boolean() })),\n },\n },\n }),\n getUsers: defineRoute({\n method: 'GET',\n path: '/',\n summary: 'List users (organization members, or all for admins)',\n schemas: {\n querystring: z.looseObject({\n ...paginationQueryShape,\n ids: z.optional(repeatableQueryValueSchema),\n firstName: z.optional(z.string()),\n lastName: z.optional(z.string()),\n email: z.optional(z.string()),\n emailVerified: z.optional(z.string()),\n role: z.optional(z.string()),\n search: z.optional(z.string()),\n sortBy: z.optional(z.string()),\n sortOrder: z.optional(z.string()),\n /** Admin only: list every user. */\n fetchAll: z.optional(z.enum(['true', 'false'])),\n }),\n response: { 200: paginatedResponseSchema(userSchema) },\n },\n }),\n updateUser: defineRoute({\n method: 'PUT',\n path: '/',\n summary: 'Update a user profile',\n schemas: {\n /**\n * Allow-list. `role`, `emailVerified` and `email` are honoured for\n * admins only (users change their email through the verified auth\n * flow). A new `email` is unverified unless `emailVerified` is sent.\n */\n body: z.object({\n id: objectIdSchema,\n name: z.optional(z.string().check(z.minLength(1))),\n email: z.optional(z.string().check(z.email())),\n phone: z.optional(z.string()),\n image: z.optional(z.nullable(z.string())),\n lang: z.optional(z.string()),\n emailVerified: z.optional(z.boolean()),\n role: z.optional(z.nullable(z.string())),\n }),\n response: { 200: responseDataSchema(userSchema) },\n },\n }),\n createUser: defineRoute({\n method: 'POST',\n path: '/',\n summary: 'Admin only: create a user (sign-up goes through auth)',\n schemas: {\n body: z.object({\n email: z.string().check(z.minLength(1)),\n name: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(userSchema) },\n },\n }),\n getUserById: defineRoute({\n method: 'GET',\n path: '/:userId',\n summary: 'Get a user',\n schemas: {\n params: userIdParamsSchema,\n response: { 200: responseDataSchema(userSchema) },\n },\n }),\n getUserByEmail: defineRoute({\n method: 'GET',\n path: '/email/:email',\n summary: 'Get a user by email',\n schemas: {\n params: z.object({ email: z.string().check(z.minLength(1)) }),\n response: { 200: responseDataSchema(userSchema) },\n },\n }),\n deleteUser: defineRoute({\n method: 'DELETE',\n path: '/:userId',\n summary: 'Delete a user',\n schemas: {\n params: userIdParamsSchema,\n response: { 200: responseDataSchema(userSchema) },\n },\n }),\n verifyEmailStatusSSE: defineRoute({\n method: 'GET',\n path: '/verify-email-status/:userId',\n summary: 'Email verification status (server-sent events stream)',\n schemas: {\n params: userIdParamsSchema,\n },\n }),\n uploadAvatar: defineRoute({\n method: 'POST',\n path: '/avatar',\n summary: 'Upload the avatar of the signed-in user (raw image body)',\n schemas: {\n response: { 200: responseDataSchema(userSchema) },\n },\n }),\n },\n});\n\n/** Route definitions of the `/api/user` group, by name. */\nexport type UserRoutes = (typeof userContract)['routes'];\n\nexport type GetSetupStatusResult = ResponseData<{ isSetupRequired: boolean }>;\nexport type GetUsersParams = RouteQuerystring<UserRoutes['getUsers']>;\nexport type GetUsersResult = PaginatedResponse<UserAPI>;\nexport type UpdateUserBody = RouteBodyInput<UserRoutes['updateUser']>;\nexport type UpdateUserResult = ResponseData<UserAPI>;\nexport type CreateUserBody = RouteBodyInput<UserRoutes['createUser']>;\nexport type CreateUserResult = ResponseData<UserAPI>;\nexport type GetUserByIdParams = RouteParams<UserRoutes['getUserById']>;\nexport type GetUserByIdResult = ResponseData<UserAPI>;\nexport type GetUserByEmailParams = RouteParams<UserRoutes['getUserByEmail']>;\nexport type GetUserByEmailResult = ResponseData<UserAPI>;\nexport type DeleteUserParams = RouteParams<UserRoutes['deleteUser']>;\nexport type DeleteUserResult = ResponseData<UserAPI>;\nexport type UploadUserAvatarResult = ResponseData<UserAPI>;\n"],"mappings":"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"}
@@ -0,0 +1,261 @@
1
+ import { dateTimeSchema, isJSONObject, paginationQueryShape, repeatableQueryValueSchema, typedStringSchema, typedValueSchema } from "./common.mjs";
2
+ import { defineRoute, defineRouteGroup } from "./defineRoute.mjs";
3
+ import { paginatedResponseSchema, responseDataSchema } from "./responseData.mjs";
4
+ import { tagSchema } from "./tag.mjs";
5
+ import { z } from "zod/mini";
6
+
7
+ //#region src/ai.ts
8
+ const aiOptionsSchema = typedValueSchema(isJSONObject);
9
+ /** Chat message exchanged with the assistants. */
10
+ const chatCompletionRequestMessageSchema = z.object({
11
+ role: z.enum([
12
+ "system",
13
+ "user",
14
+ "assistant"
15
+ ]),
16
+ content: z.string(),
17
+ /** ISO date-time, parsed to a `Date`. */
18
+ timestamp: z.optional(z.pipe(z.string(), z.transform((value) => new Date(value))))
19
+ });
20
+ const localeSchema = typedStringSchema();
21
+ const tokenUsedShape = { tokenUsed: z.number() };
22
+ /** Text result of an AI step (translation, audit, query). */
23
+ const fileContentResultSchema = z.object({
24
+ fileContent: z.string(),
25
+ ...tokenUsedShape
26
+ });
27
+ /** Tag fields rewritten by the tag audit (parsed from the model's JSON). */
28
+ const tagAuditResultSchema = z.object({
29
+ fileContent: z.looseObject({
30
+ key: z.optional(z.string()),
31
+ name: z.optional(z.string()),
32
+ description: z.optional(z.string()),
33
+ instructions: z.optional(z.string())
34
+ }),
35
+ ...tokenUsedShape
36
+ });
37
+ const metadataResultSchema = z.object({
38
+ fileContent: z.object({
39
+ title: z.string(),
40
+ description: z.string(),
41
+ tags: z.array(z.string())
42
+ }),
43
+ ...tokenUsedShape
44
+ });
45
+ /** JSON document translated by the AI. */
46
+ const jsonContentSchema = typedValueSchema();
47
+ const tokenUsageSchema = z.object({
48
+ inputTokens: z.number(),
49
+ outputTokens: z.number(),
50
+ totalTokens: z.number()
51
+ });
52
+ /** Message stored in a discussion. */
53
+ const discussionMessageSchema = z.object({
54
+ role: z.enum([
55
+ "user",
56
+ "assistant",
57
+ "system"
58
+ ]),
59
+ content: z.string(),
60
+ relatedFiles: z.optional(z.array(z.string())),
61
+ timestamp: dateTimeSchema
62
+ });
63
+ /** Saved AI discussion (doc assistant or dashboard chat). */
64
+ const discussionSchema = z.looseObject({
65
+ id: z.string(),
66
+ /** Generated by the client before the discussion is saved. */
67
+ discussionId: z.string(),
68
+ messages: z.optional(z.array(discussionMessageSchema)),
69
+ numberOfMessages: z.number(),
70
+ userId: z.optional(z.string()),
71
+ projectId: z.optional(z.string()),
72
+ organizationId: z.optional(z.string()),
73
+ title: z.optional(z.string()),
74
+ type: z.optional(z.enum(["doc", "dashboard"])),
75
+ isArchived: z.boolean(),
76
+ aiModel: z.optional(z.string()),
77
+ tokenUsage: z.optional(tokenUsageSchema),
78
+ createdAt: dateTimeSchema,
79
+ updatedAt: dateTimeSchema
80
+ });
81
+ /** Token usage of the project's dashboard discussions, per model. */
82
+ const aiStatsSchema = z.object({
83
+ projectId: z.string(),
84
+ generatedAt: z.number(),
85
+ totalDiscussions: z.number(),
86
+ totalInputTokens: z.number(),
87
+ totalOutputTokens: z.number(),
88
+ totalTokens: z.number(),
89
+ modelUsage: z.array(z.object({
90
+ aiModel: z.string(),
91
+ discussionCount: z.number(),
92
+ totalInputTokens: z.number(),
93
+ totalOutputTokens: z.number(),
94
+ totalTokens: z.number()
95
+ }))
96
+ });
97
+ const aiOptionsShape = { aiOptions: z.optional(aiOptionsSchema) };
98
+ const tagsKeysShape = { tagsKeys: z.optional(z.array(z.string())) };
99
+ const conversationSchema = z.object({
100
+ messages: z.array(chatCompletionRequestMessageSchema),
101
+ discussionId: z.string()
102
+ });
103
+ /** REST contract of the `/api/ai` routes. */
104
+ const aiContract = defineRouteGroup({
105
+ prefix: "/api/ai",
106
+ tag: "AI",
107
+ routes: {
108
+ customQuery: defineRoute({
109
+ method: "POST",
110
+ path: "/",
111
+ summary: "Run a custom prompt",
112
+ schemas: {
113
+ body: z.looseObject({
114
+ ...aiOptionsShape,
115
+ ...tagsKeysShape,
116
+ /** AI SDK model messages. */
117
+ messages: typedValueSchema(Array.isArray),
118
+ system: z.optional(z.unknown()),
119
+ applicationContext: z.optional(z.string())
120
+ }),
121
+ response: { 200: responseDataSchema(fileContentResultSchema) }
122
+ }
123
+ }),
124
+ translateJSON: defineRoute({
125
+ method: "POST",
126
+ path: "/translate/json",
127
+ summary: "Translate a JSON document into a locale",
128
+ schemas: {
129
+ body: z.object({
130
+ ...aiOptionsShape,
131
+ ...tagsKeysShape,
132
+ entryFileContent: jsonContentSchema,
133
+ presetOutputContent: jsonContentSchema,
134
+ dictionaryDescription: z.optional(z.string()),
135
+ entryLocale: localeSchema,
136
+ outputLocale: localeSchema,
137
+ mode: z.enum(["complete", "review"]),
138
+ applicationContext: z.optional(z.string())
139
+ }),
140
+ response: { 200: responseDataSchema(z.object({
141
+ fileContent: jsonContentSchema,
142
+ ...tokenUsedShape
143
+ })) }
144
+ }
145
+ }),
146
+ auditContentDeclaration: defineRoute({
147
+ method: "POST",
148
+ path: "/audit/dictionary",
149
+ summary: "Audit and complete a content declaration file",
150
+ schemas: {
151
+ body: z.object({
152
+ ...aiOptionsShape,
153
+ ...tagsKeysShape,
154
+ locales: z.array(localeSchema),
155
+ defaultLocale: localeSchema,
156
+ fileContent: z.string(),
157
+ filePath: z.optional(z.string())
158
+ }),
159
+ response: { 200: responseDataSchema(metadataResultSchema) }
160
+ }
161
+ }),
162
+ auditContentDeclarationField: defineRoute({
163
+ method: "POST",
164
+ path: "/audit/dictionary/field",
165
+ summary: "Audit a single field of a content declaration",
166
+ schemas: {
167
+ body: z.object({
168
+ ...aiOptionsShape,
169
+ ...tagsKeysShape,
170
+ locales: z.array(localeSchema),
171
+ fileContent: z.string(),
172
+ filePath: z.optional(z.string()),
173
+ keyPath: z.array(typedValueSchema())
174
+ }),
175
+ response: { 200: responseDataSchema(fileContentResultSchema) }
176
+ }
177
+ }),
178
+ auditContentDeclarationMetadata: defineRoute({
179
+ method: "POST",
180
+ path: "/audit/dictionary/metadata",
181
+ summary: "Suggest title, description and tags of a dictionary",
182
+ schemas: {
183
+ body: z.object({
184
+ ...aiOptionsShape,
185
+ fileContent: z.string()
186
+ }),
187
+ response: { 200: responseDataSchema(metadataResultSchema) }
188
+ }
189
+ }),
190
+ auditTag: defineRoute({
191
+ method: "POST",
192
+ path: "/audit/tag",
193
+ summary: "Improve the instructions of a tag",
194
+ schemas: {
195
+ body: z.object({
196
+ ...aiOptionsShape,
197
+ tag: tagSchema
198
+ }),
199
+ response: { 200: responseDataSchema(tagAuditResultSchema) }
200
+ }
201
+ }),
202
+ ask: defineRoute({
203
+ method: "POST",
204
+ path: "/ask",
205
+ summary: "Ask the documentation assistant (server-sent events stream)",
206
+ schemas: { body: conversationSchema }
207
+ }),
208
+ chat: defineRoute({
209
+ method: "POST",
210
+ path: "/chat",
211
+ summary: "Chat with the dashboard assistant (server-sent events stream)",
212
+ schemas: { body: conversationSchema }
213
+ }),
214
+ autocomplete: defineRoute({
215
+ method: "POST",
216
+ path: "/autocomplete",
217
+ summary: "Autocomplete a text being written",
218
+ schemas: {
219
+ body: z.object({
220
+ ...aiOptionsShape,
221
+ text: z.string(),
222
+ contextBefore: z.optional(z.string()),
223
+ currentLine: z.optional(z.string()),
224
+ contextAfter: z.optional(z.string())
225
+ }),
226
+ response: { 200: responseDataSchema(z.object({ autocompletion: z.string() })) }
227
+ }
228
+ }),
229
+ getDiscussions: defineRoute({
230
+ method: "GET",
231
+ path: "/discussions",
232
+ summary: "List AI discussions (own ones, all for admins)",
233
+ schemas: {
234
+ querystring: z.looseObject({
235
+ ...paginationQueryShape,
236
+ includeMessages: z.optional(z.enum(["true", "false"])),
237
+ ids: z.optional(repeatableQueryValueSchema),
238
+ userId: z.optional(z.string()),
239
+ userIds: z.optional(repeatableQueryValueSchema),
240
+ discussionId: z.optional(z.string()),
241
+ search: z.optional(z.string()),
242
+ isArchived: z.optional(z.enum(["true", "false"])),
243
+ sortBy: z.optional(z.string()),
244
+ sortOrder: z.optional(z.string()),
245
+ fetchAll: z.optional(z.enum(["true", "false"]))
246
+ }),
247
+ response: { 200: paginatedResponseSchema(discussionSchema) }
248
+ }
249
+ }),
250
+ getAIStats: defineRoute({
251
+ method: "GET",
252
+ path: "/stats",
253
+ summary: "AI token usage of the selected project",
254
+ schemas: { response: { 200: responseDataSchema(aiStatsSchema) } }
255
+ })
256
+ }
257
+ });
258
+
259
+ //#endregion
260
+ export { aiContract, aiOptionsSchema, aiStatsSchema, chatCompletionRequestMessageSchema, discussionMessageSchema, discussionSchema };
261
+ //# sourceMappingURL=ai.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.mjs","names":[],"sources":["../../src/ai.ts"],"sourcesContent":["import type { Locale } from '@intlayer/types/allLocales';\nimport type { AiProviders } from '@intlayer/types/config';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport { z } from 'zod/mini';\nimport {\n dateTimeSchema,\n isJSONObject,\n paginationQueryShape,\n repeatableQueryValueSchema,\n typedStringSchema,\n typedValueSchema,\n} from './common';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBodyInput,\n type RouteQuerystring,\n} from './defineRoute';\nimport {\n type PaginatedResponse,\n paginatedResponseSchema,\n type ResponseData,\n responseDataSchema,\n} from './responseData';\nimport { tagSchema } from './tag';\n\n/**\n * AI settings sent by a client. Provider-specific options (from the AI SDKs)\n * pass through untouched, so the value is only checked to be an object;\n * `@intlayer/ai`'s `AIOptions` is asserted assignable in the backend.\n */\nexport type AIOptions = {\n provider?: `${AiProviders}`;\n model?: string;\n temperature?: number;\n baseURL?: string;\n /** Own provider key; omitted to use the project or Intlayer key. */\n apiKey?: string;\n applicationContext?: string;\n dataSerialization?: 'json' | 'toon';\n};\n\nexport const aiOptionsSchema = typedValueSchema<AIOptions>(isJSONObject);\n\n/** Chat message exchanged with the assistants. */\nexport const chatCompletionRequestMessageSchema = z.object({\n role: z.enum(['system', 'user', 'assistant']),\n content: z.string(),\n /** ISO date-time, parsed to a `Date`. */\n timestamp: z.optional(\n z.pipe(\n z.string(),\n z.transform((value) => new Date(value))\n )\n ),\n});\n\nconst localeSchema = typedStringSchema<Locale>();\nconst tokenUsedShape = { tokenUsed: z.number() };\n\n/** Text result of an AI step (translation, audit, query). */\nconst fileContentResultSchema = z.object({\n fileContent: z.string(),\n ...tokenUsedShape,\n});\n\n/** Tag fields rewritten by the tag audit (parsed from the model's JSON). */\nconst tagAuditResultSchema = z.object({\n fileContent: z.looseObject({\n key: z.optional(z.string()),\n name: z.optional(z.string()),\n description: z.optional(z.string()),\n instructions: z.optional(z.string()),\n }),\n ...tokenUsedShape,\n});\n\nconst metadataResultSchema = z.object({\n fileContent: z.object({\n title: z.string(),\n description: z.string(),\n tags: z.array(z.string()),\n }),\n ...tokenUsedShape,\n});\n\n/** JSON document translated by the AI. */\nconst jsonContentSchema = typedValueSchema<Record<string, unknown>>();\n\nconst tokenUsageSchema = z.object({\n inputTokens: z.number(),\n outputTokens: z.number(),\n totalTokens: z.number(),\n});\n\n/** Message stored in a discussion. */\nexport const discussionMessageSchema = z.object({\n role: z.enum(['user', 'assistant', 'system']),\n content: z.string(),\n relatedFiles: z.optional(z.array(z.string())),\n timestamp: dateTimeSchema,\n});\n\n/** Saved AI discussion (doc assistant or dashboard chat). */\nexport const discussionSchema = z.looseObject({\n id: z.string(),\n /** Generated by the client before the discussion is saved. */\n discussionId: z.string(),\n messages: z.optional(z.array(discussionMessageSchema)),\n numberOfMessages: z.number(),\n userId: z.optional(z.string()),\n projectId: z.optional(z.string()),\n organizationId: z.optional(z.string()),\n title: z.optional(z.string()),\n type: z.optional(z.enum(['doc', 'dashboard'])),\n isArchived: z.boolean(),\n aiModel: z.optional(z.string()),\n tokenUsage: z.optional(tokenUsageSchema),\n createdAt: dateTimeSchema,\n updatedAt: dateTimeSchema,\n});\n\n/** Token usage of the project's dashboard discussions, per model. */\nexport const aiStatsSchema = z.object({\n projectId: z.string(),\n generatedAt: z.number(),\n totalDiscussions: z.number(),\n totalInputTokens: z.number(),\n totalOutputTokens: z.number(),\n totalTokens: z.number(),\n modelUsage: z.array(\n z.object({\n aiModel: z.string(),\n discussionCount: z.number(),\n totalInputTokens: z.number(),\n totalOutputTokens: z.number(),\n totalTokens: z.number(),\n })\n ),\n});\n\nconst aiOptionsShape = { aiOptions: z.optional(aiOptionsSchema) };\nconst tagsKeysShape = { tagsKeys: z.optional(z.array(z.string())) };\nconst conversationSchema = z.object({\n messages: z.array(chatCompletionRequestMessageSchema),\n discussionId: z.string(),\n});\n\n/** REST contract of the `/api/ai` routes. */\nexport const aiContract = defineRouteGroup({\n prefix: '/api/ai',\n tag: 'AI',\n routes: {\n customQuery: defineRoute({\n method: 'POST',\n path: '/',\n summary: 'Run a custom prompt',\n schemas: {\n body: z.looseObject({\n ...aiOptionsShape,\n ...tagsKeysShape,\n /** AI SDK model messages. */\n messages: typedValueSchema<unknown[]>(Array.isArray),\n system: z.optional(z.unknown()),\n applicationContext: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(fileContentResultSchema) },\n },\n }),\n translateJSON: defineRoute({\n method: 'POST',\n path: '/translate/json',\n summary: 'Translate a JSON document into a locale',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n ...tagsKeysShape,\n entryFileContent: jsonContentSchema,\n presetOutputContent: jsonContentSchema,\n dictionaryDescription: z.optional(z.string()),\n entryLocale: localeSchema,\n outputLocale: localeSchema,\n mode: z.enum(['complete', 'review']),\n applicationContext: z.optional(z.string()),\n }),\n response: {\n 200: responseDataSchema(\n z.object({ fileContent: jsonContentSchema, ...tokenUsedShape })\n ),\n },\n },\n }),\n auditContentDeclaration: defineRoute({\n method: 'POST',\n path: '/audit/dictionary',\n summary: 'Audit and complete a content declaration file',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n ...tagsKeysShape,\n locales: z.array(localeSchema),\n defaultLocale: localeSchema,\n fileContent: z.string(),\n filePath: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(metadataResultSchema) },\n },\n }),\n auditContentDeclarationField: defineRoute({\n method: 'POST',\n path: '/audit/dictionary/field',\n summary: 'Audit a single field of a content declaration',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n ...tagsKeysShape,\n locales: z.array(localeSchema),\n fileContent: z.string(),\n filePath: z.optional(z.string()),\n keyPath: z.array(typedValueSchema<KeyPath>()),\n }),\n response: { 200: responseDataSchema(fileContentResultSchema) },\n },\n }),\n auditContentDeclarationMetadata: defineRoute({\n method: 'POST',\n path: '/audit/dictionary/metadata',\n summary: 'Suggest title, description and tags of a dictionary',\n schemas: {\n body: z.object({ ...aiOptionsShape, fileContent: z.string() }),\n response: { 200: responseDataSchema(metadataResultSchema) },\n },\n }),\n auditTag: defineRoute({\n method: 'POST',\n path: '/audit/tag',\n summary: 'Improve the instructions of a tag',\n schemas: {\n body: z.object({ ...aiOptionsShape, tag: tagSchema }),\n response: { 200: responseDataSchema(tagAuditResultSchema) },\n },\n }),\n ask: defineRoute({\n method: 'POST',\n path: '/ask',\n summary: 'Ask the documentation assistant (server-sent events stream)',\n schemas: { body: conversationSchema },\n }),\n chat: defineRoute({\n method: 'POST',\n path: '/chat',\n summary: 'Chat with the dashboard assistant (server-sent events stream)',\n schemas: { body: conversationSchema },\n }),\n autocomplete: defineRoute({\n method: 'POST',\n path: '/autocomplete',\n summary: 'Autocomplete a text being written',\n schemas: {\n body: z.object({\n ...aiOptionsShape,\n text: z.string(),\n contextBefore: z.optional(z.string()),\n currentLine: z.optional(z.string()),\n contextAfter: z.optional(z.string()),\n }),\n response: {\n 200: responseDataSchema(z.object({ autocompletion: z.string() })),\n },\n },\n }),\n getDiscussions: defineRoute({\n method: 'GET',\n path: '/discussions',\n summary: 'List AI discussions (own ones, all for admins)',\n schemas: {\n querystring: z.looseObject({\n ...paginationQueryShape,\n includeMessages: z.optional(z.enum(['true', 'false'])),\n ids: z.optional(repeatableQueryValueSchema),\n userId: z.optional(z.string()),\n userIds: z.optional(repeatableQueryValueSchema),\n discussionId: z.optional(z.string()),\n search: z.optional(z.string()),\n isArchived: z.optional(z.enum(['true', 'false'])),\n sortBy: z.optional(z.string()),\n sortOrder: z.optional(z.string()),\n fetchAll: z.optional(z.enum(['true', 'false'])),\n }),\n response: { 200: paginatedResponseSchema(discussionSchema) },\n },\n }),\n getAIStats: defineRoute({\n method: 'GET',\n path: '/stats',\n summary: 'AI token usage of the selected project',\n schemas: {\n response: { 200: responseDataSchema(aiStatsSchema) },\n },\n }),\n },\n});\n\n/** Route definitions of the `/api/ai` group, by name. */\nexport type AIRoutes = (typeof aiContract)['routes'];\n\n/**\n * Chat message as built by clients: `timestamp` may be a `Date` (serialized\n * to an ISO string on the wire) or already a string.\n */\nexport type ChatCompletionRequestMessage = Omit<\n z.output<typeof chatCompletionRequestMessageSchema>,\n 'timestamp'\n> & { timestamp?: Date | string };\nexport type DiscussionAPI = z.output<typeof discussionSchema>;\nexport type AIStats = z.output<typeof aiStatsSchema>;\n\nexport type CustomQueryBody = RouteBodyInput<AIRoutes['customQuery']>;\nexport type CustomQueryResult = ResponseData<\n z.output<typeof fileContentResultSchema>\n>;\nexport type TranslateJSONBody = RouteBodyInput<AIRoutes['translateJSON']>;\nexport type TranslateJSONResult = ResponseData<{\n fileContent: Record<string, unknown>;\n tokenUsed: number;\n}>;\nexport type AuditContentDeclarationBody = RouteBodyInput<\n AIRoutes['auditContentDeclaration']\n>;\nexport type AuditContentDeclarationResult = ResponseData<\n z.output<typeof metadataResultSchema>\n>;\nexport type AuditContentDeclarationFieldBody = RouteBodyInput<\n AIRoutes['auditContentDeclarationField']\n>;\nexport type AuditContentDeclarationFieldResult = ResponseData<\n z.output<typeof fileContentResultSchema>\n>;\nexport type AuditContentDeclarationMetadataBody = RouteBodyInput<\n AIRoutes['auditContentDeclarationMetadata']\n>;\nexport type AuditContentDeclarationMetadataResult = ResponseData<\n z.output<typeof metadataResultSchema>\n>;\nexport type AuditTagBody = RouteBodyInput<AIRoutes['auditTag']>;\nexport type AuditTagResultData = z.output<typeof tagAuditResultSchema>;\nexport type AuditTagResult = ResponseData<AuditTagResultData>;\nexport type AskDocQuestionBody = RouteBodyInput<AIRoutes['ask']>;\n/** Final payload of the documentation assistant stream. */\nexport type AskDocQuestionResult = ResponseData<{\n response: string;\n relatedFiles: string[];\n}>;\nexport type ChatBody = RouteBodyInput<AIRoutes['chat']>;\n/** Final payload of the dashboard assistant stream. */\nexport type ChatResult = ResponseData<{\n response: string;\n tokenUsage?: z.output<typeof tokenUsageSchema>;\n aiModel?: string;\n}>;\nexport type AutocompleteBody = RouteBodyInput<AIRoutes['autocomplete']>;\nexport type AutocompleteResponse = ResponseData<{ autocompletion: string }>;\nexport type GetDiscussionsParams = RouteQuerystring<AIRoutes['getDiscussions']>;\nexport type GetDiscussionsResult = PaginatedResponse<DiscussionAPI>;\nexport type GetAIStatsResult = ResponseData<AIStats>;\n"],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ import { defineRoute, defineRouteGroup } from "./defineRoute.mjs";
2
+ import { responseDataSchema } from "./responseData.mjs";
3
+ import { z } from "zod/mini";
4
+
5
+ //#region src/analytics.ts
6
+ /** Kind of analytics event sent by the SDK. */
7
+ const analyticsEventTypeSchema = z.enum([
8
+ "page_view",
9
+ "content_exposure",
10
+ "conversion"
11
+ ]);
12
+ /** One event as sent by the SDK (batched). */
13
+ const incomingAnalyticsEventSchema = z.looseObject({
14
+ type: analyticsEventTypeSchema,
15
+ /** Client timestamp (epoch ms). */
16
+ t: z.number(),
17
+ locale: z.string(),
18
+ url: z.string(),
19
+ ref: z.optional(z.string()),
20
+ dictionaryKey: z.optional(z.string()),
21
+ keyPath: z.optional(z.string()),
22
+ nodeType: z.optional(z.string()),
23
+ variant: z.optional(z.string()),
24
+ count: z.optional(z.number()),
25
+ experimentKey: z.optional(z.string()),
26
+ goal: z.optional(z.string()),
27
+ value: z.optional(z.number())
28
+ });
29
+ /** Time windows of the audience report. */
30
+ const audienceRangeSchema = z.enum([
31
+ "1h",
32
+ "24h",
33
+ "7d",
34
+ "30d",
35
+ "90d",
36
+ "6mo",
37
+ "1y",
38
+ "3y"
39
+ ]);
40
+ const audienceGranularitySchema = z.enum([
41
+ "minute",
42
+ "hour",
43
+ "day",
44
+ "week",
45
+ "month"
46
+ ]);
47
+ const audienceSeriesPointSchema = z.object({
48
+ /** ISO bucket start. */
49
+ bucket: z.string(),
50
+ users: z.number(),
51
+ views: z.number()
52
+ });
53
+ const audienceBreakdownRowSchema = z.object({
54
+ key: z.string(),
55
+ users: z.number(),
56
+ views: z.number()
57
+ });
58
+ const audienceStatsSchema = z.object({
59
+ usersToday: z.number(),
60
+ usersLast7Days: z.number(),
61
+ usersInRange: z.number(),
62
+ viewsInRange: z.number(),
63
+ range: audienceRangeSchema,
64
+ rangeHours: z.number(),
65
+ granularity: audienceGranularitySchema,
66
+ series: z.array(audienceSeriesPointSchema),
67
+ byLocale: z.array(audienceBreakdownRowSchema),
68
+ byCountry: z.array(audienceBreakdownRowSchema),
69
+ byPage: z.array(audienceBreakdownRowSchema)
70
+ });
71
+ const analyticsOverviewRowSchema = z.object({
72
+ url: z.string(),
73
+ locale: z.string(),
74
+ views: z.number()
75
+ });
76
+ const contentStatRowSchema = z.object({
77
+ dictionaryKey: z.string(),
78
+ keyPath: z.string(),
79
+ locale: z.string(),
80
+ exposures: z.number()
81
+ });
82
+ const experimentResultSchema = z.object({
83
+ experimentKey: z.string(),
84
+ variants: z.array(z.object({
85
+ variant: z.string(),
86
+ exposures: z.number(),
87
+ conversions: z.number(),
88
+ conversionRate: z.number()
89
+ })),
90
+ pValue: z.nullable(z.number()),
91
+ winner: z.nullable(z.string())
92
+ });
93
+ const pageMetadataSchema = z.object({
94
+ title: z.optional(z.string()),
95
+ description: z.optional(z.string())
96
+ });
97
+ /** REST contract of the `/api/analytics` routes. */
98
+ const analyticsContract = defineRouteGroup({
99
+ prefix: "/api/analytics",
100
+ tag: "Analytics",
101
+ routes: {
102
+ ingestAnalyticsEvents: defineRoute({
103
+ method: "POST",
104
+ path: "/events",
105
+ summary: "Ingest SDK events (public browser token, rate limited)",
106
+ schemas: {
107
+ /** Sent as `text/plain` JSON by `navigator.sendBeacon`. */
108
+ body: z.looseObject({
109
+ /** Token from `POST /api/public/token` (`analytics:ingest`). */
110
+ token: z.optional(z.string()),
111
+ /** @deprecated Superseded by `token`; still accepted. */
112
+ clientId: z.optional(z.string()),
113
+ sessionId: z.string(),
114
+ sdkVersion: z.string(),
115
+ events: z.array(incomingAnalyticsEventSchema)
116
+ }),
117
+ response: { 200: responseDataSchema(z.object({ accepted: z.number() })) }
118
+ }
119
+ }),
120
+ getAnalyticsOverview: defineRoute({
121
+ method: "GET",
122
+ path: "/overview",
123
+ summary: "Page views per page and locale",
124
+ schemas: { response: { 200: responseDataSchema(z.array(analyticsOverviewRowSchema)) } }
125
+ }),
126
+ getAnalyticsAudience: defineRoute({
127
+ method: "GET",
128
+ path: "/audience",
129
+ summary: "Audience report over a time window",
130
+ schemas: {
131
+ querystring: z.object({
132
+ range: z.optional(z.string()),
133
+ /** Legacy: converted to the closest range. */
134
+ days: z.optional(z.string())
135
+ }),
136
+ response: { 200: responseDataSchema(audienceStatsSchema) }
137
+ }
138
+ }),
139
+ getContentStats: defineRoute({
140
+ method: "GET",
141
+ path: "/content-stats",
142
+ summary: "Content exposures per dictionary key path and locale",
143
+ schemas: { response: { 200: responseDataSchema(z.array(contentStatRowSchema)) } }
144
+ }),
145
+ getExperimentResults: defineRoute({
146
+ method: "GET",
147
+ path: "/experiments/:experimentKey",
148
+ summary: "A/B test results of an experiment",
149
+ schemas: {
150
+ params: z.object({ experimentKey: z.string().check(z.minLength(1)) }),
151
+ response: { 200: responseDataSchema(experimentResultSchema) }
152
+ }
153
+ }),
154
+ getPageMetadata: defineRoute({
155
+ method: "GET",
156
+ path: "/page-metadata",
157
+ summary: "Title and description of a page of the project",
158
+ schemas: {
159
+ querystring: z.object({ url: z.optional(z.string()) }),
160
+ response: { 200: responseDataSchema(pageMetadataSchema) }
161
+ }
162
+ })
163
+ }
164
+ });
165
+
166
+ //#endregion
167
+ export { analyticsContract, analyticsEventTypeSchema, audienceGranularitySchema, audienceRangeSchema, audienceSeriesPointSchema, audienceStatsSchema, incomingAnalyticsEventSchema };
168
+ //# sourceMappingURL=analytics.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.mjs","names":[],"sources":["../../src/analytics.ts"],"sourcesContent":["import { z } from 'zod/mini';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBodyInput,\n} from './defineRoute';\nimport { type ResponseData, responseDataSchema } from './responseData';\n\n/** Kind of analytics event sent by the SDK. */\nexport const analyticsEventTypeSchema = z.enum([\n 'page_view',\n 'content_exposure',\n 'conversion',\n]);\n\n/** One event as sent by the SDK (batched). */\nexport const incomingAnalyticsEventSchema = z.looseObject({\n type: analyticsEventTypeSchema,\n /** Client timestamp (epoch ms). */\n t: z.number(),\n locale: z.string(),\n url: z.string(),\n ref: z.optional(z.string()),\n dictionaryKey: z.optional(z.string()),\n keyPath: z.optional(z.string()),\n nodeType: z.optional(z.string()),\n variant: z.optional(z.string()),\n count: z.optional(z.number()),\n experimentKey: z.optional(z.string()),\n goal: z.optional(z.string()),\n value: z.optional(z.number()),\n});\n\n/** Time windows of the audience report. */\nexport const audienceRangeSchema = z.enum([\n '1h',\n '24h',\n '7d',\n '30d',\n '90d',\n '6mo',\n '1y',\n '3y',\n]);\n\nexport const audienceGranularitySchema = z.enum([\n 'minute',\n 'hour',\n 'day',\n 'week',\n 'month',\n]);\n\nexport const audienceSeriesPointSchema = z.object({\n /** ISO bucket start. */\n bucket: z.string(),\n users: z.number(),\n views: z.number(),\n});\n\nconst audienceBreakdownRowSchema = z.object({\n key: z.string(),\n users: z.number(),\n views: z.number(),\n});\n\nexport const audienceStatsSchema = z.object({\n usersToday: z.number(),\n usersLast7Days: z.number(),\n usersInRange: z.number(),\n viewsInRange: z.number(),\n range: audienceRangeSchema,\n rangeHours: z.number(),\n granularity: audienceGranularitySchema,\n series: z.array(audienceSeriesPointSchema),\n byLocale: z.array(audienceBreakdownRowSchema),\n byCountry: z.array(audienceBreakdownRowSchema),\n byPage: z.array(audienceBreakdownRowSchema),\n});\n\nconst analyticsOverviewRowSchema = z.object({\n url: z.string(),\n locale: z.string(),\n views: z.number(),\n});\n\nconst contentStatRowSchema = z.object({\n dictionaryKey: z.string(),\n keyPath: z.string(),\n locale: z.string(),\n exposures: z.number(),\n});\n\nconst experimentResultSchema = z.object({\n experimentKey: z.string(),\n variants: z.array(\n z.object({\n variant: z.string(),\n exposures: z.number(),\n conversions: z.number(),\n conversionRate: z.number(),\n })\n ),\n pValue: z.nullable(z.number()),\n winner: z.nullable(z.string()),\n});\n\nconst pageMetadataSchema = z.object({\n title: z.optional(z.string()),\n description: z.optional(z.string()),\n});\n\n/** REST contract of the `/api/analytics` routes. */\nexport const analyticsContract = defineRouteGroup({\n prefix: '/api/analytics',\n tag: 'Analytics',\n routes: {\n ingestAnalyticsEvents: defineRoute({\n method: 'POST',\n path: '/events',\n summary: 'Ingest SDK events (public browser token, rate limited)',\n schemas: {\n /** Sent as `text/plain` JSON by `navigator.sendBeacon`. */\n body: z.looseObject({\n /** Token from `POST /api/public/token` (`analytics:ingest`). */\n token: z.optional(z.string()),\n /** @deprecated Superseded by `token`; still accepted. */\n clientId: z.optional(z.string()),\n sessionId: z.string(),\n sdkVersion: z.string(),\n events: z.array(incomingAnalyticsEventSchema),\n }),\n response: {\n 200: responseDataSchema(z.object({ accepted: z.number() })),\n },\n },\n }),\n getAnalyticsOverview: defineRoute({\n method: 'GET',\n path: '/overview',\n summary: 'Page views per page and locale',\n schemas: {\n response: {\n 200: responseDataSchema(z.array(analyticsOverviewRowSchema)),\n },\n },\n }),\n getAnalyticsAudience: defineRoute({\n method: 'GET',\n path: '/audience',\n summary: 'Audience report over a time window',\n schemas: {\n querystring: z.object({\n range: z.optional(z.string()),\n /** Legacy: converted to the closest range. */\n days: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(audienceStatsSchema) },\n },\n }),\n getContentStats: defineRoute({\n method: 'GET',\n path: '/content-stats',\n summary: 'Content exposures per dictionary key path and locale',\n schemas: {\n response: { 200: responseDataSchema(z.array(contentStatRowSchema)) },\n },\n }),\n getExperimentResults: defineRoute({\n method: 'GET',\n path: '/experiments/:experimentKey',\n summary: 'A/B test results of an experiment',\n schemas: {\n params: z.object({ experimentKey: z.string().check(z.minLength(1)) }),\n response: { 200: responseDataSchema(experimentResultSchema) },\n },\n }),\n getPageMetadata: defineRoute({\n method: 'GET',\n path: '/page-metadata',\n summary: 'Title and description of a page of the project',\n schemas: {\n querystring: z.object({ url: z.optional(z.string()) }),\n response: { 200: responseDataSchema(pageMetadataSchema) },\n },\n }),\n },\n});\n\n/** Route definitions of the `/api/analytics` group, by name. */\nexport type AnalyticsRoutes = (typeof analyticsContract)['routes'];\n\nexport type AnalyticsEventType = z.output<typeof analyticsEventTypeSchema>;\nexport type IncomingAnalyticsEvent = z.output<\n typeof incomingAnalyticsEventSchema\n>;\nexport type AudienceRange = z.output<typeof audienceRangeSchema>;\nexport type AudienceGranularity = z.output<typeof audienceGranularitySchema>;\nexport type AudienceSeriesPoint = z.output<typeof audienceSeriesPointSchema>;\nexport type AudienceBreakdownRow = z.output<typeof audienceBreakdownRowSchema>;\nexport type AudienceStats = z.output<typeof audienceStatsSchema>;\nexport type AnalyticsOverviewRow = z.output<typeof analyticsOverviewRowSchema>;\nexport type ContentStatRow = z.output<typeof contentStatRowSchema>;\nexport type ExperimentResult = z.output<typeof experimentResultSchema>;\nexport type PageMetadata = z.output<typeof pageMetadataSchema>;\n\nexport type IngestAnalyticsBody = RouteBodyInput<\n AnalyticsRoutes['ingestAnalyticsEvents']\n>;\nexport type IngestAnalyticsResult = ResponseData<{ accepted: number }>;\nexport type GetAnalyticsOverviewResult = ResponseData<AnalyticsOverviewRow[]>;\nexport type GetContentStatsResult = ResponseData<ContentStatRow[]>;\nexport type GetExperimentResultsResult = ResponseData<ExperimentResult>;\nexport type GetAudienceResult = ResponseData<AudienceStats>;\nexport type GetPageMetadataResult = ResponseData<PageMetadata>;\n"],"mappings":"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"}