storybooker 0.19.3 → 0.22.0-canary.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 (215) hide show
  1. package/README.md +40 -18
  2. package/dist/adapters/_internal/queue.d.mts +127 -0
  3. package/dist/aws-dynamodb.d.mts +22 -0
  4. package/dist/aws-dynamodb.mjs +118 -0
  5. package/dist/aws-dynamodb.mjs.map +1 -0
  6. package/dist/aws-s3.d.mts +20 -0
  7. package/dist/aws-s3.mjs +96 -0
  8. package/dist/aws-s3.mjs.map +1 -0
  9. package/dist/azure-blob-storage.d.mts +20 -0
  10. package/dist/azure-blob-storage.mjs +126 -0
  11. package/dist/azure-blob-storage.mjs.map +1 -0
  12. package/dist/azure-cosmos-db.d.mts +23 -0
  13. package/dist/azure-cosmos-db.mjs +87 -0
  14. package/dist/azure-cosmos-db.mjs.map +1 -0
  15. package/dist/azure-data-tables.d.mts +23 -0
  16. package/dist/azure-data-tables.mjs +127 -0
  17. package/dist/azure-data-tables.mjs.map +1 -0
  18. package/dist/azure-easy-auth.d.mts +50 -0
  19. package/dist/azure-easy-auth.mjs +88 -0
  20. package/dist/azure-easy-auth.mjs.map +1 -0
  21. package/dist/azure-functions.d.mts +62 -0
  22. package/dist/azure-functions.mjs +147 -0
  23. package/dist/azure-functions.mjs.map +1 -0
  24. package/dist/fs.d.mts +37 -0
  25. package/dist/fs.mjs +240 -0
  26. package/dist/fs.mjs.map +1 -0
  27. package/dist/gcp-big-table.d.mts +23 -0
  28. package/dist/gcp-big-table.mjs +92 -0
  29. package/dist/gcp-big-table.mjs.map +1 -0
  30. package/dist/gcp-firestore.d.mts +22 -0
  31. package/dist/gcp-firestore.mjs +87 -0
  32. package/dist/gcp-firestore.mjs.map +1 -0
  33. package/dist/gcp-storage.d.mts +20 -0
  34. package/dist/gcp-storage.mjs +96 -0
  35. package/dist/gcp-storage.mjs.map +1 -0
  36. package/dist/handlers/handle-process-zip.mjs +90 -0
  37. package/dist/handlers/handle-process-zip.mjs.map +1 -0
  38. package/dist/handlers/handle-purge.d.mts +12 -0
  39. package/dist/handlers/handle-purge.mjs +36 -0
  40. package/dist/handlers/handle-purge.mjs.map +1 -0
  41. package/dist/handlers/handle-serve-storybook.mjs +94 -0
  42. package/dist/handlers/handle-serve-storybook.mjs.map +1 -0
  43. package/dist/index.d.mts +28 -0
  44. package/dist/index.mjs +62 -0
  45. package/dist/index.mjs.map +1 -0
  46. package/dist/models/builds-model.mjs +248 -0
  47. package/dist/models/builds-model.mjs.map +1 -0
  48. package/dist/models/builds-schema.d.mts +171 -0
  49. package/dist/models/builds-schema.mjs +67 -0
  50. package/dist/models/builds-schema.mjs.map +1 -0
  51. package/dist/models/projects-model.mjs +122 -0
  52. package/dist/models/projects-model.mjs.map +1 -0
  53. package/dist/models/projects-schema.d.mts +70 -0
  54. package/dist/models/projects-schema.mjs +37 -0
  55. package/dist/models/projects-schema.mjs.map +1 -0
  56. package/dist/models/tags-model.mjs +110 -0
  57. package/dist/models/tags-model.mjs.map +1 -0
  58. package/dist/models/tags-schema.d.mts +76 -0
  59. package/dist/models/tags-schema.mjs +34 -0
  60. package/dist/models/tags-schema.mjs.map +1 -0
  61. package/dist/models/~model.mjs +43 -0
  62. package/dist/models/~model.mjs.map +1 -0
  63. package/dist/models/~shared-schema.d.mts +1 -0
  64. package/dist/models/~shared-schema.mjs +20 -0
  65. package/dist/models/~shared-schema.mjs.map +1 -0
  66. package/dist/mysql.d.mts +39 -0
  67. package/dist/mysql.mjs +151 -0
  68. package/dist/mysql.mjs.map +1 -0
  69. package/dist/redis.d.mts +33 -0
  70. package/dist/redis.mjs +118 -0
  71. package/dist/redis.mjs.map +1 -0
  72. package/dist/routers/account-router.mjs +91 -0
  73. package/dist/routers/account-router.mjs.map +1 -0
  74. package/dist/routers/builds-router.mjs +347 -0
  75. package/dist/routers/builds-router.mjs.map +1 -0
  76. package/dist/routers/projects-router.mjs +236 -0
  77. package/dist/routers/projects-router.mjs.map +1 -0
  78. package/dist/routers/root-router.mjs +108 -0
  79. package/dist/routers/root-router.mjs.map +1 -0
  80. package/dist/routers/tags-router.mjs +269 -0
  81. package/dist/routers/tags-router.mjs.map +1 -0
  82. package/dist/routers/tasks-router.mjs +71 -0
  83. package/dist/routers/tasks-router.mjs.map +1 -0
  84. package/dist/urls.d.mts +47 -0
  85. package/dist/urls.mjs +208 -0
  86. package/dist/urls.mjs.map +1 -0
  87. package/dist/utils/adapter-utils.d.mts +14 -0
  88. package/dist/utils/adapter-utils.mjs +14 -0
  89. package/dist/utils/adapter-utils.mjs.map +1 -0
  90. package/dist/utils/auth.mjs +25 -0
  91. package/dist/utils/auth.mjs.map +1 -0
  92. package/dist/utils/error.d.mts +21 -0
  93. package/dist/utils/error.mjs +109 -0
  94. package/dist/utils/error.mjs.map +1 -0
  95. package/dist/utils/file-utils.mjs +16 -0
  96. package/dist/utils/file-utils.mjs.map +1 -0
  97. package/dist/utils/openapi-utils.mjs +45 -0
  98. package/dist/utils/openapi-utils.mjs.map +1 -0
  99. package/dist/utils/request.mjs +35 -0
  100. package/dist/utils/request.mjs.map +1 -0
  101. package/dist/utils/response.mjs +24 -0
  102. package/dist/utils/response.mjs.map +1 -0
  103. package/dist/utils/store.mjs +54 -0
  104. package/dist/utils/store.mjs.map +1 -0
  105. package/dist/utils/ui-utils.mjs +38 -0
  106. package/dist/utils/ui-utils.mjs.map +1 -0
  107. package/dist/utils/url-utils.d.mts +10 -0
  108. package/dist/utils/url-utils.mjs +54 -0
  109. package/dist/utils/url-utils.mjs.map +1 -0
  110. package/dist/~internal/adapter/auth.d.mts +123 -0
  111. package/dist/~internal/adapter/auth.mjs +20 -0
  112. package/dist/~internal/adapter/auth.mjs.map +1 -0
  113. package/dist/~internal/adapter/database.d.mts +240 -0
  114. package/dist/~internal/adapter/database.mjs +63 -0
  115. package/dist/~internal/adapter/database.mjs.map +1 -0
  116. package/dist/~internal/adapter/logger.d.mts +34 -0
  117. package/dist/~internal/adapter/logger.mjs +13 -0
  118. package/dist/~internal/adapter/logger.mjs.map +1 -0
  119. package/dist/~internal/adapter/storage.d.mts +208 -0
  120. package/dist/~internal/adapter/storage.mjs +63 -0
  121. package/dist/~internal/adapter/storage.mjs.map +1 -0
  122. package/dist/~internal/adapter/ui.d.mts +109 -0
  123. package/dist/~internal/adapter/ui.mjs +1 -0
  124. package/dist/~internal/adapter.d.mts +8 -0
  125. package/dist/~internal/adapter.mjs +6 -0
  126. package/dist/~internal/constants.d.mts +24 -0
  127. package/dist/~internal/constants.mjs +32 -0
  128. package/dist/~internal/constants.mjs.map +1 -0
  129. package/dist/~internal/mimes.d.mts +449 -0
  130. package/dist/~internal/mimes.mjs +454 -0
  131. package/dist/~internal/mimes.mjs.map +1 -0
  132. package/dist/~internal/router.d.mts +1651 -0
  133. package/dist/~internal/router.mjs +39 -0
  134. package/dist/~internal/router.mjs.map +1 -0
  135. package/dist/~internal/types.d.mts +77 -0
  136. package/dist/~internal/types.mjs +1 -0
  137. package/dist/~internal/utils.d.mts +4 -0
  138. package/dist/~internal/utils.mjs +5 -0
  139. package/openapi.json +3162 -0
  140. package/package.json +148 -27
  141. package/src/adapters/_internal/auth.ts +135 -0
  142. package/src/adapters/_internal/database.ts +241 -0
  143. package/src/adapters/_internal/index.ts +8 -0
  144. package/src/adapters/_internal/logger.ts +41 -0
  145. package/src/adapters/_internal/queue.ts +151 -0
  146. package/src/adapters/_internal/storage.ts +197 -0
  147. package/src/adapters/_internal/ui.ts +103 -0
  148. package/src/adapters/aws-dynamodb.ts +201 -0
  149. package/src/adapters/aws-s3.ts +160 -0
  150. package/src/adapters/azure-blob-storage.ts +223 -0
  151. package/src/adapters/azure-cosmos-db.ts +158 -0
  152. package/src/adapters/azure-data-tables.ts +223 -0
  153. package/src/adapters/azure-easy-auth.ts +174 -0
  154. package/src/adapters/azure-functions.ts +242 -0
  155. package/src/adapters/fs.ts +398 -0
  156. package/src/adapters/gcp-big-table.ts +157 -0
  157. package/src/adapters/gcp-firestore.ts +146 -0
  158. package/src/adapters/gcp-storage.ts +141 -0
  159. package/src/adapters/mysql.ts +296 -0
  160. package/src/adapters/redis.ts +242 -0
  161. package/src/handlers/handle-process-zip.ts +117 -0
  162. package/src/handlers/handle-purge.ts +65 -0
  163. package/src/handlers/handle-serve-storybook.ts +101 -0
  164. package/src/index.ts +81 -16
  165. package/src/mocks/mock-auth-service.ts +51 -0
  166. package/src/mocks/mock-store.ts +26 -0
  167. package/src/models/builds-model.ts +373 -0
  168. package/src/models/builds-schema.ts +84 -0
  169. package/src/models/projects-model.ts +177 -0
  170. package/src/models/projects-schema.ts +69 -0
  171. package/src/models/tags-model.ts +138 -0
  172. package/src/models/tags-schema.ts +45 -0
  173. package/src/models/~model.ts +79 -0
  174. package/src/models/~shared-schema.ts +14 -0
  175. package/src/routers/_app-router.ts +57 -0
  176. package/src/routers/account-router.ts +136 -0
  177. package/src/routers/builds-router.ts +464 -0
  178. package/src/routers/projects-router.ts +309 -0
  179. package/src/routers/root-router.ts +127 -0
  180. package/src/routers/tags-router.ts +339 -0
  181. package/src/routers/tasks-router.ts +75 -0
  182. package/src/types.ts +107 -0
  183. package/src/urls.ts +327 -0
  184. package/src/utils/adapter-utils.ts +26 -0
  185. package/src/utils/auth.test.ts +71 -0
  186. package/src/utils/auth.ts +39 -0
  187. package/src/utils/constants.ts +31 -0
  188. package/src/utils/date-utils.ts +10 -0
  189. package/src/utils/error.test.ts +86 -0
  190. package/src/utils/error.ts +140 -0
  191. package/src/utils/file-utils.test.ts +65 -0
  192. package/src/utils/file-utils.ts +43 -0
  193. package/src/utils/index.ts +3 -0
  194. package/src/utils/mime-utils.ts +457 -0
  195. package/src/utils/openapi-utils.ts +49 -0
  196. package/src/utils/request.ts +97 -0
  197. package/src/utils/response.ts +20 -0
  198. package/src/utils/store.ts +85 -0
  199. package/src/utils/story-utils.ts +42 -0
  200. package/src/utils/text-utils.ts +10 -0
  201. package/src/utils/ui-utils.ts +57 -0
  202. package/src/utils/url-utils.ts +113 -0
  203. package/dist/index.js +0 -554
  204. package/src/commands/create.ts +0 -263
  205. package/src/commands/purge.ts +0 -70
  206. package/src/commands/test.ts +0 -42
  207. package/src/service-schema.d.ts +0 -2023
  208. package/src/utils/auth-utils.ts +0 -31
  209. package/src/utils/pkg-utils.ts +0 -37
  210. package/src/utils/sb-build.ts +0 -55
  211. package/src/utils/sb-test.ts +0 -115
  212. package/src/utils/schema-utils.ts +0 -123
  213. package/src/utils/stream-utils.ts +0 -72
  214. package/src/utils/types.ts +0 -4
  215. package/src/utils/zip.ts +0 -77
@@ -0,0 +1,309 @@
1
+ import { createRoute, OpenAPIHono } from "@hono/zod-openapi";
2
+ import { HTTPException } from "hono/http-exception";
3
+ import { z } from "zod";
4
+ import { BuildsModel } from "../models/builds-model.ts";
5
+ import { ProjectsModel } from "../models/projects-model.ts";
6
+ import {
7
+ ProjectCreateSchema,
8
+ ProjectGetResultSchema,
9
+ ProjectIdSchema,
10
+ ProjectsListResultSchema,
11
+ ProjectUpdateSchema,
12
+ } from "../models/projects-schema.ts";
13
+ import { TagsModel } from "../models/tags-model.ts";
14
+ import { urlBuilder } from "../urls.ts";
15
+ import { authenticateOrThrow } from "../utils/auth.ts";
16
+ import { mimes } from "../utils/mime-utils.ts";
17
+ import {
18
+ openapiCommonErrorResponses,
19
+ openapiErrorResponseContent,
20
+ openapiResponseRedirect,
21
+ openapiResponsesHtml,
22
+ } from "../utils/openapi-utils.ts";
23
+ import { checkIsHTMLRequest } from "../utils/request.ts";
24
+ import { getStore } from "../utils/store.ts";
25
+ import { createUIResultResponse } from "../utils/ui-utils.ts";
26
+
27
+ const projectTag = "Projects";
28
+ const projectIdPathParams = z.object({ projectId: ProjectIdSchema });
29
+
30
+ /**
31
+ * @private
32
+ */
33
+ export const projectsRouter = new OpenAPIHono()
34
+ .openapi(
35
+ createRoute({
36
+ summary: "List projects",
37
+ method: "get",
38
+ path: "/projects",
39
+ tags: [projectTag],
40
+ responses: {
41
+ 200: {
42
+ description: "A list of projects.",
43
+ content: {
44
+ [mimes.json]: { schema: ProjectsListResultSchema },
45
+ ...openapiResponsesHtml,
46
+ },
47
+ },
48
+ ...openapiCommonErrorResponses,
49
+ },
50
+ }),
51
+ async (context) => {
52
+ const { ui } = getStore();
53
+
54
+ authenticateOrThrow({
55
+ action: "read",
56
+ projectId: undefined,
57
+ resource: "project",
58
+ });
59
+
60
+ const projects = await new ProjectsModel().list();
61
+
62
+ if (ui?.renderProjectsListPage && checkIsHTMLRequest()) {
63
+ return createUIResultResponse(context, ui.renderProjectsListPage, { projects });
64
+ }
65
+
66
+ return context.json({ projects });
67
+ },
68
+ )
69
+ .openapi(
70
+ createRoute({
71
+ summary: "Create project - UI",
72
+ method: "get",
73
+ path: "/projects/create",
74
+ tags: [projectTag],
75
+ responses: {
76
+ 200: {
77
+ description: "UI to create project",
78
+ content: openapiResponsesHtml,
79
+ },
80
+ ...openapiCommonErrorResponses,
81
+ },
82
+ }),
83
+ (context) => {
84
+ const { ui } = getStore();
85
+ if (!ui?.renderProjectCreatePage) {
86
+ throw new HTTPException(405, { message: "UI not available for this route." });
87
+ }
88
+
89
+ authenticateOrThrow({
90
+ action: "create",
91
+ projectId: undefined,
92
+ resource: "project",
93
+ });
94
+
95
+ return createUIResultResponse(context, ui.renderProjectCreatePage, {});
96
+ },
97
+ )
98
+ .openapi(
99
+ createRoute({
100
+ summary: "Create project - action",
101
+ method: "post",
102
+ path: "/projects/create",
103
+ tags: [projectTag],
104
+ request: {
105
+ body: {
106
+ content: { [mimes.formEncoded]: { schema: ProjectCreateSchema } },
107
+ required: true,
108
+ },
109
+ },
110
+ responses: {
111
+ 201: {
112
+ description: "Project created successfully",
113
+ content: { [mimes.json]: { schema: ProjectGetResultSchema } },
114
+ },
115
+ 303: openapiResponseRedirect("Redirect to project."),
116
+ 409: {
117
+ content: openapiErrorResponseContent,
118
+ description: "Project already exists.",
119
+ },
120
+ 415: {
121
+ content: openapiErrorResponseContent,
122
+ description: "Unsupported Media Type",
123
+ },
124
+ ...openapiCommonErrorResponses,
125
+ },
126
+ }),
127
+ async (context) => {
128
+ authenticateOrThrow({
129
+ action: "create",
130
+ projectId: undefined,
131
+ resource: "project",
132
+ });
133
+ const data = context.req.valid("form");
134
+ const project = await new ProjectsModel().create(data);
135
+
136
+ if (checkIsHTMLRequest(true)) {
137
+ return context.redirect(urlBuilder.projectDetails(project.id), 303);
138
+ }
139
+
140
+ return context.json({ project });
141
+ },
142
+ )
143
+ .openapi(
144
+ createRoute({
145
+ summary: "Project details",
146
+ method: "get",
147
+ path: "/projects/{projectId}",
148
+ tags: [projectTag],
149
+ request: { params: projectIdPathParams },
150
+ responses: {
151
+ 200: {
152
+ description: "Details of the project",
153
+ content: {
154
+ [mimes.json]: { schema: ProjectGetResultSchema },
155
+ ...openapiResponsesHtml,
156
+ },
157
+ },
158
+ 404: {
159
+ description: "Matching project not found.",
160
+ content: openapiErrorResponseContent,
161
+ },
162
+ ...openapiCommonErrorResponses,
163
+ },
164
+ }),
165
+ async (context) => {
166
+ const { ui } = getStore();
167
+ const { projectId } = context.req.valid("param");
168
+
169
+ authenticateOrThrow({
170
+ action: "read",
171
+ projectId,
172
+ resource: "project",
173
+ });
174
+
175
+ const project = await new ProjectsModel().get(projectId);
176
+
177
+ if (ui?.renderProjectDetailsPage && checkIsHTMLRequest()) {
178
+ const recentTags = await new TagsModel(projectId).list({ limit: 10 });
179
+ const recentBuilds = await new BuildsModel(projectId).list({
180
+ limit: 10,
181
+ });
182
+
183
+ return createUIResultResponse(context, ui.renderProjectDetailsPage, {
184
+ project,
185
+ recentBuilds,
186
+ recentTags,
187
+ });
188
+ }
189
+
190
+ return context.json({ project });
191
+ },
192
+ )
193
+ .openapi(
194
+ createRoute({
195
+ summary: "Delete project - action",
196
+ method: "post",
197
+ path: "/projects/{projectId}/delete",
198
+ tags: [projectTag],
199
+ request: { params: projectIdPathParams },
200
+ responses: {
201
+ 204: { description: "Project deleted successfully." },
202
+ 303: openapiResponseRedirect("Redirect to projects list."),
203
+ 404: {
204
+ description: "Matching project not found.",
205
+ content: openapiErrorResponseContent,
206
+ },
207
+ ...openapiCommonErrorResponses,
208
+ },
209
+ }),
210
+ async (context) => {
211
+ const { projectId } = context.req.valid("param");
212
+ authenticateOrThrow({
213
+ action: "delete",
214
+ projectId,
215
+ resource: "project",
216
+ });
217
+
218
+ await new ProjectsModel().delete(projectId);
219
+
220
+ if (checkIsHTMLRequest(true)) {
221
+ return context.redirect(urlBuilder.projectsList(), 303);
222
+ }
223
+
224
+ return new Response(null, { status: 204 });
225
+ },
226
+ )
227
+ .openapi(
228
+ createRoute({
229
+ summary: "Update project - UI",
230
+ method: "get",
231
+ path: "/projects/{projectId}/update",
232
+ tags: [projectTag],
233
+ request: { params: projectIdPathParams },
234
+ responses: {
235
+ 200: {
236
+ description: "UI to update project",
237
+ content: openapiResponsesHtml,
238
+ },
239
+ 404: {
240
+ description: "Matching project not found.",
241
+ content: openapiErrorResponseContent,
242
+ },
243
+ ...openapiCommonErrorResponses,
244
+ },
245
+ }),
246
+ async (context) => {
247
+ const { ui } = getStore();
248
+ if (!ui?.renderProjectUpdatePage) {
249
+ throw new HTTPException(405, { message: "UI not available for this route." });
250
+ }
251
+
252
+ const { projectId } = context.req.valid("param");
253
+ authenticateOrThrow({
254
+ action: "update",
255
+ projectId,
256
+ resource: "project",
257
+ });
258
+
259
+ const project = await new ProjectsModel().get(projectId);
260
+
261
+ return createUIResultResponse(context, ui.renderProjectUpdatePage, { project });
262
+ },
263
+ )
264
+ .openapi(
265
+ createRoute({
266
+ summary: "Update project - action",
267
+ method: "post",
268
+ path: "/projects/{projectId}/update",
269
+ tags: [projectTag],
270
+ request: {
271
+ params: projectIdPathParams,
272
+ body: {
273
+ content: { [mimes.formEncoded]: { schema: ProjectUpdateSchema } },
274
+ required: true,
275
+ },
276
+ },
277
+ responses: {
278
+ 202: { description: "Project updated successfully" },
279
+ 303: openapiResponseRedirect("Redirect to project."),
280
+ 404: {
281
+ description: "Matching project not found.",
282
+ content: openapiErrorResponseContent,
283
+ },
284
+ 415: {
285
+ content: openapiErrorResponseContent,
286
+ description: "Unsupported Media Type",
287
+ },
288
+ ...openapiCommonErrorResponses,
289
+ },
290
+ }),
291
+ async (context) => {
292
+ const { projectId } = context.req.valid("param");
293
+
294
+ authenticateOrThrow({
295
+ action: "update",
296
+ projectId: undefined,
297
+ resource: "project",
298
+ });
299
+
300
+ const data = context.req.valid("form");
301
+ await new ProjectsModel().update(projectId, data);
302
+
303
+ if (checkIsHTMLRequest(true)) {
304
+ return context.redirect(urlBuilder.projectDetails(projectId), 303);
305
+ }
306
+
307
+ return new Response(null, { status: 202 });
308
+ },
309
+ );
@@ -0,0 +1,127 @@
1
+ import { createRoute, OpenAPIHono } from "@hono/zod-openapi";
2
+ import { z } from "zod";
3
+ import { handleServeStoryBook } from "../handlers/handle-serve-storybook.ts";
4
+ import { ProjectsModel } from "../models/projects-model.ts";
5
+ import { UrlBuilder, urlBuilder } from "../urls.ts";
6
+ import { authenticateOrThrow } from "../utils/auth.ts";
7
+ import { SERVICE_NAME } from "../utils/constants.ts";
8
+ import { mimes } from "../utils/mime-utils.ts";
9
+ import { openapiResponsesHtml } from "../utils/openapi-utils.ts";
10
+ import { checkIsHTMLRequest } from "../utils/request.ts";
11
+ import { getStore } from "../utils/store.ts";
12
+ import { createUIResultResponse } from "../utils/ui-utils.ts";
13
+
14
+ /**
15
+ * @private
16
+ */
17
+ export const rootRouter = new OpenAPIHono()
18
+ .openapi(
19
+ createRoute({
20
+ summary: "Homepage",
21
+ method: "get",
22
+ path: "/",
23
+ responses: {
24
+ 200: {
25
+ content: {
26
+ [mimes.json]: {
27
+ schema: z.object({
28
+ name: z.string(),
29
+ adapters: z.record(z.string(), z.object({ name: z.string() })),
30
+ config: z.record(z.string(), z.unknown()),
31
+ urls: z.record(z.string(), z.string()),
32
+ }),
33
+ },
34
+ ...openapiResponsesHtml,
35
+ },
36
+ description: "Render homepage or return a list of endpoint-urls.",
37
+ },
38
+ },
39
+ }),
40
+ async (context) => {
41
+ const { auth, database, logger, storage, ui, config } = getStore();
42
+
43
+ if (ui?.renderHomePage && checkIsHTMLRequest(true)) {
44
+ authenticateOrThrow({ action: "read", resource: "project", projectId: undefined });
45
+ const projects = await new ProjectsModel().list({ limit: 5 });
46
+
47
+ return createUIResultResponse(context, ui.renderHomePage, { projects });
48
+ }
49
+
50
+ const urls: Record<string, string> = {};
51
+ for (const urlKey of Object.getOwnPropertyNames(UrlBuilder.prototype)) {
52
+ const func = urlBuilder[urlKey as keyof UrlBuilder];
53
+ if (urlKey === "constructor" || typeof func !== "function") {
54
+ continue;
55
+ }
56
+
57
+ const keyword = "ARG0REMOVE";
58
+ const url = (func as (...args: string[]) => string).call(urlBuilder, keyword);
59
+ if (url.includes(keyword)) {
60
+ continue;
61
+ }
62
+
63
+ urls[urlKey] = url;
64
+ }
65
+
66
+ return context.json({
67
+ name: SERVICE_NAME,
68
+ adapters: {
69
+ auth: auth?.metadata,
70
+ database: database.metadata,
71
+ logger: logger.metadata,
72
+ storage: storage.metadata,
73
+ ui: ui?.metadata,
74
+ },
75
+ config: {
76
+ ...config,
77
+ middlewares: config?.middlewares?.map((mw) => mw.name),
78
+ errorParser: undefined,
79
+ },
80
+ urls,
81
+ });
82
+ },
83
+ )
84
+ .openapi(
85
+ createRoute({
86
+ summary: "Health check",
87
+ method: "get",
88
+ path: "/health",
89
+ responses: {
90
+ 200: { description: "Health check status" },
91
+ },
92
+ }),
93
+ (context) => {
94
+ return context.text("Service is healthy.");
95
+ },
96
+ )
97
+ .openapi(
98
+ createRoute({
99
+ summary: "Serve build files",
100
+ method: "get",
101
+ path: "_/{projectId}/{buildId}/{filepath{.+}}",
102
+ request: {
103
+ params: z.object({
104
+ projectId: z.string(),
105
+ buildId: z.string(),
106
+ filepath: z.string(),
107
+ }),
108
+ query: z
109
+ .object({
110
+ id: z.string(),
111
+ path: z.string(),
112
+ viewMode: z.enum(["story"]),
113
+ })
114
+ .partial(),
115
+ },
116
+ responses: {
117
+ 200: {
118
+ description: "Serving the uploaded file",
119
+ content: { "*/*": { schema: z.string() } },
120
+ },
121
+ },
122
+ }),
123
+ (context) => {
124
+ const { buildId, filepath, projectId } = context.req.param();
125
+ return handleServeStoryBook({ buildId, filepath, projectId });
126
+ },
127
+ );