@joewinke/jatui 0.37.0 → 0.38.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/dist/artifact-blocks/AttachmentChip.svelte +66 -0
- package/dist/artifact-blocks/AttachmentChip.svelte.d.ts +7 -0
- package/dist/artifact-blocks/BlockComments.svelte +309 -0
- package/dist/artifact-blocks/BlockComments.svelte.d.ts +33 -0
- package/dist/artifact-blocks/BlockRenderer.svelte +674 -0
- package/dist/artifact-blocks/BlockRenderer.svelte.d.ts +55 -0
- package/dist/artifact-blocks/BlockVerdict.svelte +151 -0
- package/dist/artifact-blocks/BlockVerdict.svelte.d.ts +13 -0
- package/dist/artifact-blocks/BlocksArtifactView.svelte +1616 -0
- package/dist/artifact-blocks/BlocksArtifactView.svelte.d.ts +113 -0
- package/dist/artifact-blocks/CONTRACT.md +225 -0
- package/dist/artifact-blocks/CommentPill.svelte +49 -0
- package/dist/artifact-blocks/CommentPill.svelte.d.ts +16 -0
- package/dist/artifact-blocks/FoldedRounds.svelte +95 -0
- package/dist/artifact-blocks/FoldedRounds.svelte.d.ts +9 -0
- package/dist/artifact-blocks/Glyph.svelte +54 -0
- package/dist/artifact-blocks/Glyph.svelte.d.ts +10 -0
- package/dist/artifact-blocks/HistoryScrubber.svelte +500 -0
- package/dist/artifact-blocks/HistoryScrubber.svelte.d.ts +15 -0
- package/dist/artifact-blocks/Markdown.svelte +186 -0
- package/dist/artifact-blocks/Markdown.svelte.d.ts +30 -0
- package/dist/artifact-blocks/NoteComposer.svelte +31 -0
- package/dist/artifact-blocks/NoteComposer.svelte.d.ts +8 -0
- package/dist/artifact-blocks/PlainComposer.svelte +200 -0
- package/dist/artifact-blocks/PlainComposer.svelte.d.ts +15 -0
- package/dist/artifact-blocks/SectionTools.svelte +102 -0
- package/dist/artifact-blocks/SectionTools.svelte.d.ts +19 -0
- package/dist/artifact-blocks/adapter.d.ts +13 -0
- package/dist/artifact-blocks/adapter.js +31 -0
- package/dist/artifact-blocks/autoSend.d.ts +49 -0
- package/dist/artifact-blocks/autoSend.js +103 -0
- package/dist/artifact-blocks/blocks/actions/ActionsBlock.svelte +557 -0
- package/dist/artifact-blocks/blocks/actions/ActionsBlock.svelte.d.ts +48 -0
- package/dist/artifact-blocks/blocks/actions/block.d.ts +8 -0
- package/dist/artifact-blocks/blocks/actions/block.js +74 -0
- package/dist/artifact-blocks/blocks/actions/requests.d.ts +62 -0
- package/dist/artifact-blocks/blocks/actions/requests.js +26 -0
- package/dist/artifact-blocks/blocks/actions/schema.d.ts +168 -0
- package/dist/artifact-blocks/blocks/actions/schema.js +253 -0
- package/dist/artifact-blocks/blocks/callout/CalloutBlock.svelte +779 -0
- package/dist/artifact-blocks/blocks/callout/CalloutBlock.svelte.d.ts +40 -0
- package/dist/artifact-blocks/blocks/callout/block.d.ts +7 -0
- package/dist/artifact-blocks/blocks/callout/block.js +39 -0
- package/dist/artifact-blocks/blocks/callout/schema.d.ts +72 -0
- package/dist/artifact-blocks/blocks/callout/schema.js +115 -0
- package/dist/artifact-blocks/blocks/chart/ChartBlock.svelte +875 -0
- package/dist/artifact-blocks/blocks/chart/ChartBlock.svelte.d.ts +59 -0
- package/dist/artifact-blocks/blocks/chart/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/chart/block.js +70 -0
- package/dist/artifact-blocks/blocks/chart/schema.d.ts +171 -0
- package/dist/artifact-blocks/blocks/chart/schema.js +498 -0
- package/dist/artifact-blocks/blocks/chart/thumb.d.ts +2 -0
- package/dist/artifact-blocks/blocks/chart/thumb.js +201 -0
- package/dist/artifact-blocks/blocks/checklist/ChecklistBlock.svelte +1048 -0
- package/dist/artifact-blocks/blocks/checklist/ChecklistBlock.svelte.d.ts +16 -0
- package/dist/artifact-blocks/blocks/checklist/Icon.svelte +105 -0
- package/dist/artifact-blocks/blocks/checklist/Icon.svelte.d.ts +17 -0
- package/dist/artifact-blocks/blocks/checklist/block.d.ts +10 -0
- package/dist/artifact-blocks/blocks/checklist/block.js +63 -0
- package/dist/artifact-blocks/blocks/checklist/itemReview.d.ts +16 -0
- package/dist/artifact-blocks/blocks/checklist/itemReview.js +63 -0
- package/dist/artifact-blocks/blocks/checklist/labels.d.ts +62 -0
- package/dist/artifact-blocks/blocks/checklist/labels.js +96 -0
- package/dist/artifact-blocks/blocks/checklist/retest.d.ts +43 -0
- package/dist/artifact-blocks/blocks/checklist/retest.js +68 -0
- package/dist/artifact-blocks/blocks/checklist/schema.d.ts +84 -0
- package/dist/artifact-blocks/blocks/checklist/schema.js +91 -0
- package/dist/artifact-blocks/blocks/code/CodeBlock.svelte +128 -0
- package/dist/artifact-blocks/blocks/code/CodeBlock.svelte.d.ts +12 -0
- package/dist/artifact-blocks/blocks/code/block.d.ts +8 -0
- package/dist/artifact-blocks/blocks/code/block.js +31 -0
- package/dist/artifact-blocks/blocks/code/highlight.d.ts +34 -0
- package/dist/artifact-blocks/blocks/code/highlight.js +280 -0
- package/dist/artifact-blocks/blocks/code/schema.d.ts +32 -0
- package/dist/artifact-blocks/blocks/code/schema.js +39 -0
- package/dist/artifact-blocks/blocks/collage/CollageBlock.svelte +290 -0
- package/dist/artifact-blocks/blocks/collage/CollageBlock.svelte.d.ts +29 -0
- package/dist/artifact-blocks/blocks/collage/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/collage/block.js +29 -0
- package/dist/artifact-blocks/blocks/collage/schema.d.ts +52 -0
- package/dist/artifact-blocks/blocks/collage/schema.js +86 -0
- package/dist/artifact-blocks/blocks/compare/CompareBlock.svelte +484 -0
- package/dist/artifact-blocks/blocks/compare/CompareBlock.svelte.d.ts +25 -0
- package/dist/artifact-blocks/blocks/compare/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/compare/block.js +32 -0
- package/dist/artifact-blocks/blocks/compare/schema.d.ts +74 -0
- package/dist/artifact-blocks/blocks/compare/schema.js +148 -0
- package/dist/artifact-blocks/blocks/diagram/DiagramBlock.svelte +392 -0
- package/dist/artifact-blocks/blocks/diagram/DiagramBlock.svelte.d.ts +30 -0
- package/dist/artifact-blocks/blocks/diagram/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/diagram/block.js +50 -0
- package/dist/artifact-blocks/blocks/diagram/constants.d.ts +48 -0
- package/dist/artifact-blocks/blocks/diagram/constants.js +53 -0
- package/dist/artifact-blocks/blocks/diagram/schema.d.ts +161 -0
- package/dist/artifact-blocks/blocks/diagram/schema.js +621 -0
- package/dist/artifact-blocks/blocks/diagram/thumb.d.ts +2 -0
- package/dist/artifact-blocks/blocks/diagram/thumb.js +157 -0
- package/dist/artifact-blocks/blocks/diagram/types.d.ts +74 -0
- package/dist/artifact-blocks/blocks/diagram/types.js +1 -0
- package/dist/artifact-blocks/blocks/diff/DiffBlock.svelte +81 -0
- package/dist/artifact-blocks/blocks/diff/DiffBlock.svelte.d.ts +10 -0
- package/dist/artifact-blocks/blocks/diff/block.d.ts +7 -0
- package/dist/artifact-blocks/blocks/diff/block.js +36 -0
- package/dist/artifact-blocks/blocks/diff/schema.d.ts +18 -0
- package/dist/artifact-blocks/blocks/diff/schema.js +35 -0
- package/dist/artifact-blocks/blocks/diff-review/DiffReviewBlock.svelte +1055 -0
- package/dist/artifact-blocks/blocks/diff-review/DiffReviewBlock.svelte.d.ts +5 -0
- package/dist/artifact-blocks/blocks/diff-review/block.d.ts +15 -0
- package/dist/artifact-blocks/blocks/diff-review/block.js +64 -0
- package/dist/artifact-blocks/blocks/diff-review/decisions.d.ts +57 -0
- package/dist/artifact-blocks/blocks/diff-review/decisions.js +80 -0
- package/dist/artifact-blocks/blocks/diff-review/schema.d.ts +13 -0
- package/dist/artifact-blocks/blocks/diff-review/schema.js +84 -0
- package/dist/artifact-blocks/blocks/diff-review/types.d.ts +35 -0
- package/dist/artifact-blocks/blocks/diff-review/types.js +1 -0
- package/dist/artifact-blocks/blocks/explainer/ExplainerBlock.svelte +145 -0
- package/dist/artifact-blocks/blocks/explainer/ExplainerBlock.svelte.d.ts +5 -0
- package/dist/artifact-blocks/blocks/explainer/block.d.ts +8 -0
- package/dist/artifact-blocks/blocks/explainer/block.js +21 -0
- package/dist/artifact-blocks/blocks/explainer/schema.d.ts +26 -0
- package/dist/artifact-blocks/blocks/explainer/schema.js +69 -0
- package/dist/artifact-blocks/blocks/group-content.d.ts +10 -0
- package/dist/artifact-blocks/blocks/group-content.js +16 -0
- package/dist/artifact-blocks/blocks/group-data.d.ts +10 -0
- package/dist/artifact-blocks/blocks/group-data.js +7 -0
- package/dist/artifact-blocks/blocks/group-review.d.ts +10 -0
- package/dist/artifact-blocks/blocks/group-review.js +12 -0
- package/dist/artifact-blocks/blocks/group-visual.d.ts +17 -0
- package/dist/artifact-blocks/blocks/group-visual.js +14 -0
- package/dist/artifact-blocks/blocks/map/MapBlock.svelte +413 -0
- package/dist/artifact-blocks/blocks/map/MapBlock.svelte.d.ts +53 -0
- package/dist/artifact-blocks/blocks/map/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/map/block.js +62 -0
- package/dist/artifact-blocks/blocks/map/schema.d.ts +123 -0
- package/dist/artifact-blocks/blocks/map/schema.js +113 -0
- package/dist/artifact-blocks/blocks/map/thumb.d.ts +2 -0
- package/dist/artifact-blocks/blocks/map/thumb.js +69 -0
- package/dist/artifact-blocks/blocks/markdown/MarkdownBlock.svelte +33 -0
- package/dist/artifact-blocks/blocks/markdown/MarkdownBlock.svelte.d.ts +15 -0
- package/dist/artifact-blocks/blocks/markdown/block.d.ts +7 -0
- package/dist/artifact-blocks/blocks/markdown/block.js +28 -0
- package/dist/artifact-blocks/blocks/markdown/render.d.ts +17 -0
- package/dist/artifact-blocks/blocks/markdown/render.js +115 -0
- package/dist/artifact-blocks/blocks/markdown/schema.d.ts +10 -0
- package/dist/artifact-blocks/blocks/markdown/schema.js +23 -0
- package/dist/artifact-blocks/blocks/media-picker/MediaPickerBlock.svelte +2112 -0
- package/dist/artifact-blocks/blocks/media-picker/MediaPickerBlock.svelte.d.ts +5 -0
- package/dist/artifact-blocks/blocks/media-picker/block.d.ts +24 -0
- package/dist/artifact-blocks/blocks/media-picker/block.js +137 -0
- package/dist/artifact-blocks/blocks/media-picker/choices.d.ts +28 -0
- package/dist/artifact-blocks/blocks/media-picker/choices.js +35 -0
- package/dist/artifact-blocks/blocks/media-picker/decisions.d.ts +51 -0
- package/dist/artifact-blocks/blocks/media-picker/decisions.js +75 -0
- package/dist/artifact-blocks/blocks/media-picker/schema.d.ts +7 -0
- package/dist/artifact-blocks/blocks/media-picker/schema.js +199 -0
- package/dist/artifact-blocks/blocks/media-picker/types.d.ts +92 -0
- package/dist/artifact-blocks/blocks/media-picker/types.js +1 -0
- package/dist/artifact-blocks/blocks/media-picker/versions.d.ts +51 -0
- package/dist/artifact-blocks/blocks/media-picker/versions.js +118 -0
- package/dist/artifact-blocks/blocks/mockup/MockupBlock.svelte +213 -0
- package/dist/artifact-blocks/blocks/mockup/MockupBlock.svelte.d.ts +5 -0
- package/dist/artifact-blocks/blocks/mockup/block.d.ts +26 -0
- package/dist/artifact-blocks/blocks/mockup/block.js +52 -0
- package/dist/artifact-blocks/blocks/mockup/doc.d.ts +24 -0
- package/dist/artifact-blocks/blocks/mockup/doc.js +44 -0
- package/dist/artifact-blocks/blocks/mockup/sandbox.d.ts +21 -0
- package/dist/artifact-blocks/blocks/mockup/sandbox.js +27 -0
- package/dist/artifact-blocks/blocks/mockup/schema.d.ts +7 -0
- package/dist/artifact-blocks/blocks/mockup/schema.js +90 -0
- package/dist/artifact-blocks/blocks/mockup/types.d.ts +36 -0
- package/dist/artifact-blocks/blocks/mockup/types.js +17 -0
- package/dist/artifact-blocks/blocks/program/ProgramBlock.svelte +359 -0
- package/dist/artifact-blocks/blocks/program/ProgramBlock.svelte.d.ts +32 -0
- package/dist/artifact-blocks/blocks/program/block.d.ts +35 -0
- package/dist/artifact-blocks/blocks/program/block.js +68 -0
- package/dist/artifact-blocks/blocks/program/schema.d.ts +132 -0
- package/dist/artifact-blocks/blocks/program/schema.js +268 -0
- package/dist/artifact-blocks/blocks/stats/StatsBlock.svelte +315 -0
- package/dist/artifact-blocks/blocks/stats/StatsBlock.svelte.d.ts +24 -0
- package/dist/artifact-blocks/blocks/stats/block.d.ts +7 -0
- package/dist/artifact-blocks/blocks/stats/block.js +49 -0
- package/dist/artifact-blocks/blocks/stats/schema.d.ts +82 -0
- package/dist/artifact-blocks/blocks/stats/schema.js +43 -0
- package/dist/artifact-blocks/blocks/stats/thumb.d.ts +2 -0
- package/dist/artifact-blocks/blocks/stats/thumb.js +102 -0
- package/dist/artifact-blocks/blocks/table/TableBlock.svelte +490 -0
- package/dist/artifact-blocks/blocks/table/TableBlock.svelte.d.ts +28 -0
- package/dist/artifact-blocks/blocks/table/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/table/block.js +100 -0
- package/dist/artifact-blocks/blocks/table/schema.d.ts +143 -0
- package/dist/artifact-blocks/blocks/table/schema.js +278 -0
- package/dist/artifact-blocks/blocks/timeline/TimelineBlock.svelte +347 -0
- package/dist/artifact-blocks/blocks/timeline/TimelineBlock.svelte.d.ts +42 -0
- package/dist/artifact-blocks/blocks/timeline/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/timeline/block.js +96 -0
- package/dist/artifact-blocks/blocks/timeline/constants.d.ts +26 -0
- package/dist/artifact-blocks/blocks/timeline/constants.js +27 -0
- package/dist/artifact-blocks/blocks/timeline/schema.d.ts +102 -0
- package/dist/artifact-blocks/blocks/timeline/schema.js +405 -0
- package/dist/artifact-blocks/blocks/timeline/thumb.d.ts +2 -0
- package/dist/artifact-blocks/blocks/timeline/thumb.js +117 -0
- package/dist/artifact-blocks/blocks/timeline/types.d.ts +66 -0
- package/dist/artifact-blocks/blocks/timeline/types.js +1 -0
- package/dist/artifact-blocks/blocks/transcript/TranscriptBlock.svelte +169 -0
- package/dist/artifact-blocks/blocks/transcript/TranscriptBlock.svelte.d.ts +26 -0
- package/dist/artifact-blocks/blocks/transcript/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/transcript/block.js +86 -0
- package/dist/artifact-blocks/blocks/transcript/schema.d.ts +114 -0
- package/dist/artifact-blocks/blocks/transcript/schema.js +126 -0
- package/dist/artifact-blocks/builtins.d.ts +40 -0
- package/dist/artifact-blocks/builtins.js +22 -0
- package/dist/artifact-blocks/contractBlocks.d.ts +92 -0
- package/dist/artifact-blocks/contractBlocks.js +279 -0
- package/dist/artifact-blocks/history.d.ts +140 -0
- package/dist/artifact-blocks/history.js +363 -0
- package/dist/artifact-blocks/index.d.ts +40 -0
- package/dist/artifact-blocks/index.js +46 -0
- package/dist/artifact-blocks/listen/context.d.ts +30 -0
- package/dist/artifact-blocks/listen/context.js +30 -0
- package/dist/artifact-blocks/liveData.d.ts +78 -0
- package/dist/artifact-blocks/liveData.js +137 -0
- package/dist/artifact-blocks/liveDataPoller.d.ts +41 -0
- package/dist/artifact-blocks/liveDataPoller.js +140 -0
- package/dist/artifact-blocks/openNav.d.ts +46 -0
- package/dist/artifact-blocks/openNav.js +106 -0
- package/dist/artifact-blocks/pageReviewKeys.d.ts +17 -0
- package/dist/artifact-blocks/pageReviewKeys.js +115 -0
- package/dist/artifact-blocks/params.d.ts +98 -0
- package/dist/artifact-blocks/params.js +159 -0
- package/dist/artifact-blocks/registry.d.ts +27 -0
- package/dist/artifact-blocks/registry.js +83 -0
- package/dist/artifact-blocks/review/BlockIcon.svelte +99 -0
- package/dist/artifact-blocks/review/BlockIcon.svelte.d.ts +17 -0
- package/dist/artifact-blocks/review/BulkRejectForm.svelte +94 -0
- package/dist/artifact-blocks/review/BulkRejectForm.svelte.d.ts +11 -0
- package/dist/artifact-blocks/review/BulkUndoBar.svelte +40 -0
- package/dist/artifact-blocks/review/BulkUndoBar.svelte.d.ts +9 -0
- package/dist/artifact-blocks/review/ItemNote.svelte +193 -0
- package/dist/artifact-blocks/review/ItemNote.svelte.d.ts +33 -0
- package/dist/artifact-blocks/review/NoteToggle.svelte +52 -0
- package/dist/artifact-blocks/review/NoteToggle.svelte.d.ts +12 -0
- package/dist/artifact-blocks/review/TeamChip.svelte +71 -0
- package/dist/artifact-blocks/review/TeamChip.svelte.d.ts +8 -0
- package/dist/artifact-blocks/review/attachments.d.ts +10 -0
- package/dist/artifact-blocks/review/attachments.js +37 -0
- package/dist/artifact-blocks/review/bulk.d.ts +52 -0
- package/dist/artifact-blocks/review/bulk.js +61 -0
- package/dist/artifact-blocks/review/itemReview.d.ts +33 -0
- package/dist/artifact-blocks/review/itemReview.js +112 -0
- package/dist/artifact-blocks/review/roundLines.d.ts +14 -0
- package/dist/artifact-blocks/review/roundLines.js +20 -0
- package/dist/artifact-blocks/review/rounds.d.ts +86 -0
- package/dist/artifact-blocks/review/rounds.js +302 -0
- package/dist/artifact-blocks/review/saver.d.ts +23 -0
- package/dist/artifact-blocks/review/saver.js +48 -0
- package/dist/artifact-blocks/review/team.d.ts +31 -0
- package/dist/artifact-blocks/review/team.js +42 -0
- package/dist/artifact-blocks/review/visualOrder.d.ts +29 -0
- package/dist/artifact-blocks/review/visualOrder.js +66 -0
- package/dist/artifact-blocks/review.d.ts +180 -0
- package/dist/artifact-blocks/review.js +716 -0
- package/dist/artifact-blocks/thumb-kit.d.ts +80 -0
- package/dist/artifact-blocks/thumb-kit.js +149 -0
- package/dist/artifact-blocks/types.d.ts +513 -0
- package/dist/artifact-blocks/types.js +1 -0
- package/package.json +11 -2
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The actions block's wire shapes + the host service it calls (mos-p9auh;
|
|
3
|
+
* jatui-n5z1x). MOS made two session fetches to /api/v1/artifacts/[id]/
|
|
4
|
+
* actions; in jatui those are the HOST's, reached through
|
|
5
|
+
* `HostAdapter.services.actions` (an `ActionsService`). A host without one
|
|
6
|
+
* renders the actions as a quiet, labelled list — never live-looking
|
|
7
|
+
* buttons that send nowhere. Link actions (`href`) need no service.
|
|
8
|
+
*/
|
|
9
|
+
import type { BlockServices } from "../../types.js";
|
|
10
|
+
import type { AckStatus, ActionInputs } from "./schema.js";
|
|
11
|
+
/** One action request as a viewer sees it (no raw user ids). */
|
|
12
|
+
export interface ActionRequestView {
|
|
13
|
+
id: string;
|
|
14
|
+
actionId: string;
|
|
15
|
+
status: AckStatus;
|
|
16
|
+
/** The agent's answer, shown under the button. */
|
|
17
|
+
note: string | null;
|
|
18
|
+
ackedBy: string | null;
|
|
19
|
+
ackedAt: string | null;
|
|
20
|
+
createdAt: string;
|
|
21
|
+
/** Who pressed it (name/email), for the "by … · time" line. */
|
|
22
|
+
viewerLabel: string | null;
|
|
23
|
+
/** True when the session viewer pressed it. */
|
|
24
|
+
mine: boolean;
|
|
25
|
+
inputs: ActionInputs;
|
|
26
|
+
}
|
|
27
|
+
export interface ActionsReadResponse {
|
|
28
|
+
requests: ActionRequestView[];
|
|
29
|
+
/** actionId → may THIS viewer press it (role gate). */
|
|
30
|
+
allowed: Record<string, boolean>;
|
|
31
|
+
}
|
|
32
|
+
/** The newest request per action id (requests arrive oldest first). */
|
|
33
|
+
export declare function latestByAction(requests: ActionRequestView[]): Map<string, ActionRequestView>;
|
|
34
|
+
export declare class ActionRequestError extends Error {
|
|
35
|
+
readonly status: number;
|
|
36
|
+
readonly request: ActionRequestView | null;
|
|
37
|
+
constructor(message: string, status: number, request?: ActionRequestView | null);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The host's leg for action requests (`HostAdapter.services.actions`).
|
|
41
|
+
* Both calls may throw any Error with a human message — the block shows
|
|
42
|
+
* it. A `send` that finds the action already open throws an error carrying
|
|
43
|
+
* that open `request` (`ActionRequestError` is one), so the block shows the
|
|
44
|
+
* existing one instead of queueing a second.
|
|
45
|
+
*/
|
|
46
|
+
export interface ActionsService {
|
|
47
|
+
/** This block's requests (oldest first) + which actions THIS viewer may press. */
|
|
48
|
+
load(args: {
|
|
49
|
+
artifactId: string;
|
|
50
|
+
blockId: string;
|
|
51
|
+
}): Promise<ActionsReadResponse>;
|
|
52
|
+
/** Record one request; resolves with it as the viewer sees it. */
|
|
53
|
+
send(args: {
|
|
54
|
+
artifactId: string;
|
|
55
|
+
blockId: string;
|
|
56
|
+
actionId: string;
|
|
57
|
+
inputs: ActionInputs;
|
|
58
|
+
reason?: string | null;
|
|
59
|
+
}): Promise<ActionRequestView>;
|
|
60
|
+
}
|
|
61
|
+
/** The actions service the host provided, or null (read-only list). */
|
|
62
|
+
export declare function actionsServiceOf(services: BlockServices | undefined): ActionsService | null;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** The newest request per action id (requests arrive oldest first). */
|
|
2
|
+
export function latestByAction(requests) {
|
|
3
|
+
const out = new Map();
|
|
4
|
+
for (const r of requests) {
|
|
5
|
+
const prev = out.get(r.actionId);
|
|
6
|
+
if (!prev || prev.createdAt <= r.createdAt)
|
|
7
|
+
out.set(r.actionId, r);
|
|
8
|
+
}
|
|
9
|
+
return out;
|
|
10
|
+
}
|
|
11
|
+
export class ActionRequestError extends Error {
|
|
12
|
+
status;
|
|
13
|
+
request;
|
|
14
|
+
constructor(message, status, request = null) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.status = status;
|
|
17
|
+
this.request = request;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** The actions service the host provided, or null (read-only list). */
|
|
21
|
+
export function actionsServiceOf(services) {
|
|
22
|
+
const s = services?.actions;
|
|
23
|
+
return s && typeof s.load === "function" && typeof s.send === "function"
|
|
24
|
+
? s
|
|
25
|
+
: null;
|
|
26
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* actions block — params schema + the request rules both sides share
|
|
3
|
+
* (mos-p9auh, living artifacts phase 4).
|
|
4
|
+
*
|
|
5
|
+
* Pure TS, no Svelte: the session route (/api/v1/artifacts/[id]/actions)
|
|
6
|
+
* imports `validateActionRequest` from here so the server checks a click
|
|
7
|
+
* against the SAME declared fields the component rendered — the client's
|
|
8
|
+
* word about an input is never trusted on its own.
|
|
9
|
+
*
|
|
10
|
+
* An action is a REQUEST to the owning agent. MOS records it (one
|
|
11
|
+
* artifact_events row, kind 'action') and the agent answers with
|
|
12
|
+
* `mos-artifact ack`; nothing here executes anything.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
/**
|
|
16
|
+
* Team roles an action may be limited to. Mirrors ROLES in MOS
|
|
17
|
+
* src/lib/teams.ts (the role names a host's team model must map onto; the
|
|
18
|
+
* host enforces them server-side, jatui only carries the declaration).
|
|
19
|
+
*/
|
|
20
|
+
export declare const ACTION_ROLES: readonly ["viewer", "member", "office", "provider", "admin", "owner"];
|
|
21
|
+
type ActionRole = (typeof ACTION_ROLES)[number];
|
|
22
|
+
/** Who may press an action when it names no `roles`: every member-rank role. */
|
|
23
|
+
export declare const DEFAULT_ACTION_ROLES: readonly ActionRole[];
|
|
24
|
+
export declare const actionSchema: z.ZodObject<{
|
|
25
|
+
id: z.ZodString;
|
|
26
|
+
label: z.ZodString;
|
|
27
|
+
description: z.ZodOptional<z.ZodString>;
|
|
28
|
+
intent: z.ZodOptional<z.ZodString>;
|
|
29
|
+
variant: z.ZodDefault<z.ZodEnum<{
|
|
30
|
+
primary: "primary";
|
|
31
|
+
default: "default";
|
|
32
|
+
danger: "danger";
|
|
33
|
+
}>>;
|
|
34
|
+
confirm: z.ZodOptional<z.ZodString>;
|
|
35
|
+
fields: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
36
|
+
id: z.ZodString;
|
|
37
|
+
type: z.ZodLiteral<"text">;
|
|
38
|
+
label: z.ZodString;
|
|
39
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
40
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
41
|
+
multiline: z.ZodDefault<z.ZodBoolean>;
|
|
42
|
+
maxLength: z.ZodDefault<z.ZodNumber>;
|
|
43
|
+
default: z.ZodOptional<z.ZodString>;
|
|
44
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
45
|
+
id: z.ZodString;
|
|
46
|
+
type: z.ZodLiteral<"number">;
|
|
47
|
+
label: z.ZodString;
|
|
48
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
49
|
+
min: z.ZodOptional<z.ZodNumber>;
|
|
50
|
+
max: z.ZodOptional<z.ZodNumber>;
|
|
51
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
52
|
+
default: z.ZodOptional<z.ZodNumber>;
|
|
53
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
54
|
+
id: z.ZodString;
|
|
55
|
+
type: z.ZodLiteral<"select">;
|
|
56
|
+
label: z.ZodString;
|
|
57
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
58
|
+
options: z.ZodArray<z.ZodObject<{
|
|
59
|
+
value: z.ZodString;
|
|
60
|
+
label: z.ZodString;
|
|
61
|
+
}, z.core.$strip>>;
|
|
62
|
+
default: z.ZodOptional<z.ZodString>;
|
|
63
|
+
}, z.core.$strip>], "type">>>;
|
|
64
|
+
roles: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
65
|
+
owner: "owner";
|
|
66
|
+
admin: "admin";
|
|
67
|
+
member: "member";
|
|
68
|
+
viewer: "viewer";
|
|
69
|
+
office: "office";
|
|
70
|
+
provider: "provider";
|
|
71
|
+
}>>>;
|
|
72
|
+
owner: z.ZodOptional<z.ZodString>;
|
|
73
|
+
href: z.ZodOptional<z.ZodString>;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
export declare const actionsSchema: z.ZodObject<{
|
|
76
|
+
title: z.ZodOptional<z.ZodString>;
|
|
77
|
+
description: z.ZodOptional<z.ZodString>;
|
|
78
|
+
owner: z.ZodOptional<z.ZodString>;
|
|
79
|
+
actions: z.ZodArray<z.ZodObject<{
|
|
80
|
+
id: z.ZodString;
|
|
81
|
+
label: z.ZodString;
|
|
82
|
+
description: z.ZodOptional<z.ZodString>;
|
|
83
|
+
intent: z.ZodOptional<z.ZodString>;
|
|
84
|
+
variant: z.ZodDefault<z.ZodEnum<{
|
|
85
|
+
primary: "primary";
|
|
86
|
+
default: "default";
|
|
87
|
+
danger: "danger";
|
|
88
|
+
}>>;
|
|
89
|
+
confirm: z.ZodOptional<z.ZodString>;
|
|
90
|
+
fields: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
91
|
+
id: z.ZodString;
|
|
92
|
+
type: z.ZodLiteral<"text">;
|
|
93
|
+
label: z.ZodString;
|
|
94
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
95
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
96
|
+
multiline: z.ZodDefault<z.ZodBoolean>;
|
|
97
|
+
maxLength: z.ZodDefault<z.ZodNumber>;
|
|
98
|
+
default: z.ZodOptional<z.ZodString>;
|
|
99
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
100
|
+
id: z.ZodString;
|
|
101
|
+
type: z.ZodLiteral<"number">;
|
|
102
|
+
label: z.ZodString;
|
|
103
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
104
|
+
min: z.ZodOptional<z.ZodNumber>;
|
|
105
|
+
max: z.ZodOptional<z.ZodNumber>;
|
|
106
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
107
|
+
default: z.ZodOptional<z.ZodNumber>;
|
|
108
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
109
|
+
id: z.ZodString;
|
|
110
|
+
type: z.ZodLiteral<"select">;
|
|
111
|
+
label: z.ZodString;
|
|
112
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
113
|
+
options: z.ZodArray<z.ZodObject<{
|
|
114
|
+
value: z.ZodString;
|
|
115
|
+
label: z.ZodString;
|
|
116
|
+
}, z.core.$strip>>;
|
|
117
|
+
default: z.ZodOptional<z.ZodString>;
|
|
118
|
+
}, z.core.$strip>], "type">>>;
|
|
119
|
+
roles: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
120
|
+
owner: "owner";
|
|
121
|
+
admin: "admin";
|
|
122
|
+
member: "member";
|
|
123
|
+
viewer: "viewer";
|
|
124
|
+
office: "office";
|
|
125
|
+
provider: "provider";
|
|
126
|
+
}>>>;
|
|
127
|
+
owner: z.ZodOptional<z.ZodString>;
|
|
128
|
+
href: z.ZodOptional<z.ZodString>;
|
|
129
|
+
}, z.core.$strip>>;
|
|
130
|
+
}, z.core.$strip>;
|
|
131
|
+
export type ActionsParams = z.infer<typeof actionsSchema>;
|
|
132
|
+
export type ActionDef = z.infer<typeof actionSchema>;
|
|
133
|
+
export type ActionInputValue = string | number;
|
|
134
|
+
export type ActionInputs = Record<string, ActionInputValue>;
|
|
135
|
+
/** The ack lifecycle (mirrors the artifact_events.ack_status CHECK). */
|
|
136
|
+
export declare const ACK_STATUSES: readonly ["queued", "running", "done", "failed"];
|
|
137
|
+
export type AckStatus = (typeof ACK_STATUSES)[number];
|
|
138
|
+
/** A link action (PARAMS-SPEC §2): navigates, never sends a request. */
|
|
139
|
+
export declare function isLinkAction(action: ActionDef): action is ActionDef & {
|
|
140
|
+
href: string;
|
|
141
|
+
};
|
|
142
|
+
/** Does a link leave this origin (→ new tab)? Root-relative and `#` stay. */
|
|
143
|
+
export declare function isOffOrigin(href: string, origin?: string): boolean;
|
|
144
|
+
export declare function isTerminal(status: AckStatus): boolean;
|
|
145
|
+
/** The intent the agent switches on: explicit intent, else the action id. */
|
|
146
|
+
export declare function intentOf(action: ActionDef): string;
|
|
147
|
+
/** May a viewer with this team role press this action? */
|
|
148
|
+
export declare function roleMayAct(action: ActionDef, role: string | null): boolean;
|
|
149
|
+
export type ActionRequestCheck = {
|
|
150
|
+
ok: true;
|
|
151
|
+
inputs: ActionInputs;
|
|
152
|
+
reason: string | null;
|
|
153
|
+
} | {
|
|
154
|
+
ok: false;
|
|
155
|
+
error: string;
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Check ONE request against the action it names: every declared field is
|
|
159
|
+
* coerced and range/option-checked, undeclared inputs are dropped (never
|
|
160
|
+
* forwarded to the agent), and a danger action demands a typed reason.
|
|
161
|
+
* The server's authority; the component runs it too so the viewer sees the
|
|
162
|
+
* same message before a round-trip (`fieldsOnly` = check the form before
|
|
163
|
+
* the danger confirm opens, when no reason has been typed yet).
|
|
164
|
+
*/
|
|
165
|
+
export declare function validateActionRequest(action: ActionDef, rawInputs: unknown, rawReason: unknown, opts?: {
|
|
166
|
+
fieldsOnly?: boolean;
|
|
167
|
+
}): ActionRequestCheck;
|
|
168
|
+
export {};
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* actions block — params schema + the request rules both sides share
|
|
3
|
+
* (mos-p9auh, living artifacts phase 4).
|
|
4
|
+
*
|
|
5
|
+
* Pure TS, no Svelte: the session route (/api/v1/artifacts/[id]/actions)
|
|
6
|
+
* imports `validateActionRequest` from here so the server checks a click
|
|
7
|
+
* against the SAME declared fields the component rendered — the client's
|
|
8
|
+
* word about an input is never trusted on its own.
|
|
9
|
+
*
|
|
10
|
+
* An action is a REQUEST to the owning agent. MOS records it (one
|
|
11
|
+
* artifact_events row, kind 'action') and the agent answers with
|
|
12
|
+
* `mos-artifact ack`; nothing here executes anything.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
import { linkUrlSchema, shortTextSchema } from "../../params.js";
|
|
16
|
+
/** Ids are stable across republishes: request history keys on them. */
|
|
17
|
+
const idSchema = z
|
|
18
|
+
.string()
|
|
19
|
+
.regex(/^[a-z0-9][a-z0-9_-]{0,63}$/, "must be lowercase a-z0-9_- (max 64), starting with a letter or digit");
|
|
20
|
+
/**
|
|
21
|
+
* Team roles an action may be limited to. Mirrors ROLES in MOS
|
|
22
|
+
* src/lib/teams.ts (the role names a host's team model must map onto; the
|
|
23
|
+
* host enforces them server-side, jatui only carries the declaration).
|
|
24
|
+
*/
|
|
25
|
+
export const ACTION_ROLES = [
|
|
26
|
+
"viewer",
|
|
27
|
+
"member",
|
|
28
|
+
"office",
|
|
29
|
+
"provider",
|
|
30
|
+
"admin",
|
|
31
|
+
"owner",
|
|
32
|
+
];
|
|
33
|
+
/** Who may press an action when it names no `roles`: every member-rank role. */
|
|
34
|
+
export const DEFAULT_ACTION_ROLES = [
|
|
35
|
+
"member",
|
|
36
|
+
"office",
|
|
37
|
+
"provider",
|
|
38
|
+
"admin",
|
|
39
|
+
"owner",
|
|
40
|
+
];
|
|
41
|
+
/** Hard cap on one text input's value. */
|
|
42
|
+
const MAX_TEXT_INPUT = 2000;
|
|
43
|
+
/** A danger action's typed reason: at least this many characters. */
|
|
44
|
+
const MIN_DANGER_REASON = 4;
|
|
45
|
+
const MAX_DANGER_REASON = 500;
|
|
46
|
+
const textField = z.object({
|
|
47
|
+
id: idSchema,
|
|
48
|
+
type: z.literal("text"),
|
|
49
|
+
label: shortTextSchema.min(1),
|
|
50
|
+
placeholder: shortTextSchema.optional(),
|
|
51
|
+
required: z.boolean().default(false),
|
|
52
|
+
/** Renders a textarea instead of a single-line input. */
|
|
53
|
+
multiline: z.boolean().default(false),
|
|
54
|
+
maxLength: z.number().int().min(1).max(MAX_TEXT_INPUT).default(500),
|
|
55
|
+
default: z.string().max(MAX_TEXT_INPUT).optional(),
|
|
56
|
+
});
|
|
57
|
+
const numberField = z
|
|
58
|
+
.object({
|
|
59
|
+
id: idSchema,
|
|
60
|
+
type: z.literal("number"),
|
|
61
|
+
label: shortTextSchema.min(1),
|
|
62
|
+
required: z.boolean().default(false),
|
|
63
|
+
min: z.number().finite().optional(),
|
|
64
|
+
max: z.number().finite().optional(),
|
|
65
|
+
step: z.number().positive().finite().optional(),
|
|
66
|
+
default: z.number().finite().optional(),
|
|
67
|
+
})
|
|
68
|
+
.refine((f) => f.min === undefined || f.max === undefined || f.min <= f.max, {
|
|
69
|
+
message: "min must be <= max",
|
|
70
|
+
path: ["min"],
|
|
71
|
+
});
|
|
72
|
+
const selectField = z
|
|
73
|
+
.object({
|
|
74
|
+
id: idSchema,
|
|
75
|
+
type: z.literal("select"),
|
|
76
|
+
label: shortTextSchema.min(1),
|
|
77
|
+
required: z.boolean().default(false),
|
|
78
|
+
options: z
|
|
79
|
+
.array(z.object({
|
|
80
|
+
value: z.string().min(1).max(120),
|
|
81
|
+
label: shortTextSchema.min(1),
|
|
82
|
+
}))
|
|
83
|
+
.min(1)
|
|
84
|
+
.max(30),
|
|
85
|
+
default: z.string().max(120).optional(),
|
|
86
|
+
})
|
|
87
|
+
.refine((f) => new Set(f.options.map((o) => o.value)).size === f.options.length, { message: "option values must be unique", path: ["options"] })
|
|
88
|
+
.refine((f) => f.default === undefined || f.options.some((o) => o.value === f.default), { message: "default must be one of the option values", path: ["default"] });
|
|
89
|
+
const actionFieldSchema = z.discriminatedUnion("type", [
|
|
90
|
+
textField,
|
|
91
|
+
numberField,
|
|
92
|
+
selectField,
|
|
93
|
+
]);
|
|
94
|
+
export const actionSchema = z
|
|
95
|
+
.object({
|
|
96
|
+
id: idSchema,
|
|
97
|
+
/** The button text. */
|
|
98
|
+
label: z.string().trim().min(1).max(80),
|
|
99
|
+
/** One line under the button: what pressing it asks the agent to do. */
|
|
100
|
+
description: z.string().max(500).optional(),
|
|
101
|
+
/**
|
|
102
|
+
* The machine-readable intent the agent switches on, e.g.
|
|
103
|
+
* "rerun-scenario:ruby_office_switch". Defaults to the action id.
|
|
104
|
+
*/
|
|
105
|
+
intent: z.string().trim().min(1).max(200).optional(),
|
|
106
|
+
/** primary = the obvious next step; danger = confirm + typed reason. */
|
|
107
|
+
variant: z.enum(["default", "primary", "danger"]).default("default"),
|
|
108
|
+
/** Extra confirm copy shown before a danger request is sent. */
|
|
109
|
+
confirm: z.string().max(500).optional(),
|
|
110
|
+
/** Small form the viewer fills before sending (max 8 fields). */
|
|
111
|
+
fields: z.array(actionFieldSchema).max(8).default([]),
|
|
112
|
+
/**
|
|
113
|
+
* Team roles allowed to press it (exact list). Omitted = every
|
|
114
|
+
* member-rank role; a viewer-role seat can never act unless listed.
|
|
115
|
+
*/
|
|
116
|
+
roles: z.array(z.enum(ACTION_ROLES)).min(1).max(6).optional(),
|
|
117
|
+
/** Route this action's requests to a different agent than the block's. */
|
|
118
|
+
owner: z.string().trim().min(1).max(80).optional(),
|
|
119
|
+
/**
|
|
120
|
+
* PARAMS-SPEC §2 (jat-j49id): set → the action is a LINK, not a
|
|
121
|
+
* request. It renders as an `<a>` to this url (http(s) or
|
|
122
|
+
* root-relative; off-origin opens in a new tab), fires no event, and
|
|
123
|
+
* ignores intent / fields / confirm / roles / owner — no team role is
|
|
124
|
+
* needed to follow a link. It works on read-only surfaces too.
|
|
125
|
+
*/
|
|
126
|
+
href: linkUrlSchema.optional(),
|
|
127
|
+
})
|
|
128
|
+
.refine((a) => new Set(a.fields.map((f) => f.id)).size === a.fields.length, {
|
|
129
|
+
message: "field ids must be unique within an action",
|
|
130
|
+
path: ["fields"],
|
|
131
|
+
});
|
|
132
|
+
export const actionsSchema = z
|
|
133
|
+
.object({
|
|
134
|
+
title: shortTextSchema.optional(),
|
|
135
|
+
description: z.string().max(1000).optional(),
|
|
136
|
+
/**
|
|
137
|
+
* The agent that hears these requests (falls back to the block-level
|
|
138
|
+
* owner, then the artifact publisher). Read SERVER-SIDE only.
|
|
139
|
+
*/
|
|
140
|
+
owner: z.string().trim().min(1).max(80).optional(),
|
|
141
|
+
actions: z.array(actionSchema).min(1).max(12),
|
|
142
|
+
})
|
|
143
|
+
.refine((p) => new Set(p.actions.map((a) => a.id)).size === p.actions.length, { message: "action ids must be unique", path: ["actions"] });
|
|
144
|
+
/** The ack lifecycle (mirrors the artifact_events.ack_status CHECK). */
|
|
145
|
+
export const ACK_STATUSES = ["queued", "running", "done", "failed"];
|
|
146
|
+
/** A link action (PARAMS-SPEC §2): navigates, never sends a request. */
|
|
147
|
+
export function isLinkAction(action) {
|
|
148
|
+
return typeof action.href === "string" && action.href.length > 0;
|
|
149
|
+
}
|
|
150
|
+
/** Does a link leave this origin (→ new tab)? Root-relative and `#` stay. */
|
|
151
|
+
export function isOffOrigin(href, origin) {
|
|
152
|
+
if (!/^https?:\/\//i.test(href))
|
|
153
|
+
return false;
|
|
154
|
+
if (!origin)
|
|
155
|
+
return true;
|
|
156
|
+
try {
|
|
157
|
+
return new URL(href).origin !== origin;
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const TERMINAL_ACK = ["done", "failed"];
|
|
164
|
+
export function isTerminal(status) {
|
|
165
|
+
return TERMINAL_ACK.includes(status);
|
|
166
|
+
}
|
|
167
|
+
/** The intent the agent switches on: explicit intent, else the action id. */
|
|
168
|
+
export function intentOf(action) {
|
|
169
|
+
return action.intent ?? action.id;
|
|
170
|
+
}
|
|
171
|
+
/** May a viewer with this team role press this action? */
|
|
172
|
+
export function roleMayAct(action, role) {
|
|
173
|
+
if (!role)
|
|
174
|
+
return false;
|
|
175
|
+
const allowed = action.roles ?? DEFAULT_ACTION_ROLES;
|
|
176
|
+
return allowed.includes(role);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Check ONE request against the action it names: every declared field is
|
|
180
|
+
* coerced and range/option-checked, undeclared inputs are dropped (never
|
|
181
|
+
* forwarded to the agent), and a danger action demands a typed reason.
|
|
182
|
+
* The server's authority; the component runs it too so the viewer sees the
|
|
183
|
+
* same message before a round-trip (`fieldsOnly` = check the form before
|
|
184
|
+
* the danger confirm opens, when no reason has been typed yet).
|
|
185
|
+
*/
|
|
186
|
+
export function validateActionRequest(action, rawInputs, rawReason, opts = {}) {
|
|
187
|
+
const given = typeof rawInputs === "object" &&
|
|
188
|
+
rawInputs !== null &&
|
|
189
|
+
!Array.isArray(rawInputs)
|
|
190
|
+
? rawInputs
|
|
191
|
+
: {};
|
|
192
|
+
const inputs = {};
|
|
193
|
+
for (const field of action.fields) {
|
|
194
|
+
const raw = given[field.id];
|
|
195
|
+
const empty = raw === undefined ||
|
|
196
|
+
raw === null ||
|
|
197
|
+
(typeof raw === "string" && raw.trim() === "");
|
|
198
|
+
if (empty) {
|
|
199
|
+
if (field.required)
|
|
200
|
+
return { ok: false, error: `${field.label} is required` };
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (field.type === "text") {
|
|
204
|
+
if (typeof raw !== "string")
|
|
205
|
+
return { ok: false, error: `${field.label} must be text` };
|
|
206
|
+
const v = raw.trim();
|
|
207
|
+
if (v.length > field.maxLength)
|
|
208
|
+
return {
|
|
209
|
+
ok: false,
|
|
210
|
+
error: `${field.label} is longer than ${field.maxLength} characters`,
|
|
211
|
+
};
|
|
212
|
+
inputs[field.id] = v;
|
|
213
|
+
}
|
|
214
|
+
else if (field.type === "number") {
|
|
215
|
+
const n = typeof raw === "number" ? raw : Number(String(raw).trim());
|
|
216
|
+
if (!Number.isFinite(n))
|
|
217
|
+
return { ok: false, error: `${field.label} must be a number` };
|
|
218
|
+
if (field.min !== undefined && n < field.min)
|
|
219
|
+
return {
|
|
220
|
+
ok: false,
|
|
221
|
+
error: `${field.label} must be at least ${field.min}`,
|
|
222
|
+
};
|
|
223
|
+
if (field.max !== undefined && n > field.max)
|
|
224
|
+
return {
|
|
225
|
+
ok: false,
|
|
226
|
+
error: `${field.label} must be at most ${field.max}`,
|
|
227
|
+
};
|
|
228
|
+
inputs[field.id] = n;
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
if (typeof raw !== "string" ||
|
|
232
|
+
!field.options.some((o) => o.value === raw))
|
|
233
|
+
return { ok: false, error: `${field.label}: pick one of the options` };
|
|
234
|
+
inputs[field.id] = raw;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
let reason = null;
|
|
238
|
+
if (action.variant === "danger" && !opts.fieldsOnly) {
|
|
239
|
+
const r = typeof rawReason === "string" ? rawReason.trim() : "";
|
|
240
|
+
if (r.length < MIN_DANGER_REASON)
|
|
241
|
+
return {
|
|
242
|
+
ok: false,
|
|
243
|
+
error: "This action needs a reason (a few words on why) before it is sent",
|
|
244
|
+
};
|
|
245
|
+
if (r.length > MAX_DANGER_REASON)
|
|
246
|
+
return {
|
|
247
|
+
ok: false,
|
|
248
|
+
error: `The reason is longer than ${MAX_DANGER_REASON} characters`,
|
|
249
|
+
};
|
|
250
|
+
reason = r;
|
|
251
|
+
}
|
|
252
|
+
return { ok: true, inputs, reason };
|
|
253
|
+
}
|