@intlayer/backend-contract 0.0.0-stage → 9.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.md +330 -2
  2. package/dist/cjs/ai.cjs +267 -0
  3. package/dist/cjs/ai.cjs.map +1 -0
  4. package/dist/cjs/analytics.cjs +175 -0
  5. package/dist/cjs/analytics.cjs.map +1 -0
  6. package/dist/cjs/asset.cjs +88 -0
  7. package/dist/cjs/asset.cjs.map +1 -0
  8. package/dist/cjs/blogComment.cjs +98 -0
  9. package/dist/cjs/blogComment.cjs.map +1 -0
  10. package/dist/cjs/cliSessionToken.cjs +40 -0
  11. package/dist/cjs/cliSessionToken.cjs.map +1 -0
  12. package/dist/cjs/common.cjs +42 -0
  13. package/dist/cjs/common.cjs.map +1 -0
  14. package/dist/cjs/defineRoute.cjs +26 -0
  15. package/dist/cjs/defineRoute.cjs.map +1 -0
  16. package/dist/cjs/demo.cjs +22 -0
  17. package/dist/cjs/demo.cjs.map +1 -0
  18. package/dist/cjs/dictionary.cjs +168 -0
  19. package/dist/cjs/dictionary.cjs.map +1 -0
  20. package/dist/cjs/environment.cjs +91 -0
  21. package/dist/cjs/environment.cjs.map +1 -0
  22. package/dist/cjs/eventListener.cjs +19 -0
  23. package/dist/cjs/eventListener.cjs.map +1 -0
  24. package/dist/cjs/gitProviders.cjs +361 -0
  25. package/dist/cjs/gitProviders.cjs.map +1 -0
  26. package/dist/cjs/newsletter.cjs +50 -0
  27. package/dist/cjs/newsletter.cjs.map +1 -0
  28. package/dist/cjs/oAuth2.cjs +62 -0
  29. package/dist/cjs/oAuth2.cjs.map +1 -0
  30. package/dist/cjs/organization.cjs +226 -0
  31. package/dist/cjs/organization.cjs.map +1 -0
  32. package/dist/cjs/project.cjs +401 -0
  33. package/dist/cjs/project.cjs.map +1 -0
  34. package/dist/cjs/public.cjs +60 -0
  35. package/dist/cjs/public.cjs.map +1 -0
  36. package/dist/cjs/responseData.cjs +33 -0
  37. package/dist/cjs/responseData.cjs.map +1 -0
  38. package/dist/cjs/reviewer.cjs +401 -0
  39. package/dist/cjs/reviewer.cjs.map +1 -0
  40. package/dist/cjs/scan.cjs +235 -0
  41. package/dist/cjs/scan.cjs.map +1 -0
  42. package/dist/cjs/search.cjs +40 -0
  43. package/dist/cjs/search.cjs.map +1 -0
  44. package/dist/cjs/session.cjs +56 -0
  45. package/dist/cjs/session.cjs.map +1 -0
  46. package/dist/cjs/showcaseProject.cjs +185 -0
  47. package/dist/cjs/showcaseProject.cjs.map +1 -0
  48. package/dist/cjs/stripe.cjs +388 -0
  49. package/dist/cjs/stripe.cjs.map +1 -0
  50. package/dist/cjs/tag.cjs +83 -0
  51. package/dist/cjs/tag.cjs.map +1 -0
  52. package/dist/cjs/translation.cjs +54 -0
  53. package/dist/cjs/translation.cjs.map +1 -0
  54. package/dist/cjs/user.cjs +153 -0
  55. package/dist/cjs/user.cjs.map +1 -0
  56. package/dist/esm/ai.mjs +261 -0
  57. package/dist/esm/ai.mjs.map +1 -0
  58. package/dist/esm/analytics.mjs +168 -0
  59. package/dist/esm/analytics.mjs.map +1 -0
  60. package/dist/esm/asset.mjs +86 -0
  61. package/dist/esm/asset.mjs.map +1 -0
  62. package/dist/esm/blogComment.mjs +94 -0
  63. package/dist/esm/blogComment.mjs.map +1 -0
  64. package/dist/esm/cliSessionToken.mjs +39 -0
  65. package/dist/esm/cliSessionToken.mjs.map +1 -0
  66. package/dist/esm/common.mjs +35 -0
  67. package/dist/esm/common.mjs.map +1 -0
  68. package/dist/esm/defineRoute.mjs +23 -0
  69. package/dist/esm/defineRoute.mjs.map +1 -0
  70. package/dist/esm/demo.mjs +21 -0
  71. package/dist/esm/demo.mjs.map +1 -0
  72. package/dist/esm/dictionary.mjs +163 -0
  73. package/dist/esm/dictionary.mjs.map +1 -0
  74. package/dist/esm/environment.mjs +90 -0
  75. package/dist/esm/environment.mjs.map +1 -0
  76. package/dist/esm/eventListener.mjs +18 -0
  77. package/dist/esm/eventListener.mjs.map +1 -0
  78. package/dist/esm/gitProviders.mjs +352 -0
  79. package/dist/esm/gitProviders.mjs.map +1 -0
  80. package/dist/esm/newsletter.mjs +49 -0
  81. package/dist/esm/newsletter.mjs.map +1 -0
  82. package/dist/esm/oAuth2.mjs +60 -0
  83. package/dist/esm/oAuth2.mjs.map +1 -0
  84. package/dist/esm/organization.mjs +219 -0
  85. package/dist/esm/organization.mjs.map +1 -0
  86. package/dist/esm/project.mjs +387 -0
  87. package/dist/esm/project.mjs.map +1 -0
  88. package/dist/esm/public.mjs +58 -0
  89. package/dist/esm/public.mjs.map +1 -0
  90. package/dist/esm/responseData.mjs +30 -0
  91. package/dist/esm/responseData.mjs.map +1 -0
  92. package/dist/esm/reviewer.mjs +390 -0
  93. package/dist/esm/reviewer.mjs.map +1 -0
  94. package/dist/esm/scan.mjs +225 -0
  95. package/dist/esm/scan.mjs.map +1 -0
  96. package/dist/esm/search.mjs +38 -0
  97. package/dist/esm/search.mjs.map +1 -0
  98. package/dist/esm/session.mjs +53 -0
  99. package/dist/esm/session.mjs.map +1 -0
  100. package/dist/esm/showcaseProject.mjs +182 -0
  101. package/dist/esm/showcaseProject.mjs.map +1 -0
  102. package/dist/esm/stripe.mjs +379 -0
  103. package/dist/esm/stripe.mjs.map +1 -0
  104. package/dist/esm/tag.mjs +81 -0
  105. package/dist/esm/tag.mjs.map +1 -0
  106. package/dist/esm/translation.mjs +53 -0
  107. package/dist/esm/translation.mjs.map +1 -0
  108. package/dist/esm/user.mjs +149 -0
  109. package/dist/esm/user.mjs.map +1 -0
  110. package/dist/types/ai.d.ts +549 -0
  111. package/dist/types/ai.d.ts.map +1 -0
  112. package/dist/types/analytics.d.ts +378 -0
  113. package/dist/types/analytics.d.ts.map +1 -0
  114. package/dist/types/asset.d.ts +207 -0
  115. package/dist/types/asset.d.ts.map +1 -0
  116. package/dist/types/blogComment.d.ts +241 -0
  117. package/dist/types/blogComment.d.ts.map +1 -0
  118. package/dist/types/cliSessionToken.d.ts +263 -0
  119. package/dist/types/cliSessionToken.d.ts.map +1 -0
  120. package/dist/types/common.d.ts +32 -0
  121. package/dist/types/common.d.ts.map +1 -0
  122. package/dist/types/defineRoute.d.ts +57 -0
  123. package/dist/types/defineRoute.d.ts.map +1 -0
  124. package/dist/types/demo.d.ts +21 -0
  125. package/dist/types/demo.d.ts.map +1 -0
  126. package/dist/types/dictionary.d.ts +360 -0
  127. package/dist/types/dictionary.d.ts.map +1 -0
  128. package/dist/types/environment.d.ts +284 -0
  129. package/dist/types/environment.d.ts.map +1 -0
  130. package/dist/types/eventListener.d.ts +17 -0
  131. package/dist/types/eventListener.d.ts.map +1 -0
  132. package/dist/types/gitProviders.d.ts +807 -0
  133. package/dist/types/gitProviders.d.ts.map +1 -0
  134. package/dist/types/newsletter.d.ts +165 -0
  135. package/dist/types/newsletter.d.ts.map +1 -0
  136. package/dist/types/oAuth2.d.ts +481 -0
  137. package/dist/types/oAuth2.d.ts.map +1 -0
  138. package/dist/types/organization.d.ts +1069 -0
  139. package/dist/types/organization.d.ts.map +1 -0
  140. package/dist/types/project.d.ts +1735 -0
  141. package/dist/types/project.d.ts.map +1 -0
  142. package/dist/types/public.d.ts +109 -0
  143. package/dist/types/public.d.ts.map +1 -0
  144. package/dist/types/responseData.d.ts +68 -0
  145. package/dist/types/responseData.d.ts.map +1 -0
  146. package/dist/types/reviewer.d.ts +1239 -0
  147. package/dist/types/reviewer.d.ts.map +1 -0
  148. package/dist/types/scan.d.ts +625 -0
  149. package/dist/types/scan.d.ts.map +1 -0
  150. package/dist/types/search.d.ts +55 -0
  151. package/dist/types/search.d.ts.map +1 -0
  152. package/dist/types/session.d.ts +286 -0
  153. package/dist/types/session.d.ts.map +1 -0
  154. package/dist/types/showcaseProject.d.ts +550 -0
  155. package/dist/types/showcaseProject.d.ts.map +1 -0
  156. package/dist/types/stripe.d.ts +1219 -0
  157. package/dist/types/stripe.d.ts.map +1 -0
  158. package/dist/types/tag.d.ts +193 -0
  159. package/dist/types/tag.d.ts.map +1 -0
  160. package/dist/types/translation.d.ts +162 -0
  161. package/dist/types/translation.d.ts.map +1 -0
  162. package/dist/types/user.d.ts +447 -0
  163. package/dist/types/user.d.ts.map +1 -0
  164. package/package.json +300 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment.mjs","names":[],"sources":["../../src/environment.ts"],"sourcesContent":["import { z } from 'zod/mini';\nimport { objectIdSchema } from './common';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBodyInput,\n type RouteParams,\n} from './defineRoute';\nimport {\n type EnvironmentAPI,\n environmentSchema,\n projectConfigurationSchema,\n} from './project';\nimport { type ResponseData, responseDataSchema } from './responseData';\n\nconst environmentIdParamsSchema = z.object({ environmentId: objectIdSchema });\n\n/** Every environment of the project, production first when virtual. */\nconst environmentsResponseSchema = responseDataSchema(\n z.array(environmentSchema)\n);\n\n/** REST contract of the `/api/project/environment` routes. */\nexport const environmentContract = defineRouteGroup({\n prefix: '/api/project/environment',\n tag: 'Environment',\n routes: {\n addEnvironment: defineRoute({\n method: 'POST',\n path: '/',\n summary: 'Create an environment in the selected project',\n schemas: {\n body: z.object({\n name: z.string(),\n configuration: z.optional(projectConfigurationSchema),\n }),\n response: { 200: environmentsResponseSchema },\n },\n }),\n updateEnvironment: defineRoute({\n method: 'PUT',\n path: '/:environmentId',\n summary: 'Rename or reconfigure an environment',\n schemas: {\n params: environmentIdParamsSchema,\n body: z.object({\n name: z.optional(z.string()),\n configuration: z.optional(projectConfigurationSchema),\n }),\n response: { 200: environmentsResponseSchema },\n },\n }),\n deleteEnvironment: defineRoute({\n method: 'DELETE',\n path: '/:environmentId',\n summary: 'Delete an environment',\n schemas: {\n params: environmentIdParamsSchema,\n response: { 200: environmentsResponseSchema },\n },\n }),\n resetToProductionEnvironment: defineRoute({\n method: 'PUT',\n path: '/production/select',\n summary: 'Select the production environment for the session',\n schemas: {\n response: { 200: responseDataSchema(z.nullable(environmentSchema)) },\n },\n }),\n selectEnvironment: defineRoute({\n method: 'PUT',\n path: '/:environmentId/select',\n summary: 'Select an environment for the session',\n schemas: {\n params: environmentIdParamsSchema,\n response: { 200: responseDataSchema(environmentSchema) },\n },\n }),\n migrateEnvironment: defineRoute({\n method: 'POST',\n path: '/migrate',\n summary: 'Copy dictionaries and configuration between environments',\n schemas: {\n body: z.object({\n /** Environment id, or `production` for the default environment. */\n sourceEnvironmentId: z.string(),\n targetEnvironmentId: z.string(),\n strategy: z.enum(['overwrite', 'fill-missing']),\n migrateContent: z.optional(z.boolean()),\n migrateConfiguration: z.optional(z.boolean()),\n }),\n response: {\n 200: responseDataSchema(\n z.object({\n migratedDictionaries: z.number(),\n skippedDictionaries: z.number(),\n configurationMigrated: z.boolean(),\n })\n ),\n },\n },\n }),\n },\n});\n\n/** Route definitions of the `/api/project/environment` group, by name. */\nexport type EnvironmentRoutes = (typeof environmentContract)['routes'];\n\nexport type AddEnvironmentBody = RouteBodyInput<\n EnvironmentRoutes['addEnvironment']\n>;\nexport type AddEnvironmentResult = ResponseData<EnvironmentAPI[]>;\nexport type UpdateEnvironmentParams = RouteParams<\n EnvironmentRoutes['updateEnvironment']\n>;\nexport type UpdateEnvironmentBody = RouteBodyInput<\n EnvironmentRoutes['updateEnvironment']\n>;\nexport type UpdateEnvironmentResult = ResponseData<EnvironmentAPI[]>;\nexport type DeleteEnvironmentParams = RouteParams<\n EnvironmentRoutes['deleteEnvironment']\n>;\nexport type DeleteEnvironmentResult = ResponseData<EnvironmentAPI[]>;\nexport type SelectEnvironmentParams = RouteParams<\n EnvironmentRoutes['selectEnvironment']\n>;\nexport type SelectEnvironmentResult = ResponseData<EnvironmentAPI>;\nexport type ResetToProductionEnvironmentResult =\n ResponseData<EnvironmentAPI | null>;\nexport type MigrateEnvironmentBody = RouteBodyInput<\n EnvironmentRoutes['migrateEnvironment']\n>;\nexport type MigrateEnvironmentResult = ResponseData<{\n migratedDictionaries: number;\n skippedDictionaries: number;\n configurationMigrated: boolean;\n}>;\n"],"mappings":";;;;;;;AAeA,MAAM,4BAA4B,EAAE,OAAO,EAAE,eAAe,eAAe,CAAC;;AAG5E,MAAM,6BAA6B,mBACjC,EAAE,MAAM,iBAAiB,CAC3B;;AAGA,MAAa,sBAAsB,iBAAiB;CAClD,QAAQ;CACR,KAAK;CACL,QAAQ;EACN,gBAAgB,YAAY;GAC1B,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;IACP,MAAM,EAAE,OAAO;KACb,MAAM,EAAE,OAAO;KACf,eAAe,EAAE,SAAS,0BAA0B;IACtD,CAAC;IACD,UAAU,EAAE,KAAK,2BAA2B;GAC9C;EACF,CAAC;EACD,mBAAmB,YAAY;GAC7B,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;IACP,QAAQ;IACR,MAAM,EAAE,OAAO;KACb,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC;KAC3B,eAAe,EAAE,SAAS,0BAA0B;IACtD,CAAC;IACD,UAAU,EAAE,KAAK,2BAA2B;GAC9C;EACF,CAAC;EACD,mBAAmB,YAAY;GAC7B,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;IACP,QAAQ;IACR,UAAU,EAAE,KAAK,2BAA2B;GAC9C;EACF,CAAC;EACD,8BAA8B,YAAY;GACxC,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS,EACP,UAAU,EAAE,KAAK,mBAAmB,EAAE,SAAS,iBAAiB,CAAC,EAAE,EACrE;EACF,CAAC;EACD,mBAAmB,YAAY;GAC7B,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;IACP,QAAQ;IACR,UAAU,EAAE,KAAK,mBAAmB,iBAAiB,EAAE;GACzD;EACF,CAAC;EACD,oBAAoB,YAAY;GAC9B,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;IACP,MAAM,EAAE,OAAO;;KAEb,qBAAqB,EAAE,OAAO;KAC9B,qBAAqB,EAAE,OAAO;KAC9B,UAAU,EAAE,KAAK,CAAC,aAAa,cAAc,CAAC;KAC9C,gBAAgB,EAAE,SAAS,EAAE,QAAQ,CAAC;KACtC,sBAAsB,EAAE,SAAS,EAAE,QAAQ,CAAC;IAC9C,CAAC;IACD,UAAU,EACR,KAAK,mBACH,EAAE,OAAO;KACP,sBAAsB,EAAE,OAAO;KAC/B,qBAAqB,EAAE,OAAO;KAC9B,uBAAuB,EAAE,QAAQ;IACnC,CAAC,CACH,EACF;GACF;EACF,CAAC;CACH;AACF,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { defineRoute, defineRouteGroup } from "./defineRoute.mjs";
2
+
3
+ //#region src/eventListener.ts
4
+ /** Live dictionary change stream (server-sent events). */
5
+ const eventListenerContract = defineRouteGroup({
6
+ prefix: "/api/event-listener",
7
+ tag: "Event listener",
8
+ routes: { checkDictionaryChangeSSE: defineRoute({
9
+ method: "GET",
10
+ path: "/",
11
+ summary: "Stream dictionary changes of the project (server-sent events)",
12
+ schemas: {}
13
+ }) }
14
+ });
15
+
16
+ //#endregion
17
+ export { eventListenerContract };
18
+ //# sourceMappingURL=eventListener.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eventListener.mjs","names":[],"sources":["../../src/eventListener.ts"],"sourcesContent":["import { defineRoute, defineRouteGroup } from './defineRoute';\nimport type { DictionaryAPI } from './dictionary';\n\n/** Live dictionary change stream (server-sent events). */\nexport const eventListenerContract = defineRouteGroup({\n prefix: '/api/event-listener',\n tag: 'Event listener',\n routes: {\n checkDictionaryChangeSSE: defineRoute({\n method: 'GET',\n path: '/',\n summary: 'Stream dictionary changes of the project (server-sent events)',\n schemas: {},\n }),\n },\n});\n\n/** Route definitions of the event listener group, by name. */\nexport type EventListenerRoutes = (typeof eventListenerContract)['routes'];\n\n/** Message pushed on the dictionary change stream. */\nexport type MessageEventData = {\n object: 'DICTIONARY';\n status: 'ADDED' | 'UPDATED' | 'DELETED' | 'CREATED';\n data: DictionaryAPI;\n};\n"],"mappings":";;;;AAIA,MAAa,wBAAwB,iBAAiB;CACpD,QAAQ;CACR,KAAK;CACL,QAAQ,EACN,0BAA0B,YAAY;EACpC,QAAQ;EACR,MAAM;EACN,SAAS;EACT,SAAS,CAAC;CACZ,CAAC,EACH;AACF,CAAC"}
@@ -0,0 +1,352 @@
1
+ import { defineRoute, defineRouteGroup } from "./defineRoute.mjs";
2
+ import { responseDataSchema } from "./responseData.mjs";
3
+ import { z } from "zod/mini";
4
+
5
+ //#region src/gitProviders.ts
6
+ /**
7
+ * Git provider OAuth + repository routes (repository linking in the
8
+ * dashboard). Each provider gets its own group; the shapes below are shared.
9
+ */
10
+ const authUrlResponseSchema = responseDataSchema(z.object({ authUrl: z.string() }));
11
+ const tokenResponseSchema = responseDataSchema(z.object({ token: z.string() }));
12
+ const checkConfigResponseSchema = responseDataSchema(z.object({
13
+ hasConfig: z.boolean(),
14
+ configPaths: z.array(z.string())
15
+ }));
16
+ const configFileResponseSchema = responseDataSchema(z.object({ content: z.string() }));
17
+ /** Optional provider token: defaults to the one linked to the user. */
18
+ const tokenShape = { token: z.optional(z.string()) };
19
+ const branchAndPathShape = {
20
+ branch: z.optional(z.string()),
21
+ path: z.optional(z.string())
22
+ };
23
+ /** GitHub repository (subset of the REST API item the dashboard reads). */
24
+ const gitHubRepositorySchema = z.looseObject({
25
+ id: z.number(),
26
+ name: z.string(),
27
+ full_name: z.string(),
28
+ owner: z.looseObject({
29
+ login: z.string(),
30
+ avatar_url: z.optional(z.string())
31
+ }),
32
+ private: z.boolean(),
33
+ html_url: z.string(),
34
+ default_branch: z.optional(z.string()),
35
+ updated_at: z.optional(z.nullable(z.string()))
36
+ });
37
+ /** GitLab project (subset the dashboard reads). */
38
+ const gitLabProjectSchema = z.looseObject({
39
+ id: z.number(),
40
+ name: z.string(),
41
+ path_with_namespace: z.string(),
42
+ web_url: z.string(),
43
+ default_branch: z.string(),
44
+ visibility: z.string(),
45
+ last_activity_at: z.string(),
46
+ namespace: z.looseObject({
47
+ id: z.number(),
48
+ name: z.string(),
49
+ path: z.string()
50
+ })
51
+ });
52
+ /** Bitbucket repository (subset the dashboard reads). */
53
+ const bitbucketRepositorySchema = z.looseObject({
54
+ uuid: z.string(),
55
+ name: z.string(),
56
+ full_name: z.string(),
57
+ slug: z.string(),
58
+ mainbranch: z.optional(z.looseObject({
59
+ name: z.string(),
60
+ type: z.string()
61
+ })),
62
+ links: z.looseObject({ html: z.looseObject({ href: z.string() }) }),
63
+ workspace: z.looseObject({
64
+ slug: z.string(),
65
+ name: z.string(),
66
+ uuid: z.string()
67
+ }),
68
+ is_private: z.optional(z.boolean()),
69
+ updated_on: z.optional(z.string())
70
+ });
71
+ /**
72
+ * Repository of a Gitea-compatible forge (Codeberg/Forgejo, Gitee), normalized
73
+ * by the backend. `name` is the URL slug used in API paths.
74
+ */
75
+ const forgeRepositorySchema = z.object({
76
+ id: z.number(),
77
+ name: z.string(),
78
+ /** Human-readable name (can differ from the slug on Gitee). */
79
+ displayName: z.string(),
80
+ full_name: z.string(),
81
+ owner: z.object({
82
+ login: z.string(),
83
+ avatar_url: z.optional(z.string())
84
+ }),
85
+ private: z.boolean(),
86
+ html_url: z.string(),
87
+ default_branch: z.optional(z.string()),
88
+ updated_at: z.optional(z.nullable(z.string()))
89
+ });
90
+ const forgeRepositoryShape = {
91
+ ...tokenShape,
92
+ owner: z.string(),
93
+ repository: z.string()
94
+ };
95
+ /**
96
+ * Builds the contract of a Gitea-compatible forge: repositories are listed and
97
+ * read with the account linked through better-auth.
98
+ */
99
+ const defineForgeContract = (prefix, tag) => defineRouteGroup({
100
+ prefix,
101
+ tag,
102
+ routes: {
103
+ listRepos: defineRoute({
104
+ method: "GET",
105
+ path: "/repos",
106
+ summary: `Repositories of the ${tag} account`,
107
+ schemas: {
108
+ querystring: z.object(tokenShape),
109
+ response: { 200: responseDataSchema(z.array(forgeRepositorySchema)) }
110
+ }
111
+ }),
112
+ checkConfig: defineRoute({
113
+ method: "POST",
114
+ path: "/check-config",
115
+ summary: "Find Intlayer configuration files in a repository",
116
+ schemas: {
117
+ body: z.object({
118
+ ...forgeRepositoryShape,
119
+ branch: z.optional(z.string())
120
+ }),
121
+ response: { 200: checkConfigResponseSchema }
122
+ }
123
+ }),
124
+ getConfigFile: defineRoute({
125
+ method: "POST",
126
+ path: "/get-config-file",
127
+ summary: "Read an Intlayer configuration file of a repository",
128
+ schemas: {
129
+ body: z.object({
130
+ ...forgeRepositoryShape,
131
+ ...branchAndPathShape
132
+ }),
133
+ response: { 200: configFileResponseSchema }
134
+ }
135
+ })
136
+ }
137
+ });
138
+ /** REST contract of the `/api/codeberg` routes (Codeberg / Forgejo). */
139
+ const codebergContract = defineForgeContract("/api/codeberg", "Codeberg");
140
+ /** REST contract of the `/api/gitee` routes. */
141
+ const giteeContract = defineForgeContract("/api/gitee", "Gitee");
142
+ /** REST contract of the `/api/github` routes. */
143
+ const githubContract = defineRouteGroup({
144
+ prefix: "/api/github",
145
+ tag: "GitHub",
146
+ routes: {
147
+ getAuthUrl: defineRoute({
148
+ method: "GET",
149
+ path: "/auth-url",
150
+ summary: "GitHub OAuth authorization URL",
151
+ schemas: {
152
+ querystring: z.object({
153
+ redirectUri: z.string(),
154
+ login: z.optional(z.string())
155
+ }),
156
+ response: { 200: authUrlResponseSchema }
157
+ }
158
+ }),
159
+ authCallback: defineRoute({
160
+ method: "POST",
161
+ path: "/auth",
162
+ summary: "Exchange the OAuth code for a GitHub token",
163
+ schemas: {
164
+ body: z.object({ code: z.string() }),
165
+ response: { 200: tokenResponseSchema }
166
+ }
167
+ }),
168
+ listRepos: defineRoute({
169
+ method: "GET",
170
+ path: "/repos",
171
+ summary: "Repositories of the GitHub account",
172
+ schemas: {
173
+ querystring: z.object(tokenShape),
174
+ response: { 200: responseDataSchema(z.array(gitHubRepositorySchema)) }
175
+ }
176
+ }),
177
+ checkConfig: defineRoute({
178
+ method: "POST",
179
+ path: "/check-config",
180
+ summary: "Find Intlayer configuration files in a repository",
181
+ schemas: {
182
+ body: z.object({
183
+ ...tokenShape,
184
+ owner: z.string(),
185
+ repository: z.string(),
186
+ branch: z.optional(z.string())
187
+ }),
188
+ response: { 200: checkConfigResponseSchema }
189
+ }
190
+ }),
191
+ getConfigFile: defineRoute({
192
+ method: "POST",
193
+ path: "/get-config-file",
194
+ summary: "Read an Intlayer configuration file of a repository",
195
+ schemas: {
196
+ body: z.object({
197
+ ...tokenShape,
198
+ ...branchAndPathShape,
199
+ owner: z.string(),
200
+ repository: z.string()
201
+ }),
202
+ response: { 200: configFileResponseSchema }
203
+ }
204
+ }),
205
+ getToken: defineRoute({
206
+ method: "GET",
207
+ path: "/token",
208
+ summary: "GitHub token linked to the signed-in user's account",
209
+ schemas: { response: { 200: tokenResponseSchema } }
210
+ })
211
+ }
212
+ });
213
+ /** REST contract of the `/api/gitlab` routes. */
214
+ const gitlabContract = defineRouteGroup({
215
+ prefix: "/api/gitlab",
216
+ tag: "GitLab",
217
+ routes: {
218
+ getAuthUrl: defineRoute({
219
+ method: "GET",
220
+ path: "/auth-url",
221
+ summary: "GitLab OAuth authorization URL",
222
+ schemas: {
223
+ querystring: z.object({
224
+ redirectUri: z.string(),
225
+ /** Self-managed GitLab instance (ex: https://gitlab.company.com). */
226
+ instanceUrl: z.optional(z.string()),
227
+ login: z.optional(z.string())
228
+ }),
229
+ response: { 200: authUrlResponseSchema }
230
+ }
231
+ }),
232
+ authCallback: defineRoute({
233
+ method: "POST",
234
+ path: "/auth",
235
+ summary: "Exchange the OAuth code for a GitLab token",
236
+ schemas: {
237
+ body: z.object({
238
+ code: z.string(),
239
+ redirectUri: z.string(),
240
+ instanceUrl: z.optional(z.string())
241
+ }),
242
+ response: { 200: tokenResponseSchema }
243
+ }
244
+ }),
245
+ listProjects: defineRoute({
246
+ method: "GET",
247
+ path: "/projects",
248
+ summary: "Projects of the GitLab account",
249
+ schemas: {
250
+ querystring: z.object({
251
+ ...tokenShape,
252
+ instanceUrl: z.optional(z.string())
253
+ }),
254
+ response: { 200: responseDataSchema(z.array(gitLabProjectSchema)) }
255
+ }
256
+ }),
257
+ checkConfig: defineRoute({
258
+ method: "POST",
259
+ path: "/check-config",
260
+ summary: "Find Intlayer configuration files in a project",
261
+ schemas: {
262
+ body: z.object({
263
+ ...tokenShape,
264
+ projectId: z.number(),
265
+ branch: z.optional(z.string()),
266
+ instanceUrl: z.optional(z.string())
267
+ }),
268
+ response: { 200: checkConfigResponseSchema }
269
+ }
270
+ }),
271
+ getConfigFile: defineRoute({
272
+ method: "POST",
273
+ path: "/get-config-file",
274
+ summary: "Read an Intlayer configuration file of a project",
275
+ schemas: {
276
+ body: z.object({
277
+ ...tokenShape,
278
+ ...branchAndPathShape,
279
+ projectId: z.number(),
280
+ instanceUrl: z.optional(z.string())
281
+ }),
282
+ response: { 200: configFileResponseSchema }
283
+ }
284
+ })
285
+ }
286
+ });
287
+ /** REST contract of the `/api/bitbucket` routes. */
288
+ const bitbucketContract = defineRouteGroup({
289
+ prefix: "/api/bitbucket",
290
+ tag: "Bitbucket",
291
+ routes: {
292
+ getAuthUrl: defineRoute({
293
+ method: "GET",
294
+ path: "/auth-url",
295
+ summary: "Bitbucket OAuth authorization URL",
296
+ schemas: {
297
+ querystring: z.object({ redirectUri: z.string() }),
298
+ response: { 200: authUrlResponseSchema }
299
+ }
300
+ }),
301
+ authCallback: defineRoute({
302
+ method: "POST",
303
+ path: "/auth",
304
+ summary: "Exchange the OAuth code for a Bitbucket token",
305
+ schemas: {
306
+ body: z.object({ code: z.string() }),
307
+ response: { 200: tokenResponseSchema }
308
+ }
309
+ }),
310
+ listRepos: defineRoute({
311
+ method: "GET",
312
+ path: "/repos",
313
+ summary: "Repositories of the Bitbucket account",
314
+ schemas: {
315
+ querystring: z.object(tokenShape),
316
+ response: { 200: responseDataSchema(z.array(bitbucketRepositorySchema)) }
317
+ }
318
+ }),
319
+ checkConfig: defineRoute({
320
+ method: "POST",
321
+ path: "/check-config",
322
+ summary: "Find Intlayer configuration files in a repository",
323
+ schemas: {
324
+ body: z.object({
325
+ ...tokenShape,
326
+ workspace: z.string(),
327
+ repoSlug: z.string(),
328
+ branch: z.optional(z.string())
329
+ }),
330
+ response: { 200: checkConfigResponseSchema }
331
+ }
332
+ }),
333
+ getConfigFile: defineRoute({
334
+ method: "POST",
335
+ path: "/get-config-file",
336
+ summary: "Read an Intlayer configuration file of a repository",
337
+ schemas: {
338
+ body: z.object({
339
+ ...tokenShape,
340
+ ...branchAndPathShape,
341
+ workspace: z.string(),
342
+ repoSlug: z.string()
343
+ }),
344
+ response: { 200: configFileResponseSchema }
345
+ }
346
+ })
347
+ }
348
+ });
349
+
350
+ //#endregion
351
+ export { bitbucketContract, bitbucketRepositorySchema, codebergContract, forgeRepositorySchema, gitHubRepositorySchema, gitLabProjectSchema, giteeContract, githubContract, gitlabContract };
352
+ //# sourceMappingURL=gitProviders.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitProviders.mjs","names":[],"sources":["../../src/gitProviders.ts"],"sourcesContent":["import { z } from 'zod/mini';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBodyInput,\n type RouteQuerystring,\n} from './defineRoute';\nimport { type ResponseData, responseDataSchema } from './responseData';\n\n/**\n * Git provider OAuth + repository routes (repository linking in the\n * dashboard). Each provider gets its own group; the shapes below are shared.\n */\n\nconst authUrlResponseSchema = responseDataSchema(\n z.object({ authUrl: z.string() })\n);\nconst tokenResponseSchema = responseDataSchema(z.object({ token: z.string() }));\nconst checkConfigResponseSchema = responseDataSchema(\n z.object({ hasConfig: z.boolean(), configPaths: z.array(z.string()) })\n);\nconst configFileResponseSchema = responseDataSchema(\n z.object({ content: z.string() })\n);\n\n/** Optional provider token: defaults to the one linked to the user. */\nconst tokenShape = { token: z.optional(z.string()) };\nconst branchAndPathShape = {\n branch: z.optional(z.string()),\n path: z.optional(z.string()),\n};\n\n/** GitHub repository (subset of the REST API item the dashboard reads). */\nexport const gitHubRepositorySchema = z.looseObject({\n id: z.number(),\n name: z.string(),\n full_name: z.string(),\n owner: z.looseObject({\n login: z.string(),\n avatar_url: z.optional(z.string()),\n }),\n private: z.boolean(),\n html_url: z.string(),\n default_branch: z.optional(z.string()),\n updated_at: z.optional(z.nullable(z.string())),\n});\n\n/** GitLab project (subset the dashboard reads). */\nexport const gitLabProjectSchema = z.looseObject({\n id: z.number(),\n name: z.string(),\n path_with_namespace: z.string(),\n web_url: z.string(),\n default_branch: z.string(),\n visibility: z.string(),\n last_activity_at: z.string(),\n namespace: z.looseObject({\n id: z.number(),\n name: z.string(),\n path: z.string(),\n }),\n});\n\n/** Bitbucket repository (subset the dashboard reads). */\nexport const bitbucketRepositorySchema = z.looseObject({\n uuid: z.string(),\n name: z.string(),\n full_name: z.string(),\n slug: z.string(),\n mainbranch: z.optional(z.looseObject({ name: z.string(), type: z.string() })),\n links: z.looseObject({ html: z.looseObject({ href: z.string() }) }),\n workspace: z.looseObject({\n slug: z.string(),\n name: z.string(),\n uuid: z.string(),\n }),\n is_private: z.optional(z.boolean()),\n updated_on: z.optional(z.string()),\n});\n\n/**\n * Repository of a Gitea-compatible forge (Codeberg/Forgejo, Gitee), normalized\n * by the backend. `name` is the URL slug used in API paths.\n */\nexport const forgeRepositorySchema = z.object({\n id: z.number(),\n name: z.string(),\n /** Human-readable name (can differ from the slug on Gitee). */\n displayName: z.string(),\n full_name: z.string(),\n owner: z.object({\n login: z.string(),\n avatar_url: z.optional(z.string()),\n }),\n private: z.boolean(),\n html_url: z.string(),\n default_branch: z.optional(z.string()),\n updated_at: z.optional(z.nullable(z.string())),\n});\n\nconst forgeRepositoryShape = {\n ...tokenShape,\n owner: z.string(),\n repository: z.string(),\n};\n\n/**\n * Builds the contract of a Gitea-compatible forge: repositories are listed and\n * read with the account linked through better-auth.\n */\nconst defineForgeContract = <Prefix extends string, Tag extends string>(\n prefix: Prefix,\n tag: Tag\n) =>\n defineRouteGroup({\n prefix,\n tag,\n routes: {\n listRepos: defineRoute({\n method: 'GET',\n path: '/repos',\n summary: `Repositories of the ${tag} account`,\n schemas: {\n querystring: z.object(tokenShape),\n response: {\n 200: responseDataSchema(z.array(forgeRepositorySchema)),\n },\n },\n }),\n checkConfig: defineRoute({\n method: 'POST',\n path: '/check-config',\n summary: 'Find Intlayer configuration files in a repository',\n schemas: {\n body: z.object({\n ...forgeRepositoryShape,\n branch: z.optional(z.string()),\n }),\n response: { 200: checkConfigResponseSchema },\n },\n }),\n getConfigFile: defineRoute({\n method: 'POST',\n path: '/get-config-file',\n summary: 'Read an Intlayer configuration file of a repository',\n schemas: {\n body: z.object({ ...forgeRepositoryShape, ...branchAndPathShape }),\n response: { 200: configFileResponseSchema },\n },\n }),\n },\n });\n\n/** REST contract of the `/api/codeberg` routes (Codeberg / Forgejo). */\nexport const codebergContract = defineForgeContract(\n '/api/codeberg',\n 'Codeberg'\n);\n\n/** REST contract of the `/api/gitee` routes. */\nexport const giteeContract = defineForgeContract('/api/gitee', 'Gitee');\n\n/** REST contract of the `/api/github` routes. */\nexport const githubContract = defineRouteGroup({\n prefix: '/api/github',\n tag: 'GitHub',\n routes: {\n getAuthUrl: defineRoute({\n method: 'GET',\n path: '/auth-url',\n summary: 'GitHub OAuth authorization URL',\n schemas: {\n querystring: z.object({\n redirectUri: z.string(),\n login: z.optional(z.string()),\n }),\n response: { 200: authUrlResponseSchema },\n },\n }),\n authCallback: defineRoute({\n method: 'POST',\n path: '/auth',\n summary: 'Exchange the OAuth code for a GitHub token',\n schemas: {\n body: z.object({ code: z.string() }),\n response: { 200: tokenResponseSchema },\n },\n }),\n listRepos: defineRoute({\n method: 'GET',\n path: '/repos',\n summary: 'Repositories of the GitHub account',\n schemas: {\n querystring: z.object(tokenShape),\n response: {\n 200: responseDataSchema(z.array(gitHubRepositorySchema)),\n },\n },\n }),\n checkConfig: defineRoute({\n method: 'POST',\n path: '/check-config',\n summary: 'Find Intlayer configuration files in a repository',\n schemas: {\n body: z.object({\n ...tokenShape,\n owner: z.string(),\n repository: z.string(),\n branch: z.optional(z.string()),\n }),\n response: { 200: checkConfigResponseSchema },\n },\n }),\n getConfigFile: defineRoute({\n method: 'POST',\n path: '/get-config-file',\n summary: 'Read an Intlayer configuration file of a repository',\n schemas: {\n body: z.object({\n ...tokenShape,\n ...branchAndPathShape,\n owner: z.string(),\n repository: z.string(),\n }),\n response: { 200: configFileResponseSchema },\n },\n }),\n getToken: defineRoute({\n method: 'GET',\n path: '/token',\n summary: \"GitHub token linked to the signed-in user's account\",\n schemas: {\n response: { 200: tokenResponseSchema },\n },\n }),\n },\n});\n\n/** REST contract of the `/api/gitlab` routes. */\nexport const gitlabContract = defineRouteGroup({\n prefix: '/api/gitlab',\n tag: 'GitLab',\n routes: {\n getAuthUrl: defineRoute({\n method: 'GET',\n path: '/auth-url',\n summary: 'GitLab OAuth authorization URL',\n schemas: {\n querystring: z.object({\n redirectUri: z.string(),\n /** Self-managed GitLab instance (ex: https://gitlab.company.com). */\n instanceUrl: z.optional(z.string()),\n login: z.optional(z.string()),\n }),\n response: { 200: authUrlResponseSchema },\n },\n }),\n authCallback: defineRoute({\n method: 'POST',\n path: '/auth',\n summary: 'Exchange the OAuth code for a GitLab token',\n schemas: {\n body: z.object({\n code: z.string(),\n redirectUri: z.string(),\n instanceUrl: z.optional(z.string()),\n }),\n response: { 200: tokenResponseSchema },\n },\n }),\n listProjects: defineRoute({\n method: 'GET',\n path: '/projects',\n summary: 'Projects of the GitLab account',\n schemas: {\n querystring: z.object({\n ...tokenShape,\n instanceUrl: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(z.array(gitLabProjectSchema)) },\n },\n }),\n checkConfig: defineRoute({\n method: 'POST',\n path: '/check-config',\n summary: 'Find Intlayer configuration files in a project',\n schemas: {\n body: z.object({\n ...tokenShape,\n projectId: z.number(),\n branch: z.optional(z.string()),\n instanceUrl: z.optional(z.string()),\n }),\n response: { 200: checkConfigResponseSchema },\n },\n }),\n getConfigFile: defineRoute({\n method: 'POST',\n path: '/get-config-file',\n summary: 'Read an Intlayer configuration file of a project',\n schemas: {\n body: z.object({\n ...tokenShape,\n ...branchAndPathShape,\n projectId: z.number(),\n instanceUrl: z.optional(z.string()),\n }),\n response: { 200: configFileResponseSchema },\n },\n }),\n },\n});\n\n/** REST contract of the `/api/bitbucket` routes. */\nexport const bitbucketContract = defineRouteGroup({\n prefix: '/api/bitbucket',\n tag: 'Bitbucket',\n routes: {\n getAuthUrl: defineRoute({\n method: 'GET',\n path: '/auth-url',\n summary: 'Bitbucket OAuth authorization URL',\n schemas: {\n querystring: z.object({ redirectUri: z.string() }),\n response: { 200: authUrlResponseSchema },\n },\n }),\n authCallback: defineRoute({\n method: 'POST',\n path: '/auth',\n summary: 'Exchange the OAuth code for a Bitbucket token',\n schemas: {\n body: z.object({ code: z.string() }),\n response: { 200: tokenResponseSchema },\n },\n }),\n listRepos: defineRoute({\n method: 'GET',\n path: '/repos',\n summary: 'Repositories of the Bitbucket account',\n schemas: {\n querystring: z.object(tokenShape),\n response: {\n 200: responseDataSchema(z.array(bitbucketRepositorySchema)),\n },\n },\n }),\n checkConfig: defineRoute({\n method: 'POST',\n path: '/check-config',\n summary: 'Find Intlayer configuration files in a repository',\n schemas: {\n body: z.object({\n ...tokenShape,\n workspace: z.string(),\n repoSlug: z.string(),\n branch: z.optional(z.string()),\n }),\n response: { 200: checkConfigResponseSchema },\n },\n }),\n getConfigFile: defineRoute({\n method: 'POST',\n path: '/get-config-file',\n summary: 'Read an Intlayer configuration file of a repository',\n schemas: {\n body: z.object({\n ...tokenShape,\n ...branchAndPathShape,\n workspace: z.string(),\n repoSlug: z.string(),\n }),\n response: { 200: configFileResponseSchema },\n },\n }),\n },\n});\n\nexport type GitHubRoutes = (typeof githubContract)['routes'];\nexport type GitLabRoutes = (typeof gitlabContract)['routes'];\nexport type BitbucketRoutes = (typeof bitbucketContract)['routes'];\n/** Routes shared by every Gitea-compatible forge (Codeberg, Gitee). */\nexport type ForgeRoutes = (typeof codebergContract)['routes'];\nexport type CodebergRoutes = ForgeRoutes;\nexport type GiteeRoutes = (typeof giteeContract)['routes'];\n\ntype AuthUrlResult = ResponseData<{ authUrl: string }>;\ntype TokenResult = ResponseData<{ token: string }>;\ntype CheckConfigResult = ResponseData<{\n hasConfig: boolean;\n configPaths: string[];\n}>;\ntype ConfigFileResult = ResponseData<{ content: string }>;\n\nexport type GitHubRepository = z.output<typeof gitHubRepositorySchema>;\nexport type GitLabProject = z.output<typeof gitLabProjectSchema>;\nexport type BitbucketRepository = z.output<typeof bitbucketRepositorySchema>;\nexport type ForgeRepository = z.output<typeof forgeRepositorySchema>;\n\nexport type GitHubGetAuthUrlQuerystring = RouteQuerystring<\n GitHubRoutes['getAuthUrl']\n>;\nexport type GitHubGetAuthUrlResult = AuthUrlResult;\nexport type GitHubAuthCallbackBody = RouteBodyInput<\n GitHubRoutes['authCallback']\n>;\nexport type GitHubAuthCallbackResult = TokenResult;\nexport type GitHubListReposQuerystring = RouteQuerystring<\n GitHubRoutes['listRepos']\n>;\nexport type GitHubListReposResult = ResponseData<GitHubRepository[]>;\nexport type GitHubCheckConfigBody = RouteBodyInput<GitHubRoutes['checkConfig']>;\nexport type GitHubCheckConfigResult = CheckConfigResult;\nexport type GitHubGetConfigFileBody = RouteBodyInput<\n GitHubRoutes['getConfigFile']\n>;\nexport type GitHubGetConfigFileResult = ConfigFileResult;\nexport type GitHubGetTokenResult = TokenResult;\n\nexport type GitLabGetAuthUrlQuerystring = RouteQuerystring<\n GitLabRoutes['getAuthUrl']\n>;\nexport type GitLabGetAuthUrlResult = AuthUrlResult;\nexport type GitLabAuthCallbackBody = RouteBodyInput<\n GitLabRoutes['authCallback']\n>;\nexport type GitLabAuthCallbackResult = TokenResult;\nexport type GitLabListProjectsQuerystring = RouteQuerystring<\n GitLabRoutes['listProjects']\n>;\nexport type GitLabListProjectsResult = ResponseData<GitLabProject[]>;\nexport type GitLabCheckConfigBody = RouteBodyInput<GitLabRoutes['checkConfig']>;\nexport type GitLabCheckConfigResult = CheckConfigResult;\nexport type GitLabGetConfigFileBody = RouteBodyInput<\n GitLabRoutes['getConfigFile']\n>;\nexport type GitLabGetConfigFileResult = ConfigFileResult;\n\nexport type BitbucketGetAuthUrlQuerystring = RouteQuerystring<\n BitbucketRoutes['getAuthUrl']\n>;\nexport type BitbucketGetAuthUrlResult = AuthUrlResult;\nexport type BitbucketAuthCallbackBody = RouteBodyInput<\n BitbucketRoutes['authCallback']\n>;\nexport type BitbucketAuthCallbackResult = TokenResult;\nexport type BitbucketListReposQuerystring = RouteQuerystring<\n BitbucketRoutes['listRepos']\n>;\nexport type BitbucketListReposResult = ResponseData<BitbucketRepository[]>;\nexport type BitbucketCheckConfigBody = RouteBodyInput<\n BitbucketRoutes['checkConfig']\n>;\nexport type BitbucketCheckConfigResult = CheckConfigResult;\nexport type BitbucketGetConfigFileBody = RouteBodyInput<\n BitbucketRoutes['getConfigFile']\n>;\nexport type BitbucketGetConfigFileResult = ConfigFileResult;\n\nexport type ForgeListReposQuerystring = RouteQuerystring<\n ForgeRoutes['listRepos']\n>;\nexport type ForgeListReposResult = ResponseData<ForgeRepository[]>;\nexport type ForgeCheckConfigBody = RouteBodyInput<ForgeRoutes['checkConfig']>;\nexport type ForgeCheckConfigResult = CheckConfigResult;\nexport type ForgeGetConfigFileBody = RouteBodyInput<\n ForgeRoutes['getConfigFile']\n>;\nexport type ForgeGetConfigFileResult = ConfigFileResult;\n"],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { defineRoute, defineRouteGroup } from "./defineRoute.mjs";
2
+ import { responseDataSchema } from "./responseData.mjs";
3
+ import { emailsListSchema, userSchema } from "./user.mjs";
4
+ import { z } from "zod/mini";
5
+
6
+ //#region src/newsletter.ts
7
+ /** One mailing list or several. */
8
+ const emailListSchema = z.union([emailsListSchema, z.array(emailsListSchema)]);
9
+ /** REST contract of the `/api/newsletter` routes. */
10
+ const newsletterContract = defineRouteGroup({
11
+ prefix: "/api/newsletter",
12
+ tag: "Newsletter",
13
+ routes: {
14
+ subscribeToNewsletter: defineRoute({
15
+ method: "POST",
16
+ path: "/subscribe",
17
+ summary: "Subscribe an email to mailing lists",
18
+ schemas: {
19
+ body: z.object({
20
+ email: z.string().check(z.minLength(1)),
21
+ emailList: emailListSchema
22
+ }),
23
+ response: { 200: responseDataSchema(userSchema) }
24
+ }
25
+ }),
26
+ unsubscribeFromNewsletter: defineRoute({
27
+ method: "POST",
28
+ path: "/unsubscribe",
29
+ summary: "Unsubscribe a user from mailing lists",
30
+ schemas: {
31
+ body: z.object({
32
+ userId: z.string(),
33
+ emailList: emailListSchema
34
+ }),
35
+ response: { 200: responseDataSchema(userSchema) }
36
+ }
37
+ }),
38
+ getNewsletterStatus: defineRoute({
39
+ method: "GET",
40
+ path: "/status",
41
+ summary: "Mailing list subscriptions of the signed-in user",
42
+ schemas: { response: { 200: responseDataSchema(userSchema) } }
43
+ })
44
+ }
45
+ });
46
+
47
+ //#endregion
48
+ export { newsletterContract };
49
+ //# sourceMappingURL=newsletter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"newsletter.mjs","names":[],"sources":["../../src/newsletter.ts"],"sourcesContent":["import { z } from 'zod/mini';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBodyInput,\n} from './defineRoute';\nimport { type ResponseData, responseDataSchema } from './responseData';\nimport { emailsListSchema, type UserAPI, userSchema } from './user';\n\n/** One mailing list or several. */\nconst emailListSchema = z.union([emailsListSchema, z.array(emailsListSchema)]);\n\n/** REST contract of the `/api/newsletter` routes. */\nexport const newsletterContract = defineRouteGroup({\n prefix: '/api/newsletter',\n tag: 'Newsletter',\n routes: {\n subscribeToNewsletter: defineRoute({\n method: 'POST',\n path: '/subscribe',\n summary: 'Subscribe an email to mailing lists',\n schemas: {\n body: z.object({\n email: z.string().check(z.minLength(1)),\n emailList: emailListSchema,\n }),\n response: { 200: responseDataSchema(userSchema) },\n },\n }),\n unsubscribeFromNewsletter: defineRoute({\n method: 'POST',\n path: '/unsubscribe',\n summary: 'Unsubscribe a user from mailing lists',\n schemas: {\n body: z.object({\n userId: z.string(),\n emailList: emailListSchema,\n }),\n response: { 200: responseDataSchema(userSchema) },\n },\n }),\n getNewsletterStatus: defineRoute({\n method: 'GET',\n path: '/status',\n summary: 'Mailing list subscriptions of the signed-in user',\n schemas: {\n response: { 200: responseDataSchema(userSchema) },\n },\n }),\n },\n});\n\n/** Route definitions of the `/api/newsletter` group, by name. */\nexport type NewsletterRoutes = (typeof newsletterContract)['routes'];\n\nexport type NewsletterSubscriptionBody = RouteBodyInput<\n NewsletterRoutes['subscribeToNewsletter']\n>;\nexport type NewsletterSubscriptionResult = ResponseData<UserAPI>;\nexport type NewsletterUnsubscriptionBody = RouteBodyInput<\n NewsletterRoutes['unsubscribeFromNewsletter']\n>;\nexport type NewsletterUnsubscriptionResult = ResponseData<UserAPI>;\nexport type GetNewsletterStatusResult = ResponseData<UserAPI>;\n"],"mappings":";;;;;;;AAUA,MAAM,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,EAAE,MAAM,gBAAgB,CAAC,CAAC;;AAG7E,MAAa,qBAAqB,iBAAiB;CACjD,QAAQ;CACR,KAAK;CACL,QAAQ;EACN,uBAAuB,YAAY;GACjC,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;IACP,MAAM,EAAE,OAAO;KACb,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;KACtC,WAAW;IACb,CAAC;IACD,UAAU,EAAE,KAAK,mBAAmB,UAAU,EAAE;GAClD;EACF,CAAC;EACD,2BAA2B,YAAY;GACrC,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;IACP,MAAM,EAAE,OAAO;KACb,QAAQ,EAAE,OAAO;KACjB,WAAW;IACb,CAAC;IACD,UAAU,EAAE,KAAK,mBAAmB,UAAU,EAAE;GAClD;EACF,CAAC;EACD,qBAAqB,YAAY;GAC/B,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS,EACP,UAAU,EAAE,KAAK,mBAAmB,UAAU,EAAE,EAClD;EACF,CAAC;CACH;AACF,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { defineRoute, defineRouteGroup } from "./defineRoute.mjs";
2
+ import { responseDataSchema } from "./responseData.mjs";
3
+ import { dateTimeSchema } from "./common.mjs";
4
+ import { userSchema } from "./user.mjs";
5
+ import { projectSchema } from "./project.mjs";
6
+ import { organizationSchema } from "./organization.mjs";
7
+ import { z } from "zod/mini";
8
+
9
+ //#region src/oAuth2.ts
10
+ /** Access token issued for an access key (client credentials). */
11
+ const oAuth2TokenSchema = z.looseObject({
12
+ accessToken: z.string(),
13
+ /** `null` for a token without expiry. */
14
+ accessTokenExpiresAt: z.optional(z.nullable(dateTimeSchema)),
15
+ grants: z.optional(z.array(z.string())),
16
+ client: z.looseObject({
17
+ id: z.string(),
18
+ grants: z.array(z.string())
19
+ }),
20
+ user: userSchema,
21
+ organization: organizationSchema,
22
+ project: projectSchema
23
+ });
24
+ /** REST contract of the OAuth2 client-credentials routes. */
25
+ const oAuth2Contract = defineRouteGroup({
26
+ prefix: "/oauth2",
27
+ tag: "OAuth2",
28
+ routes: {
29
+ getOAuth2AccessToken: defineRoute({
30
+ method: "POST",
31
+ path: "/token",
32
+ summary: "Exchange access key credentials for an access token",
33
+ schemas: {
34
+ /**
35
+ * Documented only: the OAuth2 server validates it (credentials may
36
+ * also come from a Basic auth header) and answers spec errors.
37
+ */
38
+ body: z.looseObject({
39
+ grant_type: z.optional(z.string()),
40
+ client_id: z.optional(z.string()),
41
+ client_secret: z.optional(z.string())
42
+ }),
43
+ response: { 200: responseDataSchema(oAuth2TokenSchema) }
44
+ }
45
+ }),
46
+ extendOAuth2Token: defineRoute({
47
+ method: "POST",
48
+ path: "/token/extend",
49
+ summary: "Extend the lifetime of the current access token",
50
+ schemas: { response: { 200: responseDataSchema(z.object({
51
+ accessToken: z.string(),
52
+ accessTokenExpiresAt: dateTimeSchema
53
+ })) } }
54
+ })
55
+ }
56
+ });
57
+
58
+ //#endregion
59
+ export { oAuth2Contract, oAuth2TokenSchema };
60
+ //# sourceMappingURL=oAuth2.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oAuth2.mjs","names":[],"sources":["../../src/oAuth2.ts"],"sourcesContent":["import { z } from 'zod/mini';\nimport { dateTimeSchema } from './common';\nimport {\n defineRoute,\n defineRouteGroup,\n type RouteBodyInput,\n} from './defineRoute';\nimport { organizationSchema } from './organization';\nimport { projectSchema } from './project';\nimport { type ResponseData, responseDataSchema } from './responseData';\nimport { userSchema } from './user';\n\n/** Access token issued for an access key (client credentials). */\nexport const oAuth2TokenSchema = z.looseObject({\n accessToken: z.string(),\n /** `null` for a token without expiry. */\n accessTokenExpiresAt: z.optional(z.nullable(dateTimeSchema)),\n grants: z.optional(z.array(z.string())),\n client: z.looseObject({ id: z.string(), grants: z.array(z.string()) }),\n user: userSchema,\n organization: organizationSchema,\n project: projectSchema,\n});\n\n/** REST contract of the OAuth2 client-credentials routes. */\nexport const oAuth2Contract = defineRouteGroup({\n prefix: '/oauth2',\n tag: 'OAuth2',\n routes: {\n getOAuth2AccessToken: defineRoute({\n method: 'POST',\n path: '/token',\n summary: 'Exchange access key credentials for an access token',\n schemas: {\n /**\n * Documented only: the OAuth2 server validates it (credentials may\n * also come from a Basic auth header) and answers spec errors.\n */\n body: z.looseObject({\n grant_type: z.optional(z.string()),\n client_id: z.optional(z.string()),\n client_secret: z.optional(z.string()),\n }),\n response: { 200: responseDataSchema(oAuth2TokenSchema) },\n },\n }),\n extendOAuth2Token: defineRoute({\n method: 'POST',\n path: '/token/extend',\n summary: 'Extend the lifetime of the current access token',\n schemas: {\n response: {\n 200: responseDataSchema(\n z.object({\n accessToken: z.string(),\n accessTokenExpiresAt: dateTimeSchema,\n })\n ),\n },\n },\n }),\n },\n});\n\n/** Route definitions of the OAuth2 group, by name. */\nexport type OAuth2Routes = (typeof oAuth2Contract)['routes'];\n\nexport type OAuth2Token = z.output<typeof oAuth2TokenSchema>;\nexport type GetOAuth2TokenBody = RouteBodyInput<\n OAuth2Routes['getOAuth2AccessToken']\n>;\nexport type GetOAuth2TokenResult = ResponseData<OAuth2Token>;\nexport type ExtendOAuth2TokenResult = ResponseData<{\n accessToken: string;\n accessTokenExpiresAt: string;\n}>;\n"],"mappings":";;;;;;;;;;AAaA,MAAa,oBAAoB,EAAE,YAAY;CAC7C,aAAa,EAAE,OAAO;;CAEtB,sBAAsB,EAAE,SAAS,EAAE,SAAS,cAAc,CAAC;CAC3D,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC,QAAQ,EAAE,YAAY;EAAE,IAAI,EAAE,OAAO;EAAG,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC;CAAE,CAAC;CACrE,MAAM;CACN,cAAc;CACd,SAAS;AACX,CAAC;;AAGD,MAAa,iBAAiB,iBAAiB;CAC7C,QAAQ;CACR,KAAK;CACL,QAAQ;EACN,sBAAsB,YAAY;GAChC,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS;;;;;IAKP,MAAM,EAAE,YAAY;KAClB,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC;KACjC,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC;KAChC,eAAe,EAAE,SAAS,EAAE,OAAO,CAAC;IACtC,CAAC;IACD,UAAU,EAAE,KAAK,mBAAmB,iBAAiB,EAAE;GACzD;EACF,CAAC;EACD,mBAAmB,YAAY;GAC7B,QAAQ;GACR,MAAM;GACN,SAAS;GACT,SAAS,EACP,UAAU,EACR,KAAK,mBACH,EAAE,OAAO;IACP,aAAa,EAAE,OAAO;IACtB,sBAAsB;GACxB,CAAC,CACH,EACF,EACF;EACF,CAAC;CACH;AACF,CAAC"}