@storyshelf/app 0.6.1 → 0.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.
- package/README.md +42 -4
- package/dist/app-types.d.mts +1 -3
- package/dist/asset-manifest.mjs +13 -5
- package/dist/asset-manifest.mjs.map +1 -1
- package/dist/assets/{htmx.min.js → htmx.mjs} +10 -1
- package/dist/assets/htmx.mjs.map +1 -0
- package/dist/assets/mark.mjs +10 -0
- package/dist/assets/mark.mjs.map +1 -0
- package/dist/boot-tasks.mjs +80 -0
- package/dist/boot-tasks.mjs.map +1 -0
- package/dist/build-state-flags.mjs +18 -0
- package/dist/build-state-flags.mjs.map +1 -0
- package/dist/build-state-setup.mjs +75 -0
- package/dist/build-state-setup.mjs.map +1 -0
- package/dist/capture-alerts.mjs +46 -0
- package/dist/capture-alerts.mjs.map +1 -0
- package/dist/capture-process.mjs +59 -0
- package/dist/capture-process.mjs.map +1 -0
- package/dist/capture-setup.mjs +95 -117
- package/dist/capture-setup.mjs.map +1 -1
- package/dist/connections.mjs +34 -0
- package/dist/connections.mjs.map +1 -0
- package/dist/consumer-setup.mjs +58 -0
- package/dist/consumer-setup.mjs.map +1 -0
- package/dist/credentials.mjs +3 -2
- package/dist/credentials.mjs.map +1 -1
- package/dist/git-status.mjs +46 -0
- package/dist/git-status.mjs.map +1 -0
- package/dist/hidden-data.mjs +24 -0
- package/dist/hidden-data.mjs.map +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +202 -124
- package/dist/index.mjs.map +1 -1
- package/dist/insights/budget.mjs +49 -0
- package/dist/insights/budget.mjs.map +1 -0
- package/dist/insights/deps.mjs +21 -0
- package/dist/insights/deps.mjs.map +1 -0
- package/dist/insights/errors.mjs +22 -0
- package/dist/insights/errors.mjs.map +1 -0
- package/dist/insights/health-panel.mjs +40 -0
- package/dist/insights/health-panel.mjs.map +1 -0
- package/dist/insights/job.mjs +103 -0
- package/dist/insights/job.mjs.map +1 -0
- package/dist/insights/load-health.mjs +59 -0
- package/dist/insights/load-health.mjs.map +1 -0
- package/dist/insights/load-triage.mjs +98 -0
- package/dist/insights/load-triage.mjs.map +1 -0
- package/dist/insights/panel.mjs +28 -0
- package/dist/insights/panel.mjs.map +1 -0
- package/dist/insights/request.mjs +113 -0
- package/dist/insights/request.mjs.map +1 -0
- package/dist/insights/stale.mjs +21 -0
- package/dist/insights/stale.mjs.map +1 -0
- package/dist/insights/usage-report.mjs +60 -0
- package/dist/insights/usage-report.mjs.map +1 -0
- package/dist/insights/view.mjs +48 -0
- package/dist/insights/view.mjs.map +1 -0
- package/dist/job-canceller.mjs +14 -0
- package/dist/job-canceller.mjs.map +1 -0
- package/dist/job-queue.mjs +51 -0
- package/dist/job-queue.mjs.map +1 -0
- package/dist/jobs-setup.mjs +132 -0
- package/dist/jobs-setup.mjs.map +1 -0
- package/dist/lifecycle.mjs +109 -19
- package/dist/lifecycle.mjs.map +1 -1
- package/dist/middleware/auth-gate.mjs +4 -2
- package/dist/middleware/auth-gate.mjs.map +1 -1
- package/dist/middleware/rate-limit.mjs +41 -33
- package/dist/middleware/rate-limit.mjs.map +1 -1
- package/dist/middleware/request-log.mjs +3 -2
- package/dist/middleware/request-log.mjs.map +1 -1
- package/dist/middleware/require-review.mjs +51 -0
- package/dist/middleware/require-review.mjs.map +1 -0
- package/dist/middleware/require-testing.mjs +41 -0
- package/dist/middleware/require-testing.mjs.map +1 -0
- package/dist/middleware/setup-gate.mjs.map +1 -1
- package/dist/middleware/store-scope.mjs +12 -2
- package/dist/middleware/store-scope.mjs.map +1 -1
- package/dist/notifications-pause.mjs +33 -0
- package/dist/notifications-pause.mjs.map +1 -0
- package/dist/notify.d.mts +2 -1
- package/dist/notify.mjs +78 -39
- package/dist/notify.mjs.map +1 -1
- package/dist/pages/a11y-violations.mjs +116 -0
- package/dist/pages/a11y-violations.mjs.map +1 -0
- package/dist/pages/admin-ai.mjs +78 -0
- package/dist/pages/admin-ai.mjs.map +1 -0
- package/dist/pages/admin-system-origin.mjs +123 -0
- package/dist/pages/admin-system-origin.mjs.map +1 -0
- package/dist/pages/admin-system-targets.mjs +53 -0
- package/dist/pages/admin-system-targets.mjs.map +1 -0
- package/dist/pages/admin-system.mjs +63 -13
- package/dist/pages/admin-system.mjs.map +1 -1
- package/dist/pages/build-detail.mjs +104 -76
- package/dist/pages/build-detail.mjs.map +1 -1
- package/dist/pages/build-diff-actions.mjs +87 -33
- package/dist/pages/build-diff-actions.mjs.map +1 -1
- package/dist/pages/build-diff-comments.mjs +16 -14
- package/dist/pages/build-diff-comments.mjs.map +1 -1
- package/dist/pages/build-diff-environment.mjs +82 -0
- package/dist/pages/build-diff-environment.mjs.map +1 -0
- package/dist/pages/build-diff-header.mjs +22 -4
- package/dist/pages/build-diff-header.mjs.map +1 -1
- package/dist/pages/build-diff-insight.mjs +113 -0
- package/dist/pages/build-diff-insight.mjs.map +1 -0
- package/dist/pages/build-diff-model.mjs +55 -10
- package/dist/pages/build-diff-model.mjs.map +1 -1
- package/dist/pages/build-diff-nav.mjs +28 -12
- package/dist/pages/build-diff-nav.mjs.map +1 -1
- package/dist/pages/build-diff-shortcuts.mjs +5 -1
- package/dist/pages/build-diff-shortcuts.mjs.map +1 -1
- package/dist/pages/build-diff-usage.mjs +63 -0
- package/dist/pages/build-diff-usage.mjs.map +1 -0
- package/dist/pages/build-diff-viewer.mjs +62 -5
- package/dist/pages/build-diff-viewer.mjs.map +1 -1
- package/dist/pages/build-diff.mjs +34 -13
- package/dist/pages/build-diff.mjs.map +1 -1
- package/dist/pages/build-tests.mjs +74 -0
- package/dist/pages/build-tests.mjs.map +1 -0
- package/dist/pages/component-detail.mjs +249 -0
- package/dist/pages/component-detail.mjs.map +1 -0
- package/dist/pages/component-stories.mjs +168 -0
- package/dist/pages/component-stories.mjs.map +1 -0
- package/dist/pages/compute-jobs.mjs +13 -26
- package/dist/pages/compute-jobs.mjs.map +1 -1
- package/dist/pages/design-links.mjs +182 -0
- package/dist/pages/design-links.mjs.map +1 -0
- package/dist/pages/environment-change.mjs +53 -0
- package/dist/pages/environment-change.mjs.map +1 -0
- package/dist/pages/health-panel.mjs +126 -0
- package/dist/pages/health-panel.mjs.map +1 -0
- package/dist/pages/library-grid.mjs +105 -0
- package/dist/pages/library-grid.mjs.map +1 -0
- package/dist/pages/library-model.mjs +47 -0
- package/dist/pages/library-model.mjs.map +1 -0
- package/dist/pages/library-snapshots.mjs +130 -0
- package/dist/pages/library-snapshots.mjs.map +1 -0
- package/dist/pages/library.mjs +112 -218
- package/dist/pages/library.mjs.map +1 -1
- package/dist/pages/notifications-paused.mjs +22 -0
- package/dist/pages/notifications-paused.mjs.map +1 -0
- package/dist/pages/profile.mjs +53 -48
- package/dist/pages/profile.mjs.map +1 -1
- package/dist/pages/project-builds-table.mjs +2 -2
- package/dist/pages/project-builds-table.mjs.map +1 -1
- package/dist/pages/project-builds.mjs +51 -21
- package/dist/pages/project-builds.mjs.map +1 -1
- package/dist/pages/project-settings.mjs +51 -12
- package/dist/pages/project-settings.mjs.map +1 -1
- package/dist/pages/projects-card.mjs +14 -1
- package/dist/pages/projects-card.mjs.map +1 -1
- package/dist/pages/projects.mjs +6 -2
- package/dist/pages/projects.mjs.map +1 -1
- package/dist/pages/review-changeset.mjs +116 -0
- package/dist/pages/review-changeset.mjs.map +1 -0
- package/dist/pages/review-comments.mjs +103 -0
- package/dist/pages/review-comments.mjs.map +1 -0
- package/dist/pages/review-verdict.mjs +102 -0
- package/dist/pages/review-verdict.mjs.map +1 -0
- package/dist/pages/settings-ai.mjs +69 -0
- package/dist/pages/settings-ai.mjs.map +1 -0
- package/dist/pages/settings-capture.mjs +124 -0
- package/dist/pages/settings-capture.mjs.map +1 -0
- package/dist/pages/settings-design-credential.mjs +99 -0
- package/dist/pages/settings-design-credential.mjs.map +1 -0
- package/dist/pages/settings-design-links.mjs +179 -0
- package/dist/pages/settings-design-links.mjs.map +1 -0
- package/dist/pages/settings-design.mjs +48 -0
- package/dist/pages/settings-design.mjs.map +1 -0
- package/dist/pages/settings-general.mjs +46 -21
- package/dist/pages/settings-general.mjs.map +1 -1
- package/dist/pages/settings-labels.mjs +43 -2
- package/dist/pages/settings-labels.mjs.map +1 -1
- package/dist/pages/settings-links.mjs +112 -0
- package/dist/pages/settings-links.mjs.map +1 -0
- package/dist/pages/settings-notifications-git.mjs +128 -0
- package/dist/pages/settings-notifications-git.mjs.map +1 -0
- package/dist/pages/settings-notifications.mjs +79 -42
- package/dist/pages/settings-notifications.mjs.map +1 -1
- package/dist/pages/settings-tests.mjs +33 -2
- package/dist/pages/settings-tests.mjs.map +1 -1
- package/dist/pages/target-choices.mjs +39 -0
- package/dist/pages/target-choices.mjs.map +1 -0
- package/dist/publish-setup.mjs +89 -0
- package/dist/publish-setup.mjs.map +1 -0
- package/dist/retention-timer.mjs +2 -1
- package/dist/retention-timer.mjs.map +1 -1
- package/dist/review-events.mjs +48 -0
- package/dist/review-events.mjs.map +1 -0
- package/dist/routers/admin-pages.mjs +45 -3
- package/dist/routers/admin-pages.mjs.map +1 -1
- package/dist/routers/admin-public-origin.mjs +85 -0
- package/dist/routers/admin-public-origin.mjs.map +1 -0
- package/dist/routers/assets.mjs +9 -2
- package/dist/routers/assets.mjs.map +1 -1
- package/dist/routers/auth.mjs +2 -2
- package/dist/routers/auth.mjs.map +1 -1
- package/dist/routers/baseline-guard.mjs +2 -2
- package/dist/routers/baseline-guard.mjs.map +1 -1
- package/dist/routers/baselines.handlers.mjs +64 -0
- package/dist/routers/baselines.handlers.mjs.map +1 -0
- package/dist/routers/baselines.mjs +125 -0
- package/dist/routers/baselines.mjs.map +1 -0
- package/dist/routers/build-cancel.mjs +68 -0
- package/dist/routers/build-cancel.mjs.map +1 -0
- package/dist/routers/build-changeset.mjs +70 -0
- package/dist/routers/build-changeset.mjs.map +1 -0
- package/dist/routers/build-reviews.handlers.mjs +86 -0
- package/dist/routers/build-reviews.handlers.mjs.map +1 -0
- package/dist/routers/build-reviews.mjs +74 -0
- package/dist/routers/build-reviews.mjs.map +1 -0
- package/dist/routers/builds.handlers.mjs +46 -55
- package/dist/routers/builds.handlers.mjs.map +1 -1
- package/dist/routers/builds.mjs +71 -17
- package/dist/routers/builds.mjs.map +1 -1
- package/dist/routers/capture-config.mjs +35 -0
- package/dist/routers/capture-config.mjs.map +1 -0
- package/dist/routers/comments.mjs +41 -15
- package/dist/routers/comments.mjs.map +1 -1
- package/dist/routers/component-catalog.handlers.mjs +71 -0
- package/dist/routers/component-catalog.handlers.mjs.map +1 -0
- package/dist/routers/component.handlers.mjs +121 -0
- package/dist/routers/component.handlers.mjs.map +1 -0
- package/dist/routers/connections.mjs +118 -0
- package/dist/routers/connections.mjs.map +1 -0
- package/dist/routers/design-connect.handlers.mjs +44 -0
- package/dist/routers/design-connect.handlers.mjs.map +1 -0
- package/dist/routers/design.handlers.mjs +114 -0
- package/dist/routers/design.handlers.mjs.map +1 -0
- package/dist/routers/health-report.mjs +2 -3
- package/dist/routers/health-report.mjs.map +1 -1
- package/dist/routers/health.mjs +4 -3
- package/dist/routers/health.mjs.map +1 -1
- package/dist/routers/helpers.mjs +19 -3
- package/dist/routers/helpers.mjs.map +1 -1
- package/dist/routers/insights-ui.mjs +64 -0
- package/dist/routers/insights-ui.mjs.map +1 -0
- package/dist/routers/insights.handlers.mjs +45 -0
- package/dist/routers/insights.handlers.mjs.map +1 -0
- package/dist/routers/insights.mjs +189 -0
- package/dist/routers/insights.mjs.map +1 -0
- package/dist/routers/links.handlers.mjs +80 -0
- package/dist/routers/links.handlers.mjs.map +1 -0
- package/dist/routers/links.mjs +139 -0
- package/dist/routers/links.mjs.map +1 -0
- package/dist/routers/media.mjs +18 -4
- package/dist/routers/media.mjs.map +1 -1
- package/dist/routers/members.mjs +2 -1
- package/dist/routers/members.mjs.map +1 -1
- package/dist/routers/notification-channels.mjs +17 -23
- package/dist/routers/notification-channels.mjs.map +1 -1
- package/dist/routers/oauth-state.mjs +45 -0
- package/dist/routers/oauth-state.mjs.map +1 -0
- package/dist/routers/preview-base.mjs +38 -0
- package/dist/routers/preview-base.mjs.map +1 -0
- package/dist/routers/preview-token.mjs +51 -0
- package/dist/routers/preview-token.mjs.map +1 -0
- package/dist/routers/profile.mjs +4 -2
- package/dist/routers/profile.mjs.map +1 -1
- package/dist/routers/projects.mjs +17 -1
- package/dist/routers/projects.mjs.map +1 -1
- package/dist/routers/publish-upload.mjs +78 -0
- package/dist/routers/publish-upload.mjs.map +1 -0
- package/dist/routers/published-access.mjs +52 -0
- package/dist/routers/published-access.mjs.map +1 -0
- package/dist/routers/published-files.mjs +52 -0
- package/dist/routers/published-files.mjs.map +1 -0
- package/dist/routers/review-forms.mjs +72 -0
- package/dist/routers/review-forms.mjs.map +1 -0
- package/dist/routers/review-section.handlers.mjs +85 -0
- package/dist/routers/review-section.handlers.mjs.map +1 -0
- package/dist/routers/review-switch-off.mjs +29 -0
- package/dist/routers/review-switch-off.mjs.map +1 -0
- package/dist/routers/schemas.mjs +140 -22
- package/dist/routers/schemas.mjs.map +1 -1
- package/dist/routers/scoped-models.mjs +22 -0
- package/dist/routers/scoped-models.mjs.map +1 -0
- package/dist/routers/settings-ai.mjs +35 -0
- package/dist/routers/settings-ai.mjs.map +1 -0
- package/dist/routers/settings-capture.mjs +77 -0
- package/dist/routers/settings-capture.mjs.map +1 -0
- package/dist/routers/settings-design.mjs +103 -0
- package/dist/routers/settings-design.mjs.map +1 -0
- package/dist/routers/settings-general.mjs +55 -10
- package/dist/routers/settings-general.mjs.map +1 -1
- package/dist/routers/settings-git-channel.mjs +77 -0
- package/dist/routers/settings-git-channel.mjs.map +1 -0
- package/dist/routers/settings-labels.mjs +27 -1
- package/dist/routers/settings-labels.mjs.map +1 -1
- package/dist/routers/settings-links.mjs +63 -0
- package/dist/routers/settings-links.mjs.map +1 -0
- package/dist/routers/settings-members.mjs +4 -7
- package/dist/routers/settings-members.mjs.map +1 -1
- package/dist/routers/settings-notifications.mjs +15 -10
- package/dist/routers/settings-notifications.mjs.map +1 -1
- package/dist/routers/settings-tokens.mjs +2 -5
- package/dist/routers/settings-tokens.mjs.map +1 -1
- package/dist/routers/settings-webhooks.mjs +7 -24
- package/dist/routers/settings-webhooks.mjs.map +1 -1
- package/dist/routers/settings.handlers.mjs +107 -26
- package/dist/routers/settings.handlers.mjs.map +1 -1
- package/dist/routers/settings.mjs +16 -4
- package/dist/routers/settings.mjs.map +1 -1
- package/dist/routers/signed-storybook.mjs +53 -0
- package/dist/routers/signed-storybook.mjs.map +1 -0
- package/dist/routers/snapshot-groups.mjs +63 -0
- package/dist/routers/snapshot-groups.mjs.map +1 -0
- package/dist/routers/snapshots.mjs +103 -5
- package/dist/routers/snapshots.mjs.map +1 -1
- package/dist/routers/storybook.mjs +37 -88
- package/dist/routers/storybook.mjs.map +1 -1
- package/dist/routers/tokens.mjs +2 -5
- package/dist/routers/tokens.mjs.map +1 -1
- package/dist/routers/ui.mjs +34 -5
- package/dist/routers/ui.mjs.map +1 -1
- package/dist/routers/webhooks.mjs +5 -11
- package/dist/routers/webhooks.mjs.map +1 -1
- package/dist/routers/well-known.mjs +11 -4
- package/dist/routers/well-known.mjs.map +1 -1
- package/dist/routes/api-routes.mjs +93 -0
- package/dist/routes/api-routes.mjs.map +1 -0
- package/dist/routes/classification.mjs +38 -0
- package/dist/routes/classification.mjs.map +1 -0
- package/dist/routes/openapi-classes.mjs +22 -0
- package/dist/routes/openapi-classes.mjs.map +1 -0
- package/dist/routes/page-routes.mjs +104 -0
- package/dist/routes/page-routes.mjs.map +1 -0
- package/dist/runtime.mjs +18 -13
- package/dist/runtime.mjs.map +1 -1
- package/dist/serverless.mjs +5 -0
- package/dist/store.mjs +19 -1
- package/dist/store.mjs.map +1 -1
- package/dist/targets.mjs +46 -0
- package/dist/targets.mjs.map +1 -0
- package/dist/ui/buttons.mjs +16 -3
- package/dist/ui/buttons.mjs.map +1 -1
- package/dist/ui/design-reference.mjs +97 -0
- package/dist/ui/design-reference.mjs.map +1 -0
- package/dist/ui/document.mjs +1 -2
- package/dist/ui/document.mjs.map +1 -1
- package/dist/ui/forms.mjs +6 -5
- package/dist/ui/forms.mjs.map +1 -1
- package/dist/ui/icons/paths.mjs +1 -0
- package/dist/ui/icons/paths.mjs.map +1 -1
- package/dist/ui/preview-embed.mjs +82 -0
- package/dist/ui/preview-embed.mjs.map +1 -0
- package/dist/ui/shell/client-script.mjs +85 -0
- package/dist/ui/shell/client-script.mjs.map +1 -1
- package/dist/ui/shell/nav.mjs +12 -8
- package/dist/ui/shell/nav.mjs.map +1 -1
- package/dist/ui/shell/review-script.mjs +8 -0
- package/dist/ui/shell/review-script.mjs.map +1 -1
- package/dist/ui/shell/sidebar.mjs +2 -2
- package/dist/ui/shell/sidebar.mjs.map +1 -1
- package/package.json +11 -6
- package/dist/asset-paths.mjs +0 -23
- package/dist/asset-paths.mjs.map +0 -1
- package/dist/assets/mark.svg +0 -1
- package/dist/pages/settings-status.mjs +0 -137
- package/dist/pages/settings-status.mjs.map +0 -1
- package/dist/routers/settings-status.mjs +0 -77
- package/dist/routers/settings-status.mjs.map +0 -1
- package/dist/routers/status-configs.mjs +0 -108
- package/dist/routers/status-configs.mjs.map +0 -1
package/dist/routers/schemas.mjs
CHANGED
|
@@ -2,9 +2,22 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { z } from "@hono/zod-openapi";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { storybookUrlTtlOverrideError } from "@storyshelf/core/utils";
|
|
6
|
+
import { WebhookModel } from "@storyshelf/core/models";
|
|
7
|
+
import { BUILD_STATUSES, PROJECT_ROLES, REVIEW_VERDICTS, SNAPSHOT_STATUSES } from "@storyshelf/core/types";
|
|
8
|
+
import { BROWSER_NAMES, TARGET_NAME_PATTERN } from "@storyshelf/core/adapter/capture-runner";
|
|
7
9
|
//#region src/routers/schemas.ts
|
|
10
|
+
/** A capture target: an engine (`chromium`) or a remote one, `<engine>@<name>` (ADR 0007). */
|
|
11
|
+
const captureTargetSchema = z.string().regex(new RegExp(`^(?:${BROWSER_NAMES.join("|")})(?:@${TARGET_NAME_PATTERN.source.slice(1, -1)})?$`, "u"), "Expected an engine (chromium, firefox, webkit, chrome) or <engine>@<name>");
|
|
12
|
+
const reviewApprovalsSchema = z.number().int().min(1).max(20);
|
|
13
|
+
/** Seconds a signed Storybook URL stays valid (ADR 0007, decision 5). */
|
|
14
|
+
const storybookUrlTtlSchema = z.number().int().superRefine((seconds, ctx) => {
|
|
15
|
+
const message = storybookUrlTtlOverrideError(seconds);
|
|
16
|
+
if (message !== void 0) ctx.addIssue({
|
|
17
|
+
code: "custom",
|
|
18
|
+
message
|
|
19
|
+
});
|
|
20
|
+
});
|
|
8
21
|
const storybookMetaSchema = z.record(z.string(), z.unknown()).nullable().optional();
|
|
9
22
|
/** OpenAPI schema for a project record. */
|
|
10
23
|
const projectSchema = z.object({
|
|
@@ -19,7 +32,23 @@ const projectSchema = z.object({
|
|
|
19
32
|
storybookMeta: z.string().nullable().optional(),
|
|
20
33
|
executePlay: z.boolean(),
|
|
21
34
|
playTimeoutMs: z.number(),
|
|
35
|
+
/** Axe accessibility checks run during capture (default on; results never block a build). */
|
|
36
|
+
runA11y: z.boolean().optional(),
|
|
37
|
+
/** Storybook 10 `.test()` entries run as interaction tests during capture (default off). */
|
|
38
|
+
runTests: z.boolean().optional(),
|
|
22
39
|
browser: z.string().optional(),
|
|
40
|
+
/** JSON array of capture targets, primary first, primary first; null = just `browser`. */
|
|
41
|
+
browsers: z.string().nullable().optional(),
|
|
42
|
+
/** JSON array of mode names to capture; null = every declared mode. */
|
|
43
|
+
modesAllowlist: z.string().nullable().optional(),
|
|
44
|
+
/** AI profile gate: null/absent = AI off for this project. */
|
|
45
|
+
aiProfile: z.string().nullable().optional(),
|
|
46
|
+
/** Review is on for this project (ADR 0013, decision 1). */
|
|
47
|
+
reviewEnabled: z.boolean().optional(),
|
|
48
|
+
/** Approvals a build needs when `testing` is off. */
|
|
49
|
+
reviewApprovals: z.number().optional(),
|
|
50
|
+
/** Seconds the signed Storybook URLs of a render stay valid; null derives it from the stories. */
|
|
51
|
+
storybookUrlTtlSeconds: z.number().nullable().optional(),
|
|
23
52
|
createdAt: z.string(),
|
|
24
53
|
updatedAt: z.string()
|
|
25
54
|
}).openapi("Project");
|
|
@@ -30,7 +59,13 @@ const projectCreateSchema = z.object({
|
|
|
30
59
|
gitDefaultBranch: z.string().optional(),
|
|
31
60
|
storybookMeta: storybookMetaSchema,
|
|
32
61
|
executePlay: z.boolean().optional(),
|
|
33
|
-
playTimeoutMs: z.number().int().min(1e3).max(3e4).optional()
|
|
62
|
+
playTimeoutMs: z.number().int().min(1e3).max(3e4).optional(),
|
|
63
|
+
/** Axe accessibility checks during capture; on when omitted. */
|
|
64
|
+
runA11y: z.boolean().optional(),
|
|
65
|
+
/** Run Storybook 10 `.test()` entries as interaction tests during capture; off when omitted. */
|
|
66
|
+
runTests: z.boolean().optional(),
|
|
67
|
+
reviewEnabled: z.boolean().optional(),
|
|
68
|
+
reviewApprovals: reviewApprovalsSchema.optional()
|
|
34
69
|
}).openapi("ProjectCreateInput");
|
|
35
70
|
/** OpenAPI schema for patching a project. */
|
|
36
71
|
const projectUpdateSchema = z.object({
|
|
@@ -43,7 +78,24 @@ const projectUpdateSchema = z.object({
|
|
|
43
78
|
storybookMeta: storybookMetaSchema,
|
|
44
79
|
executePlay: z.boolean().optional(),
|
|
45
80
|
playTimeoutMs: z.number().int().min(1e3).max(3e4).optional(),
|
|
46
|
-
|
|
81
|
+
/** Turn axe accessibility checks during capture on or off (admins). */
|
|
82
|
+
runA11y: z.boolean().optional(),
|
|
83
|
+
/** Turn the Storybook 10 `.test()` runs on or off (admins). */
|
|
84
|
+
runTests: z.boolean().optional(),
|
|
85
|
+
/** Single capture target; clears `browsers`. */
|
|
86
|
+
browser: captureTargetSchema.optional(),
|
|
87
|
+
/** Capture targets, primary first (max 3); null returns to single `browser`. */
|
|
88
|
+
browsers: z.array(captureTargetSchema).min(1).max(3).nullable().optional(),
|
|
89
|
+
/** Mode names to capture; null runs every declared mode. */
|
|
90
|
+
modesAllowlist: z.array(z.string().min(1)).max(50).nullable().optional(),
|
|
91
|
+
/** Site admins only: a configured AI profile name, or null to turn AI off. */
|
|
92
|
+
aiProfile: z.string().min(1).nullable().optional(),
|
|
93
|
+
/** Turn review (comments and build-level verdicts) on or off for the project. */
|
|
94
|
+
reviewEnabled: z.boolean().optional(),
|
|
95
|
+
/** Approvals a build needs before it is accepted when `testing` is off. */
|
|
96
|
+
reviewApprovals: reviewApprovalsSchema.optional(),
|
|
97
|
+
/** Seconds (at least one minimum slice plus grace, 1050, to 86400) the signed Storybook URLs of a render stay valid; null derives it from the stories. */
|
|
98
|
+
storybookUrlTtlSeconds: storybookUrlTtlSchema.nullable().optional()
|
|
47
99
|
}).openapi("ProjectUpdateInput");
|
|
48
100
|
/** OpenAPI schema for a build record. */
|
|
49
101
|
const buildSchema = z.object({
|
|
@@ -61,10 +113,13 @@ const buildSchema = z.object({
|
|
|
61
113
|
changedCount: z.number(),
|
|
62
114
|
approvedCount: z.number(),
|
|
63
115
|
rejectedCount: z.number(),
|
|
116
|
+
inheritedCount: z.number(),
|
|
64
117
|
affectedOnly: z.boolean(),
|
|
65
118
|
baselineSha: z.string().nullable(),
|
|
66
119
|
changedFiles: z.string().nullable(),
|
|
67
120
|
affectedImportPaths: z.string().nullable(),
|
|
121
|
+
/** JSON array of the build's Storybook `.test()` results (id, title, name, status, error); null when none ran. */
|
|
122
|
+
testResults: z.string().nullable().optional(),
|
|
68
123
|
createdAt: z.string(),
|
|
69
124
|
updatedAt: z.string()
|
|
70
125
|
}).openapi("Build");
|
|
@@ -78,6 +133,8 @@ const snapshotSchema = z.object({
|
|
|
78
133
|
storyTitle: z.string(),
|
|
79
134
|
storyImportPath: z.string().nullable(),
|
|
80
135
|
viewportName: z.string(),
|
|
136
|
+
/** Globals JSON the capture's mode applied; null for plain viewports. */
|
|
137
|
+
mode: z.string().nullable().optional(),
|
|
81
138
|
viewportWidth: z.number(),
|
|
82
139
|
viewportHeight: z.number(),
|
|
83
140
|
screenshotPath: z.string(),
|
|
@@ -89,6 +146,8 @@ const snapshotSchema = z.object({
|
|
|
89
146
|
reviewedBy: z.string().nullable(),
|
|
90
147
|
reviewedAt: z.string().nullable(),
|
|
91
148
|
inherited: z.boolean(),
|
|
149
|
+
/** JSON array of the axe violations found on this capture (non-blocking); null when none. */
|
|
150
|
+
a11yViolations: z.string().nullable().optional(),
|
|
92
151
|
createdAt: z.string(),
|
|
93
152
|
updatedAt: z.string()
|
|
94
153
|
}).openapi("Snapshot");
|
|
@@ -133,6 +192,8 @@ const commentSchema = z.object({
|
|
|
133
192
|
projectId: z.string(),
|
|
134
193
|
buildId: z.string(),
|
|
135
194
|
snapshotId: z.string().nullable(),
|
|
195
|
+
/** Storybook story id of a story-anchored comment. */
|
|
196
|
+
storyId: z.string().nullable().optional(),
|
|
136
197
|
userId: z.string().nullable(),
|
|
137
198
|
body: z.string(),
|
|
138
199
|
parentId: z.string().nullable(),
|
|
@@ -143,9 +204,39 @@ const commentSchema = z.object({
|
|
|
143
204
|
/** OpenAPI schema for creating a build comment. */
|
|
144
205
|
const commentCreateSchema = z.object({
|
|
145
206
|
body: z.string().min(1),
|
|
207
|
+
/** Anchor to a snapshot; not together with `storyId`. */
|
|
146
208
|
snapshotId: z.string().optional(),
|
|
209
|
+
/** Anchor to a story of the build; not together with `snapshotId`. */
|
|
210
|
+
storyId: z.string().min(1).optional(),
|
|
147
211
|
parentId: z.string().optional()
|
|
148
212
|
}).openapi("CommentCreateInput");
|
|
213
|
+
/** OpenAPI schema for a build-level review verdict. */
|
|
214
|
+
const buildReviewSchema = z.object({
|
|
215
|
+
id: z.string(),
|
|
216
|
+
buildId: z.string(),
|
|
217
|
+
userId: z.string().nullable(),
|
|
218
|
+
verdict: z.enum(REVIEW_VERDICTS),
|
|
219
|
+
body: z.string().nullable(),
|
|
220
|
+
createdAt: z.string()
|
|
221
|
+
}).openapi("BuildReview");
|
|
222
|
+
/** OpenAPI schema for giving a build a verdict. */
|
|
223
|
+
const buildReviewCreateSchema = z.object({
|
|
224
|
+
verdict: z.enum(REVIEW_VERDICTS),
|
|
225
|
+
body: z.string().max(4e3).optional()
|
|
226
|
+
}).openapi("BuildReviewInput");
|
|
227
|
+
/** OpenAPI schema for a build's review state: the verdicts and what they make of the build. */
|
|
228
|
+
const buildReviewStateSchema = z.object({
|
|
229
|
+
/** Build status now. */
|
|
230
|
+
status: z.enum(BUILD_STATUSES),
|
|
231
|
+
/** Approvals the project requires. */
|
|
232
|
+
approvalsRequired: z.number(),
|
|
233
|
+
/** Approvals among the reviewers' latest verdicts. */
|
|
234
|
+
approvals: z.number(),
|
|
235
|
+
/** Every reviewer's latest verdict. */
|
|
236
|
+
latest: buildReviewSchema.array(),
|
|
237
|
+
/** Every verdict given, oldest first. */
|
|
238
|
+
history: buildReviewSchema.array()
|
|
239
|
+
}).openapi("BuildReviewState");
|
|
149
240
|
/** OpenAPI schema for a project label type. */
|
|
150
241
|
const labelTypeSchema = z.object({
|
|
151
242
|
id: z.string(),
|
|
@@ -218,9 +309,10 @@ const webhookPublicSchema = z.object({
|
|
|
218
309
|
url: z.string(),
|
|
219
310
|
events: z.array(z.string())
|
|
220
311
|
}).openapi("Webhook");
|
|
312
|
+
const webhookUrlBase = z.string().url();
|
|
221
313
|
/** OpenAPI schema for creating a webhook. */
|
|
222
314
|
const webhookCreateSchema = z.object({
|
|
223
|
-
url:
|
|
315
|
+
url: webhookUrlBase.refine((url) => WebhookModel.urlError(url) === null, { message: "URL must use http or https" }),
|
|
224
316
|
events: z.array(z.string().min(1)).optional()
|
|
225
317
|
}).openapi("WebhookCreateInput");
|
|
226
318
|
/** OpenAPI schema for a newly created webhook including its signing secret. */
|
|
@@ -230,22 +322,6 @@ const webhookCreatedSchema = z.object({
|
|
|
230
322
|
events: z.array(z.string()),
|
|
231
323
|
secret: z.string()
|
|
232
324
|
}).openapi("WebhookCreated");
|
|
233
|
-
/** OpenAPI schema for a git status-check configuration. */
|
|
234
|
-
const statusConfigSchema = z.object({
|
|
235
|
-
id: z.string(),
|
|
236
|
-
projectId: z.string(),
|
|
237
|
-
provider: z.string(),
|
|
238
|
-
config: z.record(z.string(), z.unknown()),
|
|
239
|
-
hasToken: z.boolean(),
|
|
240
|
-
createdAt: z.string(),
|
|
241
|
-
updatedAt: z.string()
|
|
242
|
-
}).openapi("StatusConfig");
|
|
243
|
-
/** OpenAPI schema for creating a git status-check configuration. */
|
|
244
|
-
const statusConfigCreateSchema = z.object({
|
|
245
|
-
provider: z.string().min(1),
|
|
246
|
-
config: z.record(z.string(), z.unknown()),
|
|
247
|
-
token: z.string().min(1)
|
|
248
|
-
}).openapi("StatusConfigCreateInput");
|
|
249
325
|
/** OpenAPI schema for a public notification channel (secret omitted). */
|
|
250
326
|
const notificationChannelSchema = z.object({
|
|
251
327
|
id: z.string(),
|
|
@@ -255,6 +331,8 @@ const notificationChannelSchema = z.object({
|
|
|
255
331
|
hasSecret: z.boolean(),
|
|
256
332
|
events: z.array(z.string()),
|
|
257
333
|
enabled: z.boolean(),
|
|
334
|
+
lastError: z.string().nullable(),
|
|
335
|
+
lastErrorAt: z.string().nullable(),
|
|
258
336
|
createdAt: z.string(),
|
|
259
337
|
updatedAt: z.string()
|
|
260
338
|
}).openapi("NotificationChannel");
|
|
@@ -287,6 +365,11 @@ const approveAllResultSchema = z.object({
|
|
|
287
365
|
ok: z.boolean(),
|
|
288
366
|
skipped: z.array(z.string())
|
|
289
367
|
}).openapi("ApproveAllResult");
|
|
368
|
+
/** Group decision result: the snapshots one story/mode decision covered. */
|
|
369
|
+
const groupDecisionResultSchema = z.object({
|
|
370
|
+
ok: z.boolean(),
|
|
371
|
+
snapshotIds: z.array(z.string())
|
|
372
|
+
}).openapi("GroupDecisionResult");
|
|
290
373
|
/** Result of re-diffing a build against the baselines that apply now. */
|
|
291
374
|
const rediffResultSchema = z.object({
|
|
292
375
|
ok: z.boolean(),
|
|
@@ -331,7 +414,42 @@ const notFound = { 404: {
|
|
|
331
414
|
content: { "application/json": { schema: errorSchema } },
|
|
332
415
|
description: "Not found"
|
|
333
416
|
} };
|
|
417
|
+
/** OpenAPI schema for an insight (build triage or project health). */
|
|
418
|
+
const insightSchema = z.object({
|
|
419
|
+
id: z.string(),
|
|
420
|
+
kind: z.enum(["triage", "health"]),
|
|
421
|
+
buildId: z.string().nullable(),
|
|
422
|
+
window: z.string().nullable(),
|
|
423
|
+
status: z.enum([
|
|
424
|
+
"pending",
|
|
425
|
+
"running",
|
|
426
|
+
"done",
|
|
427
|
+
"failed"
|
|
428
|
+
]),
|
|
429
|
+
profile: z.string(),
|
|
430
|
+
model: z.string(),
|
|
431
|
+
promptVersion: z.string(),
|
|
432
|
+
verdict: z.string().nullable(),
|
|
433
|
+
summary: z.string().nullable(),
|
|
434
|
+
output: z.unknown().nullable(),
|
|
435
|
+
meta: z.unknown().nullable(),
|
|
436
|
+
errorCode: z.string().nullable(),
|
|
437
|
+
createdAt: z.string(),
|
|
438
|
+
startedAt: z.string().nullable(),
|
|
439
|
+
finishedAt: z.string().nullable()
|
|
440
|
+
}).openapi("Insight");
|
|
441
|
+
/** Request body to (re)generate a build triage. */
|
|
442
|
+
const insightRequestSchema = z.object({
|
|
443
|
+
task: z.literal("triage").optional(),
|
|
444
|
+
force: z.boolean().optional(),
|
|
445
|
+
profile: z.string().min(1).optional()
|
|
446
|
+
}).openapi("InsightRequest");
|
|
447
|
+
/** Request body to (re)generate a project-health digest. */
|
|
448
|
+
const healthRequestSchema = z.object({
|
|
449
|
+
window: z.string().optional(),
|
|
450
|
+
force: z.boolean().optional()
|
|
451
|
+
}).openapi("HealthInsightRequest");
|
|
334
452
|
//#endregion
|
|
335
|
-
export { approveAllResultSchema, attemptLogSchema, attemptSchema, badRequest, baselineChangedSchema, buildSchema, commentCreateSchema, commentSchema, errorSchema, forbidden, groupMappingCreateSchema, groupMappingSchema, labelTypeCreateSchema, labelTypeSchema, labelTypeUpdateSchema, memberRoleSchema, memberSchema, memberSetSchema, notFound, notificationChannelCreateSchema, notificationChannelSchema, notificationSubscriptionPutSchema, notificationSubscriptionSchema, okSchema, projectCreateSchema, projectSchema, projectUpdateSchema, purgeInputSchema, purgeSchema, rediffResultSchema, snapshotSchema,
|
|
453
|
+
export { approveAllResultSchema, attemptLogSchema, attemptSchema, badRequest, baselineChangedSchema, buildReviewCreateSchema, buildReviewSchema, buildReviewStateSchema, buildSchema, commentCreateSchema, commentSchema, errorSchema, forbidden, groupDecisionResultSchema, groupMappingCreateSchema, groupMappingSchema, healthRequestSchema, insightRequestSchema, insightSchema, labelTypeCreateSchema, labelTypeSchema, labelTypeUpdateSchema, memberRoleSchema, memberSchema, memberSetSchema, notFound, notificationChannelCreateSchema, notificationChannelSchema, notificationSubscriptionPutSchema, notificationSubscriptionSchema, okSchema, projectCreateSchema, projectSchema, projectUpdateSchema, purgeInputSchema, purgeSchema, rediffResultSchema, snapshotSchema, tokenCreateSchema, tokenCreatedSchema, tokenPublicSchema, unauthorized, webhookCreateSchema, webhookCreatedSchema, webhookPublicSchema };
|
|
336
454
|
|
|
337
455
|
//# sourceMappingURL=schemas.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.mjs","names":[],"sources":["../../src/routers/schemas.ts"],"sourcesContent":["import { z } from \"@hono/zod-openapi\";\nimport { BROWSER_NAMES } from \"@storyshelf/core/adapter/capture-runner\";\nimport { BUILD_STATUSES, PROJECT_ROLES, SNAPSHOT_STATUSES } from \"@storyshelf/core/types\";\n\nconst storybookMetaSchema = z.record(z.string(), z.unknown()).nullable().optional();\n\n/** OpenAPI schema for a project record. */\nexport const projectSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n slug: z.string(),\n gitRepository: z.string().nullable(),\n gitDefaultBranch: z.string(),\n pixelThreshold: z.number(),\n maxDiffRatio: z.number(),\n publicBranchRegex: z.string().nullable(),\n storybookMeta: z.string().nullable().optional(),\n executePlay: z.boolean(),\n playTimeoutMs: z.number(),\n // Stored rows predate enum validation, so the response stays a plain string.\n browser: z.string().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"Project\");\n\n/** OpenAPI schema for creating a project. */\nexport const projectCreateSchema = z\n .object({\n name: z.string().min(1),\n gitRepository: z.string().optional(),\n gitDefaultBranch: z.string().optional(),\n storybookMeta: storybookMetaSchema,\n executePlay: z.boolean().optional(),\n playTimeoutMs: z.number().int().min(1000).max(30_000).optional(),\n })\n .openapi(\"ProjectCreateInput\");\n\n/** OpenAPI schema for patching a project. */\nexport const projectUpdateSchema = z\n .object({\n name: z.string().optional(),\n gitRepository: z.string().optional(),\n gitDefaultBranch: z.string().optional(),\n pixelThreshold: z.number().optional(),\n maxDiffRatio: z.number().optional(),\n publicBranchRegex: z.string().nullable().optional(),\n storybookMeta: storybookMetaSchema,\n executePlay: z.boolean().optional(),\n playTimeoutMs: z.number().int().min(1000).max(30_000).optional(),\n browser: z.enum(BROWSER_NAMES).optional(),\n })\n .openapi(\"ProjectUpdateInput\");\n\n/** OpenAPI schema for a build record. */\nexport const buildSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n gitSha: z.string(),\n gitBranch: z.string(),\n isDefault: z.boolean(),\n authorEmail: z.string().nullable(),\n authorName: z.string().nullable(),\n message: z.string().nullable(),\n public: z.boolean(),\n status: z.enum(BUILD_STATUSES),\n snapshotCount: z.number(),\n changedCount: z.number(),\n approvedCount: z.number(),\n rejectedCount: z.number(),\n affectedOnly: z.boolean(),\n baselineSha: z.string().nullable(),\n changedFiles: z.string().nullable(),\n affectedImportPaths: z.string().nullable(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"Build\");\n\n/** OpenAPI schema for a snapshot record. */\nexport const snapshotSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n buildId: z.string(),\n storyId: z.string(),\n storyName: z.string(),\n storyTitle: z.string(),\n storyImportPath: z.string().nullable(),\n viewportName: z.string(),\n viewportWidth: z.number(),\n viewportHeight: z.number(),\n screenshotPath: z.string(),\n diffPath: z.string().nullable(),\n diffPixels: z.number().nullable(),\n diffRatio: z.number().nullable(),\n diffPassed: z.boolean().nullable(),\n status: z.enum(SNAPSHOT_STATUSES),\n reviewedBy: z.string().nullable(),\n reviewedAt: z.string().nullable(),\n inherited: z.boolean(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"Snapshot\");\n\n/** OpenAPI schema for a capture attempt (one run of a build's capture). */\nexport const attemptSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n buildId: z.string(),\n attemptNo: z.number(),\n status: z.enum([\"queued\", \"running\", \"completed\", \"failed\", \"cancelled\"]),\n error: z.string().nullable(),\n reqId: z.string().nullable(),\n storyCount: z.number(),\n failedCount: z.number(),\n queuedAt: z.string(),\n startedAt: z.string().nullable(),\n finishedAt: z.string().nullable(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"CaptureAttempt\");\n\n/** OpenAPI schema for a single capture log line within an attempt. */\nexport const attemptLogSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n buildId: z.string(),\n attemptId: z.string(),\n seq: z.number(),\n level: z.string(),\n message: z.string(),\n fields: z.string().nullable(),\n createdAt: z.string(),\n })\n .openapi(\"CaptureLog\");\n\n/** OpenAPI schema for a build comment. */\nexport const commentSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n buildId: z.string(),\n snapshotId: z.string().nullable(),\n userId: z.string().nullable(),\n body: z.string(),\n parentId: z.string().nullable(),\n resolved: z.boolean(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"Comment\");\n\n/** OpenAPI schema for creating a build comment. */\nexport const commentCreateSchema = z\n .object({\n body: z.string().min(1),\n snapshotId: z.string().optional(),\n parentId: z.string().optional(),\n })\n .openapi(\"CommentCreateInput\");\n\n/** OpenAPI schema for a project label type. */\nexport const labelTypeSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n key: z.string(),\n name: z.string(),\n linkTemplate: z.string().nullable(),\n color: z.string().nullable(),\n createdAt: z.string(),\n })\n .openapi(\"LabelType\");\n\n/** OpenAPI schema for creating a label type. */\nexport const labelTypeCreateSchema = z\n .object({\n key: z.string().min(1),\n name: z.string().min(1),\n linkTemplate: z.string().optional(),\n color: z.string().optional(),\n })\n .openapi(\"LabelTypeCreateInput\");\n\n/** OpenAPI schema for patching a label type. */\nexport const labelTypeUpdateSchema = z\n .object({\n name: z.string().min(1).optional(),\n linkTemplate: z.string().nullable().optional(),\n color: z.string().nullable().optional(),\n })\n .openapi(\"LabelTypeUpdateInput\");\n\n/** OpenAPI schema for a public API token (hash omitted). */\nexport const tokenPublicSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n name: z.string(),\n lastUsedAt: z.string().nullable(),\n createdAt: z.string(),\n })\n .openapi(\"Token\");\n\n/** OpenAPI schema for creating an API token. */\nexport const tokenCreateSchema = z.object({ name: z.string().min(1) }).openapi(\"TokenCreateInput\");\n\n/** OpenAPI schema for a newly created token including its secret value. */\nexport const tokenCreatedSchema = z\n .object({\n name: z.string(),\n token: z.string(),\n })\n .openapi(\"TokenCreated\");\n\n/** OpenAPI schema for a project member record. */\nexport const memberSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n userId: z.string(),\n role: z.enum(PROJECT_ROLES),\n createdAt: z.string(),\n })\n .openapi(\"ProjectMember\");\n\n/** OpenAPI schema for updating a member's role. */\nexport const memberRoleSchema = z\n .object({ role: z.enum(PROJECT_ROLES) })\n .openapi(\"MemberRoleInput\");\n\n/** OpenAPI schema for adding a member to a project. */\nexport const memberSetSchema = z\n .object({\n userId: z.string().min(1),\n role: z.enum(PROJECT_ROLES),\n })\n .openapi(\"MemberSetInput\");\n\n/** OpenAPI schema for an identity-provider group mapping. */\nexport const groupMappingSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n groupName: z.string(),\n role: z.enum(PROJECT_ROLES),\n createdAt: z.string(),\n })\n .openapi(\"GroupMapping\");\n\n/** OpenAPI schema for creating a group mapping. */\nexport const groupMappingCreateSchema = z\n .object({\n groupName: z.string().min(1),\n role: z.enum(PROJECT_ROLES),\n })\n .openapi(\"GroupMappingCreateInput\");\n\n/** OpenAPI schema for a public webhook (secret omitted). */\nexport const webhookPublicSchema = z\n .object({\n id: z.string(),\n url: z.string(),\n events: z.array(z.string()),\n })\n .openapi(\"Webhook\");\n\n/** OpenAPI schema for creating a webhook. */\nexport const webhookCreateSchema = z\n .object({\n // oxlint-disable-next-line typescript/no-deprecated -- z.string().url() kept for zod v3 API compat\n url: z.string().url(),\n events: z.array(z.string().min(1)).optional(),\n })\n .openapi(\"WebhookCreateInput\");\n\n/** OpenAPI schema for a newly created webhook including its signing secret. */\nexport const webhookCreatedSchema = z\n .object({\n id: z.string(),\n url: z.string(),\n events: z.array(z.string()),\n secret: z.string(),\n })\n .openapi(\"WebhookCreated\");\n\n/** OpenAPI schema for a git status-check configuration. */\nexport const statusConfigSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n provider: z.string(),\n config: z.record(z.string(), z.unknown()),\n hasToken: z.boolean(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"StatusConfig\");\n\n/** OpenAPI schema for creating a git status-check configuration. */\nexport const statusConfigCreateSchema = z\n .object({\n provider: z.string().min(1),\n config: z.record(z.string(), z.unknown()),\n token: z.string().min(1),\n })\n .openapi(\"StatusConfigCreateInput\");\n\n/** OpenAPI schema for a public notification channel (secret omitted). */\nexport const notificationChannelSchema = z\n .object({\n id: z.string(),\n projectId: z.string().nullable(),\n provider: z.string(),\n config: z.record(z.string(), z.unknown()),\n hasSecret: z.boolean(),\n events: z.array(z.string()),\n enabled: z.boolean(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"NotificationChannel\");\n\n/** OpenAPI schema for creating a notification channel. */\nexport const notificationChannelCreateSchema = z\n .object({\n provider: z.string().min(1),\n config: z.record(z.string(), z.unknown()),\n secret: z.string().min(1).optional(),\n events: z.array(z.string().min(1)).optional(),\n enabled: z.boolean().optional(),\n })\n .openapi(\"NotificationChannelCreateInput\");\n\n/** OpenAPI schema for a per-user notification subscription. */\nexport const notificationSubscriptionSchema = z\n .object({\n projectId: z.string(),\n userId: z.string(),\n events: z.array(z.string()),\n via: z.array(z.string()),\n enabled: z.boolean(),\n })\n .openapi(\"NotificationSubscription\");\n\n/** OpenAPI schema for setting your own notification subscription. */\nexport const notificationSubscriptionPutSchema = z\n .object({\n events: z.array(z.string().min(1)).optional(),\n via: z.array(z.string().min(1)).optional(),\n enabled: z.boolean().optional(),\n })\n .openapi(\"NotificationSubscriptionPutInput\");\n\n/** OpenAPI schema for a generic `{ ok: true }` acknowledgement. */\nexport const okSchema = z.object({ ok: z.boolean() }).openapi(\"Ok\");\n\n/** Bulk approve result: ids skipped because their baseline changed after the diff. */\nexport const approveAllResultSchema = z\n .object({ ok: z.boolean(), skipped: z.array(z.string()) })\n .openapi(\"ApproveAllResult\");\n\n/** Result of re-diffing a build against the baselines that apply now. */\nexport const rediffResultSchema = z\n .object({\n ok: z.boolean(),\n rediffed: z.number().int(),\n statusChanged: z.number().int(),\n missingScreenshots: z.array(z.string()),\n })\n .openapi(\"RediffResult\");\n\n/** 409 returned when approving a snapshot whose baseline changed after the diff. */\nexport const baselineChangedSchema = z\n .object({\n code: z.literal(\"baseline_changed\"),\n message: z.string(),\n snapshotId: z.string(),\n baselineStatus: z.enum([\"stale\", \"removed\"]),\n })\n .openapi(\"BaselineChanged\");\n\n/** OpenAPI schema for an error response message. */\nexport const errorSchema = z.object({ message: z.string() }).openapi(\"Error\");\n\n/** OpenAPI schema for the retention purge result. */\nexport const purgeSchema = z\n .object({\n removedBuilds: z.number(),\n removedBranches: z.number().optional(),\n removedBaselines: z.number().optional(),\n })\n .openapi(\"PurgeResult\");\n\n/** OpenAPI schema for the retention purge input. */\nexport const purgeInputSchema = z.object({ ttlDays: z.number().optional() }).openapi(\"PurgeInput\");\n\n/** Shared response spec for a 400 Bad Request. */\nexport const badRequest = {\n 400: { content: { \"application/json\": { schema: errorSchema } }, description: \"Bad request\" },\n} as const;\n\n/** Shared response spec for a 401 Unauthorized. */\nexport const unauthorized = {\n 401: { content: { \"application/json\": { schema: errorSchema } }, description: \"Unauthorized\" },\n} as const;\n\n/** Shared response spec for a 403 Forbidden. */\nexport const forbidden = {\n 403: { content: { \"application/json\": { schema: errorSchema } }, description: \"Forbidden\" },\n} as const;\n\n/** Shared response spec for a 404 Not Found. */\nexport const notFound = {\n 404: { content: { \"application/json\": { schema: errorSchema } }, description: \"Not found\" },\n} as const;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schemas.mjs","names":[],"sources":["../../src/routers/schemas.ts"],"sourcesContent":["import { z } from \"@hono/zod-openapi\";\nimport { BROWSER_NAMES, TARGET_NAME_PATTERN } from \"@storyshelf/core/adapter/capture-runner\";\nimport { WebhookModel } from \"@storyshelf/core/models\";\nimport {\n BUILD_STATUSES,\n PROJECT_ROLES,\n REVIEW_VERDICTS,\n SNAPSHOT_STATUSES,\n} from \"@storyshelf/core/types\";\nimport { storybookUrlTtlOverrideError } from \"@storyshelf/core/utils\";\n\n/** A capture target: an engine (`chromium`) or a remote one, `<engine>@<name>` (ADR 0007). */\nconst captureTargetSchema = z\n .string()\n .regex(\n new RegExp(\n `^(?:${BROWSER_NAMES.join(\"|\")})(?:@${TARGET_NAME_PATTERN.source.slice(1, -1)})?$`,\n \"u\",\n ),\n \"Expected an engine (chromium, firefox, webkit, chrome) or <engine>@<name>\",\n );\n\nconst reviewApprovalsSchema = z.number().int().min(1).max(20);\n\n/** Seconds a signed Storybook URL stays valid (ADR 0007, decision 5). */\nconst storybookUrlTtlSchema = z\n .number()\n .int()\n .superRefine((seconds, ctx) => {\n const message = storybookUrlTtlOverrideError(seconds);\n if (message !== undefined) {\n ctx.addIssue({ code: \"custom\", message });\n }\n });\n\nconst storybookMetaSchema = z.record(z.string(), z.unknown()).nullable().optional();\n\n/** OpenAPI schema for a project record. */\nexport const projectSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n slug: z.string(),\n gitRepository: z.string().nullable(),\n gitDefaultBranch: z.string(),\n pixelThreshold: z.number(),\n maxDiffRatio: z.number(),\n publicBranchRegex: z.string().nullable(),\n storybookMeta: z.string().nullable().optional(),\n executePlay: z.boolean(),\n playTimeoutMs: z.number(),\n /** Axe accessibility checks run during capture (default on; results never block a build). */\n runA11y: z.boolean().optional(),\n /** Storybook 10 `.test()` entries run as interaction tests during capture (default off). */\n runTests: z.boolean().optional(),\n // Stored rows predate enum validation, so the response stays a plain string.\n browser: z.string().optional(),\n /** JSON array of capture targets, primary first, primary first; null = just `browser`. */\n browsers: z.string().nullable().optional(),\n /** JSON array of mode names to capture; null = every declared mode. */\n modesAllowlist: z.string().nullable().optional(),\n /** AI profile gate: null/absent = AI off for this project. */\n aiProfile: z.string().nullable().optional(),\n /** Review is on for this project (ADR 0013, decision 1). */\n reviewEnabled: z.boolean().optional(),\n /** Approvals a build needs when `testing` is off. */\n reviewApprovals: z.number().optional(),\n /** Seconds the signed Storybook URLs of a render stay valid; null derives it from the stories. */\n storybookUrlTtlSeconds: z.number().nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"Project\");\n\n/** OpenAPI schema for creating a project. */\nexport const projectCreateSchema = z\n .object({\n name: z.string().min(1),\n gitRepository: z.string().optional(),\n gitDefaultBranch: z.string().optional(),\n storybookMeta: storybookMetaSchema,\n executePlay: z.boolean().optional(),\n playTimeoutMs: z.number().int().min(1000).max(30_000).optional(),\n /** Axe accessibility checks during capture; on when omitted. */\n runA11y: z.boolean().optional(),\n /** Run Storybook 10 `.test()` entries as interaction tests during capture; off when omitted. */\n runTests: z.boolean().optional(),\n reviewEnabled: z.boolean().optional(),\n reviewApprovals: reviewApprovalsSchema.optional(),\n })\n .openapi(\"ProjectCreateInput\");\n\n/** OpenAPI schema for patching a project. */\nexport const projectUpdateSchema = z\n .object({\n name: z.string().optional(),\n gitRepository: z.string().optional(),\n gitDefaultBranch: z.string().optional(),\n pixelThreshold: z.number().optional(),\n maxDiffRatio: z.number().optional(),\n publicBranchRegex: z.string().nullable().optional(),\n storybookMeta: storybookMetaSchema,\n executePlay: z.boolean().optional(),\n playTimeoutMs: z.number().int().min(1000).max(30_000).optional(),\n /** Turn axe accessibility checks during capture on or off (admins). */\n runA11y: z.boolean().optional(),\n /** Turn the Storybook 10 `.test()` runs on or off (admins). */\n runTests: z.boolean().optional(),\n /** Single capture target; clears `browsers`. */\n browser: captureTargetSchema.optional(),\n /** Capture targets, primary first (max 3); null returns to single `browser`. */\n browsers: z.array(captureTargetSchema).min(1).max(3).nullable().optional(),\n /** Mode names to capture; null runs every declared mode. */\n modesAllowlist: z.array(z.string().min(1)).max(50).nullable().optional(),\n /** Site admins only: a configured AI profile name, or null to turn AI off. */\n aiProfile: z.string().min(1).nullable().optional(),\n /** Turn review (comments and build-level verdicts) on or off for the project. */\n reviewEnabled: z.boolean().optional(),\n /** Approvals a build needs before it is accepted when `testing` is off. */\n reviewApprovals: reviewApprovalsSchema.optional(),\n /** Seconds (at least one minimum slice plus grace, 1050, to 86400) the signed Storybook URLs of a render stay valid; null derives it from the stories. */\n storybookUrlTtlSeconds: storybookUrlTtlSchema.nullable().optional(),\n })\n .openapi(\"ProjectUpdateInput\");\n\n/** OpenAPI schema for a build record. */\nexport const buildSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n gitSha: z.string(),\n gitBranch: z.string(),\n isDefault: z.boolean(),\n authorEmail: z.string().nullable(),\n authorName: z.string().nullable(),\n message: z.string().nullable(),\n public: z.boolean(),\n status: z.enum(BUILD_STATUSES),\n snapshotCount: z.number(),\n changedCount: z.number(),\n approvedCount: z.number(),\n rejectedCount: z.number(),\n inheritedCount: z.number(),\n affectedOnly: z.boolean(),\n baselineSha: z.string().nullable(),\n changedFiles: z.string().nullable(),\n affectedImportPaths: z.string().nullable(),\n /** JSON array of the build's Storybook `.test()` results (id, title, name, status, error); null when none ran. */\n testResults: z.string().nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"Build\");\n\n/** OpenAPI schema for a snapshot record. */\nexport const snapshotSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n buildId: z.string(),\n storyId: z.string(),\n storyName: z.string(),\n storyTitle: z.string(),\n storyImportPath: z.string().nullable(),\n viewportName: z.string(),\n /** Globals JSON the capture's mode applied; null for plain viewports. */\n mode: z.string().nullable().optional(),\n viewportWidth: z.number(),\n viewportHeight: z.number(),\n screenshotPath: z.string(),\n diffPath: z.string().nullable(),\n diffPixels: z.number().nullable(),\n diffRatio: z.number().nullable(),\n diffPassed: z.boolean().nullable(),\n status: z.enum(SNAPSHOT_STATUSES),\n reviewedBy: z.string().nullable(),\n reviewedAt: z.string().nullable(),\n inherited: z.boolean(),\n /** JSON array of the axe violations found on this capture (non-blocking); null when none. */\n a11yViolations: z.string().nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"Snapshot\");\n\n/** OpenAPI schema for a capture attempt (one run of a build's capture). */\nexport const attemptSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n buildId: z.string(),\n attemptNo: z.number(),\n status: z.enum([\"queued\", \"running\", \"completed\", \"failed\", \"cancelled\"]),\n error: z.string().nullable(),\n reqId: z.string().nullable(),\n storyCount: z.number(),\n failedCount: z.number(),\n queuedAt: z.string(),\n startedAt: z.string().nullable(),\n finishedAt: z.string().nullable(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"CaptureAttempt\");\n\n/** OpenAPI schema for a single capture log line within an attempt. */\nexport const attemptLogSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n buildId: z.string(),\n attemptId: z.string(),\n seq: z.number(),\n level: z.string(),\n message: z.string(),\n fields: z.string().nullable(),\n createdAt: z.string(),\n })\n .openapi(\"CaptureLog\");\n\n/** OpenAPI schema for a build comment. */\nexport const commentSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n buildId: z.string(),\n snapshotId: z.string().nullable(),\n /** Storybook story id of a story-anchored comment. */\n storyId: z.string().nullable().optional(),\n userId: z.string().nullable(),\n body: z.string(),\n parentId: z.string().nullable(),\n resolved: z.boolean(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"Comment\");\n\n/** OpenAPI schema for creating a build comment. */\nexport const commentCreateSchema = z\n .object({\n body: z.string().min(1),\n /** Anchor to a snapshot; not together with `storyId`. */\n snapshotId: z.string().optional(),\n /** Anchor to a story of the build; not together with `snapshotId`. */\n storyId: z.string().min(1).optional(),\n parentId: z.string().optional(),\n })\n .openapi(\"CommentCreateInput\");\n\n/** OpenAPI schema for a build-level review verdict. */\nexport const buildReviewSchema = z\n .object({\n id: z.string(),\n buildId: z.string(),\n userId: z.string().nullable(),\n verdict: z.enum(REVIEW_VERDICTS),\n body: z.string().nullable(),\n createdAt: z.string(),\n })\n .openapi(\"BuildReview\");\n\n/** OpenAPI schema for giving a build a verdict. */\nexport const buildReviewCreateSchema = z\n .object({\n verdict: z.enum(REVIEW_VERDICTS),\n body: z.string().max(4000).optional(),\n })\n .openapi(\"BuildReviewInput\");\n\n/** OpenAPI schema for a build's review state: the verdicts and what they make of the build. */\nexport const buildReviewStateSchema = z\n .object({\n /** Build status now. */\n status: z.enum(BUILD_STATUSES),\n /** Approvals the project requires. */\n approvalsRequired: z.number(),\n /** Approvals among the reviewers' latest verdicts. */\n approvals: z.number(),\n /** Every reviewer's latest verdict. */\n latest: buildReviewSchema.array(),\n /** Every verdict given, oldest first. */\n history: buildReviewSchema.array(),\n })\n .openapi(\"BuildReviewState\");\n\n/** OpenAPI schema for a project label type. */\nexport const labelTypeSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n key: z.string(),\n name: z.string(),\n linkTemplate: z.string().nullable(),\n color: z.string().nullable(),\n createdAt: z.string(),\n })\n .openapi(\"LabelType\");\n\n/** OpenAPI schema for creating a label type. */\nexport const labelTypeCreateSchema = z\n .object({\n key: z.string().min(1),\n name: z.string().min(1),\n linkTemplate: z.string().optional(),\n color: z.string().optional(),\n })\n .openapi(\"LabelTypeCreateInput\");\n\n/** OpenAPI schema for patching a label type. */\nexport const labelTypeUpdateSchema = z\n .object({\n name: z.string().min(1).optional(),\n linkTemplate: z.string().nullable().optional(),\n color: z.string().nullable().optional(),\n })\n .openapi(\"LabelTypeUpdateInput\");\n\n/** OpenAPI schema for a public API token (hash omitted). */\nexport const tokenPublicSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n name: z.string(),\n lastUsedAt: z.string().nullable(),\n createdAt: z.string(),\n })\n .openapi(\"Token\");\n\n/** OpenAPI schema for creating an API token. */\nexport const tokenCreateSchema = z.object({ name: z.string().min(1) }).openapi(\"TokenCreateInput\");\n\n/** OpenAPI schema for a newly created token including its secret value. */\nexport const tokenCreatedSchema = z\n .object({\n name: z.string(),\n token: z.string(),\n })\n .openapi(\"TokenCreated\");\n\n/** OpenAPI schema for a project member record. */\nexport const memberSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n userId: z.string(),\n role: z.enum(PROJECT_ROLES),\n createdAt: z.string(),\n })\n .openapi(\"ProjectMember\");\n\n/** OpenAPI schema for updating a member's role. */\nexport const memberRoleSchema = z\n .object({ role: z.enum(PROJECT_ROLES) })\n .openapi(\"MemberRoleInput\");\n\n/** OpenAPI schema for adding a member to a project. */\nexport const memberSetSchema = z\n .object({\n userId: z.string().min(1),\n role: z.enum(PROJECT_ROLES),\n })\n .openapi(\"MemberSetInput\");\n\n/** OpenAPI schema for an identity-provider group mapping. */\nexport const groupMappingSchema = z\n .object({\n id: z.string(),\n projectId: z.string(),\n groupName: z.string(),\n role: z.enum(PROJECT_ROLES),\n createdAt: z.string(),\n })\n .openapi(\"GroupMapping\");\n\n/** OpenAPI schema for creating a group mapping. */\nexport const groupMappingCreateSchema = z\n .object({\n groupName: z.string().min(1),\n role: z.enum(PROJECT_ROLES),\n })\n .openapi(\"GroupMappingCreateInput\");\n\n/** OpenAPI schema for a public webhook (secret omitted). */\nexport const webhookPublicSchema = z\n .object({\n id: z.string(),\n url: z.string(),\n events: z.array(z.string()),\n })\n .openapi(\"Webhook\");\n\n// oxlint-disable-next-line typescript/no-deprecated -- z.string().url() kept for zod v3 API compat\nconst webhookUrlBase = z.string().url();\n\n/** OpenAPI schema for creating a webhook. */\nexport const webhookCreateSchema = z\n .object({\n url: webhookUrlBase.refine((url) => WebhookModel.urlError(url) === null, {\n message: \"URL must use http or https\",\n }),\n events: z.array(z.string().min(1)).optional(),\n })\n .openapi(\"WebhookCreateInput\");\n\n/** OpenAPI schema for a newly created webhook including its signing secret. */\nexport const webhookCreatedSchema = z\n .object({\n id: z.string(),\n url: z.string(),\n events: z.array(z.string()),\n secret: z.string(),\n })\n .openapi(\"WebhookCreated\");\n\n/** OpenAPI schema for a public notification channel (secret omitted). */\nexport const notificationChannelSchema = z\n .object({\n id: z.string(),\n projectId: z.string().nullable(),\n provider: z.string(),\n config: z.record(z.string(), z.unknown()),\n hasSecret: z.boolean(),\n events: z.array(z.string()),\n enabled: z.boolean(),\n lastError: z.string().nullable(),\n lastErrorAt: z.string().nullable(),\n createdAt: z.string(),\n updatedAt: z.string(),\n })\n .openapi(\"NotificationChannel\");\n\n/** OpenAPI schema for creating a notification channel. */\nexport const notificationChannelCreateSchema = z\n .object({\n provider: z.string().min(1),\n config: z.record(z.string(), z.unknown()),\n secret: z.string().min(1).optional(),\n events: z.array(z.string().min(1)).optional(),\n enabled: z.boolean().optional(),\n })\n .openapi(\"NotificationChannelCreateInput\");\n\n/** OpenAPI schema for a per-user notification subscription. */\nexport const notificationSubscriptionSchema = z\n .object({\n projectId: z.string(),\n userId: z.string(),\n events: z.array(z.string()),\n via: z.array(z.string()),\n enabled: z.boolean(),\n })\n .openapi(\"NotificationSubscription\");\n\n/** OpenAPI schema for setting your own notification subscription. */\nexport const notificationSubscriptionPutSchema = z\n .object({\n events: z.array(z.string().min(1)).optional(),\n via: z.array(z.string().min(1)).optional(),\n enabled: z.boolean().optional(),\n })\n .openapi(\"NotificationSubscriptionPutInput\");\n\n/** OpenAPI schema for a generic `{ ok: true }` acknowledgement. */\nexport const okSchema = z.object({ ok: z.boolean() }).openapi(\"Ok\");\n\n/** Bulk approve result: ids skipped because their baseline changed after the diff. */\nexport const approveAllResultSchema = z\n .object({ ok: z.boolean(), skipped: z.array(z.string()) })\n .openapi(\"ApproveAllResult\");\n\n/** Group decision result: the snapshots one story/mode decision covered. */\nexport const groupDecisionResultSchema = z\n .object({ ok: z.boolean(), snapshotIds: z.array(z.string()) })\n .openapi(\"GroupDecisionResult\");\n\n/** Result of re-diffing a build against the baselines that apply now. */\nexport const rediffResultSchema = z\n .object({\n ok: z.boolean(),\n rediffed: z.number().int(),\n statusChanged: z.number().int(),\n missingScreenshots: z.array(z.string()),\n })\n .openapi(\"RediffResult\");\n\n/** 409 returned when approving a snapshot whose baseline changed after the diff. */\nexport const baselineChangedSchema = z\n .object({\n code: z.literal(\"baseline_changed\"),\n message: z.string(),\n snapshotId: z.string(),\n baselineStatus: z.enum([\"stale\", \"removed\"]),\n })\n .openapi(\"BaselineChanged\");\n\n/** OpenAPI schema for an error response message. */\nexport const errorSchema = z.object({ message: z.string() }).openapi(\"Error\");\n\n/** OpenAPI schema for the retention purge result. */\nexport const purgeSchema = z\n .object({\n removedBuilds: z.number(),\n removedBranches: z.number().optional(),\n removedBaselines: z.number().optional(),\n })\n .openapi(\"PurgeResult\");\n\n/** OpenAPI schema for the retention purge input. */\nexport const purgeInputSchema = z.object({ ttlDays: z.number().optional() }).openapi(\"PurgeInput\");\n\n/** Shared response spec for a 400 Bad Request. */\nexport const badRequest = {\n 400: { content: { \"application/json\": { schema: errorSchema } }, description: \"Bad request\" },\n} as const;\n\n/** Shared response spec for a 401 Unauthorized. */\nexport const unauthorized = {\n 401: { content: { \"application/json\": { schema: errorSchema } }, description: \"Unauthorized\" },\n} as const;\n\n/** Shared response spec for a 403 Forbidden. */\nexport const forbidden = {\n 403: { content: { \"application/json\": { schema: errorSchema } }, description: \"Forbidden\" },\n} as const;\n\n/** Shared response spec for a 404 Not Found. */\nexport const notFound = {\n 404: { content: { \"application/json\": { schema: errorSchema } }, description: \"Not found\" },\n} as const;\n\n/** OpenAPI schema for an insight (build triage or project health). */\nexport const insightSchema = z\n .object({\n id: z.string(),\n kind: z.enum([\"triage\", \"health\"]),\n buildId: z.string().nullable(),\n window: z.string().nullable(),\n status: z.enum([\"pending\", \"running\", \"done\", \"failed\"]),\n profile: z.string(),\n model: z.string(),\n promptVersion: z.string(),\n verdict: z.string().nullable(),\n summary: z.string().nullable(),\n output: z.unknown().nullable(),\n meta: z.unknown().nullable(),\n errorCode: z.string().nullable(),\n createdAt: z.string(),\n startedAt: z.string().nullable(),\n finishedAt: z.string().nullable(),\n })\n .openapi(\"Insight\");\n\n/** Request body to (re)generate a build triage. */\nexport const insightRequestSchema = z\n .object({\n task: z.literal(\"triage\").optional(),\n force: z.boolean().optional(),\n profile: z.string().min(1).optional(),\n })\n .openapi(\"InsightRequest\");\n\n/** Request body to (re)generate a project-health digest. */\nexport const healthRequestSchema = z\n .object({ window: z.string().optional(), force: z.boolean().optional() })\n .openapi(\"HealthInsightRequest\");\n"],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { credentialKeys } from "../credential-keys.mjs";
|
|
5
|
+
import { getStore } from "../store.mjs";
|
|
6
|
+
import { NotificationChannelModel, WebhookModel } from "@storyshelf/core/models";
|
|
7
|
+
//#region src/routers/scoped-models.ts
|
|
8
|
+
/** Models that encrypt secrets at rest, bound to the current request's db and server secret. */
|
|
9
|
+
/** Webhook model for the current request. */
|
|
10
|
+
function webhookModel() {
|
|
11
|
+
const { db, config } = getStore();
|
|
12
|
+
return new WebhookModel(db, void 0, credentialKeys(config));
|
|
13
|
+
}
|
|
14
|
+
/** Notification-channel model for the current request. */
|
|
15
|
+
function notificationChannelModel() {
|
|
16
|
+
const { db, config } = getStore();
|
|
17
|
+
return new NotificationChannelModel(db, void 0, credentialKeys(config));
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { notificationChannelModel, webhookModel };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=scoped-models.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoped-models.mjs","names":[],"sources":["../../src/routers/scoped-models.ts"],"sourcesContent":["import { NotificationChannelModel, WebhookModel } from \"@storyshelf/core/models\";\nimport { credentialKeys } from \"../credential-keys.ts\";\nimport { getStore } from \"../store.ts\";\n\n/** Models that encrypt secrets at rest, bound to the current request's db and server secret. */\n\n/** Webhook model for the current request. */\nexport function webhookModel(): WebhookModel {\n const { db, config } = getStore();\n return new WebhookModel(db, undefined, credentialKeys(config));\n}\n\n/** Notification-channel model for the current request. */\nexport function notificationChannelModel(): NotificationChannelModel {\n const { db, config } = getStore();\n return new NotificationChannelModel(db, undefined, credentialKeys(config));\n}\n"],"mappings":";;;;;;;;;AAOA,SAAgB,eAA6B;CAC3C,MAAM,EAAE,IAAI,WAAW,SAAS;CAChC,OAAO,IAAI,aAAa,IAAI,KAAA,GAAW,eAAe,MAAM,CAAC;AAC/D;;AAGA,SAAgB,2BAAqD;CACnE,MAAM,EAAE,IAAI,WAAW,SAAS;CAChC,OAAO,IAAI,yBAAyB,IAAI,KAAA,GAAW,eAAe,MAAM,CAAC;AAC3E"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { getStore } from "../store.mjs";
|
|
5
|
+
import { requireSiteAdmin } from "./helpers.mjs";
|
|
6
|
+
import { hxRedirect } from "./htmx.mjs";
|
|
7
|
+
import { flash } from "./flash.mjs";
|
|
8
|
+
import { asString, findProject, renderSettingsPage } from "./settings.handlers.mjs";
|
|
9
|
+
import { ProjectModel } from "@storyshelf/core/models";
|
|
10
|
+
//#region src/routers/settings-ai.ts
|
|
11
|
+
/** Register the project AI settings tab (site admins set the profile gate). */
|
|
12
|
+
function registerAiSettings(app) {
|
|
13
|
+
app.get("/projects/:slug/settings/ai", async (c) => c.html(await renderSettingsPage(c, "ai")));
|
|
14
|
+
app.post("/projects/:slug/settings/ai", handleAiUpdate);
|
|
15
|
+
}
|
|
16
|
+
/** Error text for an unusable choice, or null when it is allowed. */
|
|
17
|
+
function profileError(ai, requested) {
|
|
18
|
+
if (!ai) return "AI is not configured";
|
|
19
|
+
return requested !== "" && !ai.profileNames().includes(requested) ? `Unknown profile "${requested}"` : null;
|
|
20
|
+
}
|
|
21
|
+
async function handleAiUpdate(c) {
|
|
22
|
+
requireSiteAdmin(c);
|
|
23
|
+
const { ai, db } = getStore();
|
|
24
|
+
const project = await findProject(c.req.param("slug") ?? "");
|
|
25
|
+
const requested = asString((await c.req.formData()).get("aiProfile")) ?? "";
|
|
26
|
+
const error = profileError(ai, requested);
|
|
27
|
+
if (error) return c.html(await renderSettingsPage(c, "ai", { globalError: error }), 400);
|
|
28
|
+
await new ProjectModel(db).update(project.id, { aiProfile: requested === "" ? null : requested });
|
|
29
|
+
flash(c, requested === "" ? "AI turned off for this project" : "AI profile saved");
|
|
30
|
+
return hxRedirect(c, `/projects/${project.slug}/settings/ai`);
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { registerAiSettings };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=settings-ai.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-ai.mjs","names":[],"sources":["../../src/routers/settings-ai.ts"],"sourcesContent":["import type { Ai } from \"@storyshelf/core/ai\";\nimport { ProjectModel } from \"@storyshelf/core/models\";\nimport type { Context } from \"hono\";\nimport type { ShelfRouter } from \"../app-types.ts\";\nimport { getStore } from \"../store.ts\";\nimport { flash } from \"./flash.ts\";\nimport { requireSiteAdmin } from \"./helpers.ts\";\nimport { hxRedirect } from \"./htmx.ts\";\nimport { asString, findProject, renderSettingsPage } from \"./settings.handlers.ts\";\n\n/** Register the project AI settings tab (site admins set the profile gate). */\nexport function registerAiSettings(app: ShelfRouter): void {\n app.get(\"/projects/:slug/settings/ai\", async (c) => c.html(await renderSettingsPage(c, \"ai\")));\n app.post(\"/projects/:slug/settings/ai\", handleAiUpdate);\n}\n\n/** Error text for an unusable choice, or null when it is allowed. */\nfunction profileError(ai: Ai | undefined, requested: string): string | null {\n if (!ai) {\n return \"AI is not configured\";\n }\n return requested !== \"\" && !ai.profileNames().includes(requested)\n ? `Unknown profile \"${requested}\"`\n : null;\n}\n\nasync function handleAiUpdate(c: Context): Promise<Response> {\n requireSiteAdmin(c);\n const { ai, db } = getStore();\n const project = await findProject(c.req.param(\"slug\") ?? \"\");\n const requested = asString((await c.req.formData()).get(\"aiProfile\")) ?? \"\";\n const error = profileError(ai, requested);\n if (error) {\n return c.html(await renderSettingsPage(c, \"ai\", { globalError: error }), 400);\n }\n await new ProjectModel(db).update(project.id, { aiProfile: requested === \"\" ? null : requested });\n flash(c, requested === \"\" ? \"AI turned off for this project\" : \"AI profile saved\");\n return hxRedirect(c, `/projects/${project.slug}/settings/ai`);\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,mBAAmB,KAAwB;CACzD,IAAI,IAAI,+BAA+B,OAAO,MAAM,EAAE,KAAK,MAAM,mBAAmB,GAAG,IAAI,CAAC,CAAC;CAC7F,IAAI,KAAK,+BAA+B,cAAc;AACxD;;AAGA,SAAS,aAAa,IAAoB,WAAkC;CAC1E,IAAI,CAAC,IACH,OAAO;CAET,OAAO,cAAc,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,SAAS,SAAS,IAC5D,oBAAoB,UAAU,KAC9B;AACN;AAEA,eAAe,eAAe,GAA+B;CAC3D,iBAAiB,CAAC;CAClB,MAAM,EAAE,IAAI,OAAO,SAAS;CAC5B,MAAM,UAAU,MAAM,YAAY,EAAE,IAAI,MAAM,MAAM,KAAK,EAAE;CAC3D,MAAM,YAAY,UAAU,MAAM,EAAE,IAAI,SAAS,EAAA,CAAG,IAAI,WAAW,CAAC,KAAK;CACzE,MAAM,QAAQ,aAAa,IAAI,SAAS;CACxC,IAAI,OACF,OAAO,EAAE,KAAK,MAAM,mBAAmB,GAAG,MAAM,EAAE,aAAa,MAAM,CAAC,GAAG,GAAG;CAE9E,MAAM,IAAI,aAAa,EAAE,CAAC,CAAC,OAAO,QAAQ,IAAI,EAAE,WAAW,cAAc,KAAK,OAAO,UAAU,CAAC;CAChG,MAAM,GAAG,cAAc,KAAK,mCAAmC,kBAAkB;CACjF,OAAO,WAAW,GAAG,aAAa,QAAQ,KAAK,aAAa;AAC9D"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { getStore } from "../store.mjs";
|
|
5
|
+
import { assertTargetsSelectable } from "../targets.mjs";
|
|
6
|
+
import { hxRedirect } from "./htmx.mjs";
|
|
7
|
+
import { flash } from "./flash.mjs";
|
|
8
|
+
import { toProjectPatch } from "./capture-config.mjs";
|
|
9
|
+
import { asString, findProject, renderSettingsPage } from "./settings.handlers.mjs";
|
|
10
|
+
import { storybookUrlTtlOverrideError } from "@storyshelf/core/utils";
|
|
11
|
+
import { resolveBrowsers } from "@storyshelf/core/capture";
|
|
12
|
+
import { ProjectModel } from "@storyshelf/core/models";
|
|
13
|
+
import { HTTPException } from "hono/http-exception";
|
|
14
|
+
import { isCaptureTarget } from "@storyshelf/core/adapter/capture-runner";
|
|
15
|
+
//#region src/routers/settings-capture.ts
|
|
16
|
+
/** Capture settings: browsers (primary + extras), the mode allowlist and the signed URL lifetime. */
|
|
17
|
+
function registerCaptureSettings(app) {
|
|
18
|
+
app.get("/projects/:slug/settings/capture", async (c) => c.html(await renderSettingsPage(c, "capture")));
|
|
19
|
+
app.post("/projects/:slug/settings/capture", handleCaptureUpdate);
|
|
20
|
+
}
|
|
21
|
+
const EXTRA_PREFIX = "extra_";
|
|
22
|
+
/** Primary target first, then the ticked extras; throws 400 when the form is malformed. */
|
|
23
|
+
function readBrowsers(form) {
|
|
24
|
+
const primary = asString(form.get("browser")) ?? "chromium";
|
|
25
|
+
if (!isCaptureTarget(primary)) throw badBrowser(primary);
|
|
26
|
+
const extras = [...form.entries()].flatMap(([key, value]) => key.startsWith(EXTRA_PREFIX) && value === key.slice(6) ? [key.slice(6)] : []);
|
|
27
|
+
const bad = extras.find((extra) => !isCaptureTarget(extra));
|
|
28
|
+
if (bad !== void 0) throw badBrowser(bad);
|
|
29
|
+
return [.../* @__PURE__ */ new Set([primary, ...extras])];
|
|
30
|
+
}
|
|
31
|
+
function badBrowser(value) {
|
|
32
|
+
return new HTTPException(400, { message: `Unknown browser "${value}"` });
|
|
33
|
+
}
|
|
34
|
+
/** Mode names, one per line (blank lines and surrounding space ignored). */
|
|
35
|
+
function readAllowlist(form) {
|
|
36
|
+
const lines = (asString(form.get("modesAllowlist")) ?? "").split("\n").map((line) => line.trim()).filter((line) => line !== "");
|
|
37
|
+
return lines.length > 0 ? lines : null;
|
|
38
|
+
}
|
|
39
|
+
/** Seconds of the signed Storybook URL lifetime; empty derives it from the stories (null). */
|
|
40
|
+
function readUrlTtl(form) {
|
|
41
|
+
const raw = asString(form.get("storybookUrlTtlSeconds"));
|
|
42
|
+
if (!raw) return null;
|
|
43
|
+
const seconds = Number(raw);
|
|
44
|
+
const message = storybookUrlTtlOverrideError(seconds);
|
|
45
|
+
if (message !== void 0) throw new HTTPException(400, { message });
|
|
46
|
+
return seconds;
|
|
47
|
+
}
|
|
48
|
+
async function reject(c, message) {
|
|
49
|
+
return c.html(await renderSettingsPage(c, "capture", { globalError: message }) ?? "", 400);
|
|
50
|
+
}
|
|
51
|
+
async function saveCapture(project, form, browsers) {
|
|
52
|
+
const patch = toProjectPatch({
|
|
53
|
+
browsers: browsers.length > 1 ? browsers : null,
|
|
54
|
+
browser: browsers[0],
|
|
55
|
+
modesAllowlist: readAllowlist(form),
|
|
56
|
+
storybookUrlTtlSeconds: readUrlTtl(form)
|
|
57
|
+
});
|
|
58
|
+
await new ProjectModel(getStore().db).update(project.id, patch);
|
|
59
|
+
}
|
|
60
|
+
async function handleCaptureUpdate(c) {
|
|
61
|
+
const project = await findProject(c.req.param("slug") ?? "");
|
|
62
|
+
const form = await c.req.formData();
|
|
63
|
+
try {
|
|
64
|
+
const browsers = readBrowsers(form);
|
|
65
|
+
await assertTargetsSelectable(browsers, resolveBrowsers(project));
|
|
66
|
+
await saveCapture(project, form, browsers);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
if (error instanceof HTTPException) return await reject(c, error.message);
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
flash(c, "Capture settings saved");
|
|
72
|
+
return hxRedirect(c, `/projects/${project.slug}/settings/capture`);
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { registerCaptureSettings };
|
|
76
|
+
|
|
77
|
+
//# sourceMappingURL=settings-capture.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-capture.mjs","names":[],"sources":["../../src/routers/settings-capture.ts"],"sourcesContent":["import { isCaptureTarget, type CaptureTarget } from \"@storyshelf/core/adapter/capture-runner\";\nimport { resolveBrowsers } from \"@storyshelf/core/capture\";\nimport { ProjectModel } from \"@storyshelf/core/models\";\nimport type { Project } from \"@storyshelf/core/schema\";\nimport { storybookUrlTtlOverrideError } from \"@storyshelf/core/utils\";\nimport type { Context } from \"hono\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { ShelfRouter } from \"../app-types.ts\";\nimport { getStore } from \"../store.ts\";\nimport { assertTargetsSelectable } from \"../targets.ts\";\nimport { toProjectPatch } from \"./capture-config.ts\";\nimport { flash } from \"./flash.ts\";\nimport { hxRedirect } from \"./htmx.ts\";\nimport { asString, findProject, renderSettingsPage } from \"./settings.handlers.ts\";\n\n/** Capture settings: browsers (primary + extras), the mode allowlist and the signed URL lifetime. */\nexport function registerCaptureSettings(app: ShelfRouter): void {\n app.get(\"/projects/:slug/settings/capture\", async (c) =>\n c.html(await renderSettingsPage(c, \"capture\")),\n );\n app.post(\"/projects/:slug/settings/capture\", handleCaptureUpdate);\n}\n\nconst EXTRA_PREFIX = \"extra_\";\n\n/** Primary target first, then the ticked extras; throws 400 when the form is malformed. */\nfunction readBrowsers(form: FormData): CaptureTarget[] {\n const primary = asString(form.get(\"browser\")) ?? \"chromium\";\n if (!isCaptureTarget(primary)) throw badBrowser(primary);\n const extras = [...form.entries()].flatMap(([key, value]) =>\n key.startsWith(EXTRA_PREFIX) && value === key.slice(EXTRA_PREFIX.length)\n ? [key.slice(EXTRA_PREFIX.length)]\n : [],\n );\n const bad = extras.find((extra) => !isCaptureTarget(extra));\n if (bad !== undefined) throw badBrowser(bad);\n return [...new Set([primary, ...(extras as CaptureTarget[])])];\n}\n\nfunction badBrowser(value: string): HTTPException {\n return new HTTPException(400, { message: `Unknown browser \"${value}\"` });\n}\n\n/** Mode names, one per line (blank lines and surrounding space ignored). */\nfunction readAllowlist(form: FormData): string[] | null {\n const lines = (asString(form.get(\"modesAllowlist\")) ?? \"\")\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line !== \"\");\n return lines.length > 0 ? lines : null;\n}\n\n/** Seconds of the signed Storybook URL lifetime; empty derives it from the stories (null). */\nfunction readUrlTtl(form: FormData): number | null {\n const raw = asString(form.get(\"storybookUrlTtlSeconds\"));\n if (!raw) return null;\n const seconds = Number(raw);\n const message = storybookUrlTtlOverrideError(seconds);\n if (message !== undefined) {\n throw new HTTPException(400, { message });\n }\n return seconds;\n}\n\nasync function reject(c: Context, message: string): Promise<Response> {\n return c.html((await renderSettingsPage(c, \"capture\", { globalError: message })) ?? \"\", 400);\n}\n\nasync function saveCapture(\n project: Project,\n form: FormData,\n browsers: CaptureTarget[],\n): Promise<void> {\n const patch = toProjectPatch({\n browsers: browsers.length > 1 ? browsers : null,\n browser: browsers[0],\n modesAllowlist: readAllowlist(form),\n storybookUrlTtlSeconds: readUrlTtl(form),\n });\n await new ProjectModel(getStore().db).update(project.id, patch);\n}\n\nasync function handleCaptureUpdate(c: Context): Promise<Response> {\n const project = await findProject(c.req.param(\"slug\") ?? \"\");\n const form = await c.req.formData();\n try {\n const browsers = readBrowsers(form);\n await assertTargetsSelectable(browsers, resolveBrowsers(project));\n await saveCapture(project, form, browsers);\n } catch (error) {\n if (error instanceof HTTPException) return await reject(c, error.message);\n throw error;\n }\n flash(c, \"Capture settings saved\");\n return hxRedirect(c, `/projects/${project.slug}/settings/capture`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,SAAgB,wBAAwB,KAAwB;CAC9D,IAAI,IAAI,oCAAoC,OAAO,MACjD,EAAE,KAAK,MAAM,mBAAmB,GAAG,SAAS,CAAC,CAC/C;CACA,IAAI,KAAK,oCAAoC,mBAAmB;AAClE;AAEA,MAAM,eAAe;;AAGrB,SAAS,aAAa,MAAiC;CACrD,MAAM,UAAU,SAAS,KAAK,IAAI,SAAS,CAAC,KAAK;CACjD,IAAI,CAAC,gBAAgB,OAAO,GAAG,MAAM,WAAW,OAAO;CACvD,MAAM,SAAS,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,WAChD,IAAI,WAAW,YAAY,KAAK,UAAU,IAAI,MAAM,CAAmB,IACnE,CAAC,IAAI,MAAM,CAAmB,CAAC,IAC/B,CAAC,CACP;CACA,MAAM,MAAM,OAAO,MAAM,UAAU,CAAC,gBAAgB,KAAK,CAAC;CAC1D,IAAI,QAAQ,KAAA,GAAW,MAAM,WAAW,GAAG;CAC3C,OAAO,CAAC,mBAAG,IAAI,IAAI,CAAC,SAAS,GAAI,MAA0B,CAAC,CAAC;AAC/D;AAEA,SAAS,WAAW,OAA8B;CAChD,OAAO,IAAI,cAAc,KAAK,EAAE,SAAS,oBAAoB,MAAM,GAAG,CAAC;AACzE;;AAGA,SAAS,cAAc,MAAiC;CACtD,MAAM,SAAS,SAAS,KAAK,IAAI,gBAAgB,CAAC,KAAK,GAAA,CACpD,MAAM,IAAI,CAAC,CACX,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,CAC1B,QAAQ,SAAS,SAAS,EAAE;CAC/B,OAAO,MAAM,SAAS,IAAI,QAAQ;AACpC;;AAGA,SAAS,WAAW,MAA+B;CACjD,MAAM,MAAM,SAAS,KAAK,IAAI,wBAAwB,CAAC;CACvD,IAAI,CAAC,KAAK,OAAO;CACjB,MAAM,UAAU,OAAO,GAAG;CAC1B,MAAM,UAAU,6BAA6B,OAAO;CACpD,IAAI,YAAY,KAAA,GACd,MAAM,IAAI,cAAc,KAAK,EAAE,QAAQ,CAAC;CAE1C,OAAO;AACT;AAEA,eAAe,OAAO,GAAY,SAAoC;CACpE,OAAO,EAAE,KAAM,MAAM,mBAAmB,GAAG,WAAW,EAAE,aAAa,QAAQ,CAAC,KAAM,IAAI,GAAG;AAC7F;AAEA,eAAe,YACb,SACA,MACA,UACe;CACf,MAAM,QAAQ,eAAe;EAC3B,UAAU,SAAS,SAAS,IAAI,WAAW;EAC3C,SAAS,SAAS;EAClB,gBAAgB,cAAc,IAAI;EAClC,wBAAwB,WAAW,IAAI;CACzC,CAAC;CACD,MAAM,IAAI,aAAa,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,QAAQ,IAAI,KAAK;AAChE;AAEA,eAAe,oBAAoB,GAA+B;CAChE,MAAM,UAAU,MAAM,YAAY,EAAE,IAAI,MAAM,MAAM,KAAK,EAAE;CAC3D,MAAM,OAAO,MAAM,EAAE,IAAI,SAAS;CAClC,IAAI;EACF,MAAM,WAAW,aAAa,IAAI;EAClC,MAAM,wBAAwB,UAAU,gBAAgB,OAAO,CAAC;EAChE,MAAM,YAAY,SAAS,MAAM,QAAQ;CAC3C,SAAS,OAAO;EACd,IAAI,iBAAiB,eAAe,OAAO,MAAM,OAAO,GAAG,MAAM,OAAO;EACxE,MAAM;CACR;CACA,MAAM,GAAG,wBAAwB;CACjC,OAAO,WAAW,GAAG,aAAa,QAAQ,KAAK,kBAAkB;AACnE"}
|