@terreno/blocks 57.10.1
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/LICENSE +21 -0
- package/README.md +62 -0
- package/biome.jsonc +18 -0
- package/bunfig.toml +6 -0
- package/dist/asks/errors.d.ts +77 -0
- package/dist/asks/errors.js +364 -0
- package/dist/asks/files.d.ts +53 -0
- package/dist/asks/files.js +171 -0
- package/dist/asks/formValues.d.ts +32 -0
- package/dist/asks/formValues.js +229 -0
- package/dist/asks/headless.d.ts +227 -0
- package/dist/asks/headless.js +94 -0
- package/dist/asks/jsonSchema.d.ts +6 -0
- package/dist/asks/jsonSchema.js +62 -0
- package/dist/asks/limits.d.ts +58 -0
- package/dist/asks/limits.js +61 -0
- package/dist/asks/prompt.d.ts +10 -0
- package/dist/asks/prompt.js +144 -0
- package/dist/asks/schema.d.ts +826 -0
- package/dist/asks/schema.js +864 -0
- package/dist/asks/simpleCard.d.ts +85 -0
- package/dist/asks/simpleCard.js +279 -0
- package/dist/asks/validateInput.d.ts +13 -0
- package/dist/asks/validateInput.js +19 -0
- package/dist/asks/validateResponse.d.ts +13 -0
- package/dist/asks/validateResponse.js +278 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +58 -0
- package/dist/errors.d.ts +51 -0
- package/dist/errors.js +106 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +111 -0
- package/dist/jsonSchema.d.ts +5 -0
- package/dist/jsonSchema.js +12 -0
- package/dist/limits.d.ts +27 -0
- package/dist/limits.js +30 -0
- package/dist/lint.d.ts +21 -0
- package/dist/lint.js +388 -0
- package/dist/parse.d.ts +16 -0
- package/dist/parse.js +95 -0
- package/dist/parsePartial.d.ts +12 -0
- package/dist/parsePartial.js +105 -0
- package/dist/prompt.d.ts +9 -0
- package/dist/prompt.js +95 -0
- package/dist/schema.d.ts +199 -0
- package/dist/schema.js +277 -0
- package/dist/validate.d.ts +17 -0
- package/dist/validate.js +331 -0
- package/package.json +60 -0
- package/schemas/pendingAsksResponse.schema.json +195 -0
- package/schemas/simpleCard.schema.json +135 -0
- package/schemas/turnRequest.schema.json +108 -0
- package/schemas/turnResponse.schema.json +204 -0
- package/scripts/writeJsonSchemas.ts +11 -0
- package/src/asks/docParity.test.ts +65 -0
- package/src/asks/errors.test.ts +250 -0
- package/src/asks/errors.ts +449 -0
- package/src/asks/files.test.ts +294 -0
- package/src/asks/files.ts +216 -0
- package/src/asks/fixtures/invalid/choice-blank-text.json +20 -0
- package/src/asks/fixtures/invalid/choice-default-not-in-options.json +13 -0
- package/src/asks/fixtures/invalid/choice-default-selects-two.json +16 -0
- package/src/asks/fixtures/invalid/choice-description-too-long.json +24 -0
- package/src/asks/fixtures/invalid/choice-duplicate-ids.json +17 -0
- package/src/asks/fixtures/invalid/choice-label-too-long.json +23 -0
- package/src/asks/fixtures/invalid/choice-many-bounds-not-whole.json +17 -0
- package/src/asks/fixtures/invalid/choice-many-bounds-out-of-range.json +17 -0
- package/src/asks/fixtures/invalid/choice-many-default-duplicate.json +17 -0
- package/src/asks/fixtures/invalid/choice-many-default-too-many.json +15 -0
- package/src/asks/fixtures/invalid/choice-many-max-above-options.json +14 -0
- package/src/asks/fixtures/invalid/choice-many-min-above-choices.json +13 -0
- package/src/asks/fixtures/invalid/choice-many-min-above-max.json +15 -0
- package/src/asks/fixtures/invalid/choice-missing-required.json +14 -0
- package/src/asks/fixtures/invalid/choice-mixed-errors.json +19 -0
- package/src/asks/fixtures/invalid/choice-not-an-object.json +5 -0
- package/src/asks/fixtures/invalid/choice-one-with-many-fields.json +19 -0
- package/src/asks/fixtures/invalid/choice-option-id-format.json +35 -0
- package/src/asks/fixtures/invalid/choice-options-not-objects.json +12 -0
- package/src/asks/fixtures/invalid/choice-other-label-too-long.json +25 -0
- package/src/asks/fixtures/invalid/choice-other-label-without-allow-other.json +14 -0
- package/src/asks/fixtures/invalid/choice-prompt-empty.json +12 -0
- package/src/asks/fixtures/invalid/choice-prompt-too-long.json +23 -0
- package/src/asks/fixtures/invalid/choice-select-unknown.json +12 -0
- package/src/asks/fixtures/invalid/choice-submit-label-too-long.json +13 -0
- package/src/asks/fixtures/invalid/choice-title-too-long.json +24 -0
- package/src/asks/fixtures/invalid/choice-too-few-options.json +9 -0
- package/src/asks/fixtures/invalid/choice-too-many-options.json +219 -0
- package/src/asks/fixtures/invalid/choice-unknown-key-option.json +15 -0
- package/src/asks/fixtures/invalid/choice-unknown-key-root.json +13 -0
- package/src/asks/fixtures/invalid/choice-wrong-types.json +16 -0
- package/src/asks/fixtures/invalid/confirm-emoji-label-too-long.json +13 -0
- package/src/asks/fixtures/invalid/confirm-label-too-long.json +14 -0
- package/src/asks/fixtures/invalid/confirm-labels-alike-after-trim.json +14 -0
- package/src/asks/fixtures/invalid/confirm-labels-alike.json +13 -0
- package/src/asks/fixtures/invalid/confirm-missing-prompt-blank-label.json +16 -0
- package/src/asks/fixtures/invalid/confirm-unknown-keys.json +23 -0
- package/src/asks/fixtures/invalid/confirm-wrong-types.json +18 -0
- package/src/asks/fixtures/invalid/files-accept-duplicate.json +13 -0
- package/src/asks/fixtures/invalid/files-accept-empty.json +13 -0
- package/src/asks/fixtures/invalid/files-accept-unknown.json +13 -0
- package/src/asks/fixtures/invalid/files-counts-out-of-range.json +19 -0
- package/src/asks/fixtures/invalid/files-min-above-max.json +15 -0
- package/src/asks/fixtures/invalid/files-missing-accept-unknown-key.json +17 -0
- package/src/asks/fixtures/invalid/form-default-bad-format.json +40 -0
- package/src/asks/fixtures/invalid/form-default-invalid-date.json +40 -0
- package/src/asks/fixtures/invalid/form-default-not-in-options.json +58 -0
- package/src/asks/fixtures/invalid/form-default-out-of-range.json +33 -0
- package/src/asks/fixtures/invalid/form-default-text-bounds.json +42 -0
- package/src/asks/fixtures/invalid/form-default-wrong-type.json +30 -0
- package/src/asks/fixtures/invalid/form-duplicate-field-ids.json +24 -0
- package/src/asks/fixtures/invalid/form-field-id-format.json +19 -0
- package/src/asks/fixtures/invalid/form-field-text-limits.json +33 -0
- package/src/asks/fixtures/invalid/form-keys-of-another-type.json +39 -0
- package/src/asks/fixtures/invalid/form-length-above-cap.json +30 -0
- package/src/asks/fixtures/invalid/form-min-above-max.json +32 -0
- package/src/asks/fixtures/invalid/form-no-fields.json +13 -0
- package/src/asks/fixtures/invalid/form-select-options.json +44 -0
- package/src/asks/fixtures/invalid/form-too-many-fields.json +59 -0
- package/src/asks/fixtures/invalid/form-unknown-field-type.json +27 -0
- package/src/asks/fixtures/invalid/markdown-bounds-out-of-range.json +18 -0
- package/src/asks/fixtures/invalid/markdown-initial-above-cap.json +13 -0
- package/src/asks/fixtures/invalid/markdown-max-above-cap.json +13 -0
- package/src/asks/fixtures/invalid/markdown-min-above-cap.json +13 -0
- package/src/asks/fixtures/invalid/markdown-min-above-max.json +14 -0
- package/src/asks/fixtures/invalid/markdown-placeholder-too-long.json +13 -0
- package/src/asks/fixtures/invalid/markdown-wrong-types-unknown-key.json +27 -0
- package/src/asks/fixtures/valid/choice-emoji-label-cut.json +32 -0
- package/src/asks/fixtures/valid/choice-labels-collide-after-cut.json +21 -0
- package/src/asks/fixtures/valid/choice-long-text-cut.json +41 -0
- package/src/asks/fixtures/valid/choice-many-default-below-min.json +24 -0
- package/src/asks/fixtures/valid/choice-many-every-choice-with-other.json +24 -0
- package/src/asks/fixtures/valid/choice-many-no-default.json +21 -0
- package/src/asks/fixtures/valid/choice-many-optional-no-buttons.json +20 -0
- package/src/asks/fixtures/valid/choice-many-options-default-label-collides.json +23 -0
- package/src/asks/fixtures/valid/choice-many-options-no-buttons.json +21 -0
- package/src/asks/fixtures/valid/choice-many-options-no-default.json +22 -0
- package/src/asks/fixtures/valid/choice-many-options-with-default.json +30 -0
- package/src/asks/fixtures/valid/choice-many-required-with-default.json +29 -0
- package/src/asks/fixtures/valid/choice-many-single-pick-or-other.json +29 -0
- package/src/asks/fixtures/valid/choice-many-toppings-with-default.json +36 -0
- package/src/asks/fixtures/valid/choice-max-limits.json +245 -0
- package/src/asks/fixtures/valid/choice-plan-with-default.json +42 -0
- package/src/asks/fixtures/valid/choice-two-options-no-decline.json +32 -0
- package/src/asks/fixtures/valid/choice-two-options.json +32 -0
- package/src/asks/fixtures/valid/confirm-allow-decline.json +40 -0
- package/src/asks/fixtures/valid/confirm-default-labels.json +36 -0
- package/src/asks/fixtures/valid/confirm-destructive-delete.json +41 -0
- package/src/asks/fixtures/valid/confirm-emoji-labels.json +38 -0
- package/src/asks/fixtures/valid/confirm-long-text-cut.json +40 -0
- package/src/asks/fixtures/valid/files-every-type.json +28 -0
- package/src/asks/fixtures/valid/files-one-csv-no-decline.json +16 -0
- package/src/asks/fixtures/valid/files-receipt-photos.json +24 -0
- package/src/asks/fixtures/valid/form-boolean-newsletter.json +30 -0
- package/src/asks/fixtures/valid/form-date-due.json +44 -0
- package/src/asks/fixtures/valid/form-datetime-meeting.json +44 -0
- package/src/asks/fixtures/valid/form-datetime-minutes-offset.json +44 -0
- package/src/asks/fixtures/valid/form-eight-fields.json +71 -0
- package/src/asks/fixtures/valid/form-email-contact.json +44 -0
- package/src/asks/fixtures/valid/form-invoice-details.json +68 -0
- package/src/asks/fixtures/valid/form-multiselect-channels.json +64 -0
- package/src/asks/fixtures/valid/form-number-budget.json +45 -0
- package/src/asks/fixtures/valid/form-phone-callback.json +44 -0
- package/src/asks/fixtures/valid/form-select-shipping.json +58 -0
- package/src/asks/fixtures/valid/form-text-required-default.json +47 -0
- package/src/asks/fixtures/valid/form-textarea-notes.json +23 -0
- package/src/asks/fixtures/valid/form-time-reminder.json +44 -0
- package/src/asks/fixtures/valid/form-url-website.json +30 -0
- package/src/asks/fixtures/valid/markdown-announcement-draft.json +39 -0
- package/src/asks/fixtures/valid/markdown-empty-draft.json +34 -0
- package/src/asks/fixtures/valid/markdown-initial-blank-below-min.json +24 -0
- package/src/asks/fixtures/valid/markdown-initial-over-max.json +24 -0
- package/src/asks/fixtures/valid/markdown-long-text-cut.json +37 -0
- package/src/asks/fixtures/valid/markdown-no-decline.json +28 -0
- package/src/asks/fixtures/valid/markdown-no-initial-with-min.json +25 -0
- package/src/asks/formValues.ts +320 -0
- package/src/asks/headless.test.ts +146 -0
- package/src/asks/headless.ts +130 -0
- package/src/asks/jsonSchema.test.ts +171 -0
- package/src/asks/jsonSchema.ts +89 -0
- package/src/asks/limits.ts +58 -0
- package/src/asks/prompt.test.ts +200 -0
- package/src/asks/prompt.ts +173 -0
- package/src/asks/schema.test.ts +198 -0
- package/src/asks/schema.ts +1203 -0
- package/src/asks/simpleCard.test.ts +998 -0
- package/src/asks/simpleCard.ts +341 -0
- package/src/asks/validateInput.test.ts +875 -0
- package/src/asks/validateInput.ts +24 -0
- package/src/asks/validateResponse.test.ts +740 -0
- package/src/asks/validateResponse.ts +341 -0
- package/src/blocksDocParity.test.ts +21 -0
- package/src/cli.test.ts +134 -0
- package/src/cli.ts +65 -0
- package/src/display.test.ts +68 -0
- package/src/errors.test.ts +29 -0
- package/src/errors.ts +125 -0
- package/src/fixtures/invalid/column-not-found.yaml +14 -0
- package/src/fixtures/invalid/column-type.yaml +14 -0
- package/src/fixtures/invalid/dataset-not-found.yaml +7 -0
- package/src/fixtures/invalid/dataset-too-large.yaml +20 -0
- package/src/fixtures/invalid/depth-exceeded.yaml +10 -0
- package/src/fixtures/invalid/duplicate-id.yaml +6 -0
- package/src/fixtures/invalid/invalid-enum.yaml +5 -0
- package/src/fixtures/invalid/key-order.yaml +4 -0
- package/src/fixtures/invalid/missing-required.yaml +3 -0
- package/src/fixtures/invalid/not-a-document.txt +1 -0
- package/src/fixtures/invalid/row-arity.yaml +11 -0
- package/src/fixtures/invalid/select-target.yaml +12 -0
- package/src/fixtures/invalid/table-too-wide.yaml +9 -0
- package/src/fixtures/invalid/too-many-points.yaml +8 -0
- package/src/fixtures/invalid/unknown-key.yaml +5 -0
- package/src/fixtures/invalid/unsupported-version.yaml +4 -0
- package/src/fixtures/invalid/yaml-anchor.yaml +6 -0
- package/src/fixtures/partial/cut-after-divider.yaml +5 -0
- package/src/fixtures/valid/actions.yaml +32 -0
- package/src/fixtures/valid/chart.yaml +20 -0
- package/src/fixtures/valid/layout.yaml +26 -0
- package/src/fixtures/valid/prose.yaml +4 -0
- package/src/html.test.ts +52 -0
- package/src/index.test.ts +114 -0
- package/src/index.ts +175 -0
- package/src/jsonSchema.test.ts +33 -0
- package/src/jsonSchema.ts +11 -0
- package/src/limits.ts +27 -0
- package/src/lint.test.ts +289 -0
- package/src/lint.ts +484 -0
- package/src/parse.test.ts +281 -0
- package/src/parse.ts +104 -0
- package/src/parsePartial.test.ts +53 -0
- package/src/parsePartial.ts +116 -0
- package/src/prompt.test.ts +24 -0
- package/src/prompt.ts +104 -0
- package/src/schema.ts +509 -0
- package/src/tests/askFixtures.ts +40 -0
- package/src/validate.perf.test.ts +43 -0
- package/src/validate.ts +369 -0
- package/tsconfig.json +18 -0
package/src/errors.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/** Error codes for whole-reply documents. Warnings never block rendering. */
|
|
2
|
+
export const BLOCK_ERROR_CODES = {
|
|
3
|
+
COLUMN_NOT_FOUND: "A chart or table names a column the dataset does not have.",
|
|
4
|
+
COLUMN_TYPE_MISMATCH: "A column value does not match the column type.",
|
|
5
|
+
DATASET_NOT_FOUND: "A chart or table names a dataset the document does not define.",
|
|
6
|
+
DATASET_TOO_LARGE: "A dataset has more rows or columns than allowed.",
|
|
7
|
+
DEPTH_EXCEEDED: "A columns or card block is nested inside another columns or card block.",
|
|
8
|
+
DUPLICATE_ID: "An id or a column name is used more than once.",
|
|
9
|
+
HTML_DISABLED: "An html block is present and this host has not turned HTML on.",
|
|
10
|
+
HTML_TOO_LARGE: "An html block is larger than 100,000 bytes.",
|
|
11
|
+
IMAGE_HOST_NOT_ALLOWED:
|
|
12
|
+
"An image URL is not a data:image URL, a file: ref, or an https URL on an allowed host.",
|
|
13
|
+
INVALID_ENUM: "A value is not one of the allowed values.",
|
|
14
|
+
INVALID_FORMAT: "A string does not match its required format.",
|
|
15
|
+
INVALID_TYPE: "A value has the wrong type.",
|
|
16
|
+
KEY_ORDER: "Top-level keys are not in the order v, datasets, blocks.",
|
|
17
|
+
MISSING_REQUIRED: "A required field is missing.",
|
|
18
|
+
NOT_A_DOCUMENT: "The reply is not one YAML or JSON mapping with a v field.",
|
|
19
|
+
ROW_ARITY_MISMATCH: "A dataset row does not have one value per column.",
|
|
20
|
+
SELECT_TARGET_INVALID: "A select action names a block that is not a chart or table.",
|
|
21
|
+
TABLE_TOO_WIDE: "A table lists more columns than allowed.",
|
|
22
|
+
TOO_FEW: "A list has fewer items than allowed.",
|
|
23
|
+
TOO_LONG: "A string is longer than allowed.",
|
|
24
|
+
TOO_MANY: "A list has more items than allowed.",
|
|
25
|
+
TOO_MANY_BLOCKS: "The document has more than the maximum number of blocks.",
|
|
26
|
+
TOO_MANY_POINTS: "A ref dataset asks for more rendered rows than allowed.",
|
|
27
|
+
TOO_SHORT: "A string is empty or only whitespace.",
|
|
28
|
+
UNKNOWN_HOST_ACTION: "A callback names a host action that is not registered.",
|
|
29
|
+
UNKNOWN_KEY: "An object has a field that its schema does not define.",
|
|
30
|
+
UNSUPPORTED_VERSION: "The document version is not 1.",
|
|
31
|
+
YAML_FEATURE_DISALLOWED: "The document uses a YAML anchor, alias, or custom tag.",
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
/** Chart heuristics. They ride along on a valid document and do not block rendering. */
|
|
35
|
+
export const BLOCK_WARNING_CODES = {
|
|
36
|
+
BAR_TOO_MANY_CATEGORIES: "A bar chart has more categories than fit comfortably.",
|
|
37
|
+
DONUT_TOO_MANY_SLICES: "A donut chart has more slices than fit comfortably.",
|
|
38
|
+
LINE_SINGLE_POINT: "A line chart has only one point.",
|
|
39
|
+
} as const;
|
|
40
|
+
|
|
41
|
+
export type BlockWarningCode = keyof typeof BLOCK_WARNING_CODES;
|
|
42
|
+
|
|
43
|
+
export type BlockErrorCode = keyof typeof BLOCK_ERROR_CODES;
|
|
44
|
+
|
|
45
|
+
export interface BlockError {
|
|
46
|
+
/** A key of `BLOCK_ERROR_CODES` or `BLOCK_WARNING_CODES`. */
|
|
47
|
+
code: BlockErrorCode | BlockWarningCode;
|
|
48
|
+
/** One instruction that fixes the error. */
|
|
49
|
+
fix: string;
|
|
50
|
+
/** What is wrong, in one sentence. */
|
|
51
|
+
message: string;
|
|
52
|
+
/** Where the error is, such as `blocks[0].text`. The root is an empty string. */
|
|
53
|
+
path: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const formatBlockPath = (segments: readonly PropertyKey[]): string =>
|
|
57
|
+
segments.reduce<string>((path, segment) => {
|
|
58
|
+
if (typeof segment === "number") {
|
|
59
|
+
return `${path}[${segment}]`;
|
|
60
|
+
}
|
|
61
|
+
const key = String(segment);
|
|
62
|
+
if (path === "") {
|
|
63
|
+
return key;
|
|
64
|
+
}
|
|
65
|
+
return `${path}.${key}`;
|
|
66
|
+
}, "");
|
|
67
|
+
|
|
68
|
+
const pathIndex = (segment: string): number | string => {
|
|
69
|
+
const index = Number(segment);
|
|
70
|
+
if (segment !== "" && String(index) === segment) {
|
|
71
|
+
return index;
|
|
72
|
+
}
|
|
73
|
+
return segment;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** Splits `blocks[0].text` into comparable pieces so indexes sort numerically. */
|
|
77
|
+
const blockPathSegments = (path: string): readonly (string | number)[] => {
|
|
78
|
+
const parts: (string | number)[] = [];
|
|
79
|
+
const pattern = /([^[\].]+)|\[(\d+)\]/g;
|
|
80
|
+
for (const match of path.matchAll(pattern)) {
|
|
81
|
+
const index = match[2];
|
|
82
|
+
if (index !== undefined) {
|
|
83
|
+
parts.push(pathIndex(index));
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const key = match[1];
|
|
87
|
+
if (key !== undefined) {
|
|
88
|
+
parts.push(key);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return parts;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const compareBlockPaths = (left: string, right: string): number => {
|
|
95
|
+
const leftParts = blockPathSegments(left);
|
|
96
|
+
const rightParts = blockPathSegments(right);
|
|
97
|
+
const length = Math.max(leftParts.length, rightParts.length);
|
|
98
|
+
for (let index = 0; index < length; index += 1) {
|
|
99
|
+
const leftPart = leftParts[index];
|
|
100
|
+
const rightPart = rightParts[index];
|
|
101
|
+
if (leftPart === undefined) {
|
|
102
|
+
return -1;
|
|
103
|
+
}
|
|
104
|
+
if (rightPart === undefined) {
|
|
105
|
+
return 1;
|
|
106
|
+
}
|
|
107
|
+
if (leftPart === rightPart) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (typeof leftPart === "number" && typeof rightPart === "number") {
|
|
111
|
+
return leftPart - rightPart;
|
|
112
|
+
}
|
|
113
|
+
return String(leftPart) < String(rightPart) ? -1 : 1;
|
|
114
|
+
}
|
|
115
|
+
return 0;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const sortBlockErrors = (errors: readonly BlockError[]): BlockError[] =>
|
|
119
|
+
[...errors].sort((left, right) => {
|
|
120
|
+
const byPath = compareBlockPaths(left.path, right.path);
|
|
121
|
+
if (byPath !== 0) {
|
|
122
|
+
return byPath;
|
|
123
|
+
}
|
|
124
|
+
return left.code < right.code ? -1 : 1;
|
|
125
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
v: 1
|
|
2
|
+
datasets:
|
|
3
|
+
signups:
|
|
4
|
+
columns:
|
|
5
|
+
- {name: a, type: string}
|
|
6
|
+
- {name: b, type: string}
|
|
7
|
+
- {name: c, type: string}
|
|
8
|
+
- {name: d, type: string}
|
|
9
|
+
- {name: e, type: string}
|
|
10
|
+
- {name: f, type: string}
|
|
11
|
+
- {name: g, type: string}
|
|
12
|
+
- {name: h, type: string}
|
|
13
|
+
- {name: i, type: string}
|
|
14
|
+
- {name: j, type: string}
|
|
15
|
+
- {name: k, type: string}
|
|
16
|
+
- {name: l, type: string}
|
|
17
|
+
- {name: m, type: string}
|
|
18
|
+
rows: []
|
|
19
|
+
blocks:
|
|
20
|
+
- type: divider
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Just a sentence, not a document.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
v: 1
|
|
2
|
+
blocks:
|
|
3
|
+
- type: chart
|
|
4
|
+
id: signups_chart
|
|
5
|
+
kind: bar
|
|
6
|
+
points:
|
|
7
|
+
- label: Jan
|
|
8
|
+
value: 120
|
|
9
|
+
- type: actions
|
|
10
|
+
id: followups
|
|
11
|
+
elements:
|
|
12
|
+
- type: button
|
|
13
|
+
id: weekly
|
|
14
|
+
text: Show weekly
|
|
15
|
+
action:
|
|
16
|
+
kind: reply
|
|
17
|
+
text: Show weekly signups for this quarter
|
|
18
|
+
- type: button
|
|
19
|
+
id: open_report
|
|
20
|
+
text: Open report
|
|
21
|
+
variant: outline
|
|
22
|
+
action:
|
|
23
|
+
kind: open
|
|
24
|
+
route: /reports
|
|
25
|
+
- type: segmented
|
|
26
|
+
id: grain
|
|
27
|
+
target: signups_chart
|
|
28
|
+
options:
|
|
29
|
+
- label: Month
|
|
30
|
+
data: signups
|
|
31
|
+
- label: Week
|
|
32
|
+
data: signups_weekly
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
v: 1
|
|
2
|
+
datasets:
|
|
3
|
+
signups:
|
|
4
|
+
columns:
|
|
5
|
+
- {name: month, type: string}
|
|
6
|
+
- {name: count, type: number}
|
|
7
|
+
rows:
|
|
8
|
+
- [Jan, 120]
|
|
9
|
+
- [Feb, 145]
|
|
10
|
+
blocks:
|
|
11
|
+
- type: chart
|
|
12
|
+
id: signups_chart
|
|
13
|
+
kind: bar
|
|
14
|
+
data: signups
|
|
15
|
+
x: month
|
|
16
|
+
y: count
|
|
17
|
+
title: Signups by month
|
|
18
|
+
- type: table
|
|
19
|
+
data: signups
|
|
20
|
+
columns: [month, count]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
v: 1
|
|
2
|
+
blocks:
|
|
3
|
+
- type: heading
|
|
4
|
+
text: Signups this quarter
|
|
5
|
+
size: lg
|
|
6
|
+
- type: text
|
|
7
|
+
markdown: Signups grew **12%** quarter over quarter.
|
|
8
|
+
- type: columns
|
|
9
|
+
children:
|
|
10
|
+
- type: metric
|
|
11
|
+
label: Total
|
|
12
|
+
value: "403"
|
|
13
|
+
delta: "+12%"
|
|
14
|
+
trend: up
|
|
15
|
+
- type: metric
|
|
16
|
+
label: Best month
|
|
17
|
+
value: Feb
|
|
18
|
+
- type: card
|
|
19
|
+
title: Notes
|
|
20
|
+
children:
|
|
21
|
+
- type: badge
|
|
22
|
+
text: Draft
|
|
23
|
+
status: info
|
|
24
|
+
- type: context
|
|
25
|
+
text: February was the strongest month.
|
|
26
|
+
- type: divider
|
package/src/html.test.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import {describe, expect, it} from "bun:test";
|
|
2
|
+
|
|
3
|
+
import {BLOCK_LIMITS} from "./limits";
|
|
4
|
+
import {blocksPromptSection} from "./prompt";
|
|
5
|
+
import {validateBlocks} from "./validate";
|
|
6
|
+
|
|
7
|
+
const htmlDocument = (html: string): unknown => {
|
|
8
|
+
const block: Record<string, unknown> = {};
|
|
9
|
+
block.type = "html";
|
|
10
|
+
block.title = "Invoice preview";
|
|
11
|
+
block.height = "md";
|
|
12
|
+
block.html = html;
|
|
13
|
+
const doc: Record<string, unknown> = {};
|
|
14
|
+
doc.v = 1;
|
|
15
|
+
doc.blocks = [block];
|
|
16
|
+
return doc;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe("html blocks", () => {
|
|
20
|
+
it("rejects html unless the host turns it on", () => {
|
|
21
|
+
const result = validateBlocks(htmlDocument("<p>Invoice</p>"));
|
|
22
|
+
|
|
23
|
+
expect(result.ok).toBe(false);
|
|
24
|
+
if (!result.ok) {
|
|
25
|
+
expect(result.errors.map((error) => error.code)).toContain("HTML_DISABLED");
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("accepts a short html block when HTML is on", () => {
|
|
30
|
+
const result = validateBlocks(htmlDocument("<h1>Invoice #1042</h1>"), {allowHtml: true});
|
|
31
|
+
|
|
32
|
+
expect(result.ok).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("accepts html at 100,000 bytes and rejects one more byte", () => {
|
|
36
|
+
const atLimit = "a".repeat(BLOCK_LIMITS.htmlMaxBytes);
|
|
37
|
+
const over = `${atLimit}b`;
|
|
38
|
+
|
|
39
|
+
expect(validateBlocks(htmlDocument(atLimit), {allowHtml: true}).ok).toBe(true);
|
|
40
|
+
const result = validateBlocks(htmlDocument(over), {allowHtml: true});
|
|
41
|
+
expect(result.ok).toBe(false);
|
|
42
|
+
if (!result.ok) {
|
|
43
|
+
expect(result.errors.map((error) => error.code)).toContain("HTML_TOO_LARGE");
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("mentions html in the prompt only when it is allowed", () => {
|
|
48
|
+
expect(blocksPromptSection()).toContain("Do not emit type html");
|
|
49
|
+
expect(blocksPromptSection({allowHtml: true})).toContain("card, html");
|
|
50
|
+
expect(blocksPromptSection({allowHtml: true})).toContain(String(BLOCK_LIMITS.htmlMaxBytes));
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import {describe, expect, it} from "bun:test";
|
|
2
|
+
|
|
3
|
+
import * as terrenoBlocks from "./index";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Guards the public entrypoint of @terreno/blocks: a missing or renamed export here breaks
|
|
7
|
+
* @terreno/ai, @terreno/ui, and apps, and the per-module tests import the modules directly.
|
|
8
|
+
*/
|
|
9
|
+
describe("@terreno/blocks public exports", () => {
|
|
10
|
+
const expectedExports = [
|
|
11
|
+
"BADGE_STATUSES",
|
|
12
|
+
"BLOCK_ERROR_CODES",
|
|
13
|
+
"BLOCK_LIMITS",
|
|
14
|
+
"BLOCK_WARNING_CODES",
|
|
15
|
+
"BUTTON_VARIANTS",
|
|
16
|
+
"CALLOUT_STATUSES",
|
|
17
|
+
"CHART_HEIGHTS",
|
|
18
|
+
"CHART_KINDS",
|
|
19
|
+
"DATASET_COLUMN_TYPES",
|
|
20
|
+
"DATASET_GRAINS",
|
|
21
|
+
"HEADING_SIZES",
|
|
22
|
+
"HTML_HEIGHTS",
|
|
23
|
+
"METRIC_TRENDS",
|
|
24
|
+
"blocksJsonSchema",
|
|
25
|
+
"blocksPromptSection",
|
|
26
|
+
"blocksSchema",
|
|
27
|
+
"parseBlocks",
|
|
28
|
+
"parseBlocksPartial",
|
|
29
|
+
"validateBlocks",
|
|
30
|
+
"wrapAsTextDocument",
|
|
31
|
+
|
|
32
|
+
"ASK_ERROR_CODES",
|
|
33
|
+
|
|
34
|
+
"ASK_FILE_ACCEPT",
|
|
35
|
+
"ASK_FILE_ACCEPT_MIME_TYPES",
|
|
36
|
+
"acceptedFileMimeTypes",
|
|
37
|
+
"checkAskFileBytes",
|
|
38
|
+
"fileNotOwnedError",
|
|
39
|
+
"isTextFileMimeType",
|
|
40
|
+
"parseAskDataUrl",
|
|
41
|
+
"sniffFileBytes",
|
|
42
|
+
|
|
43
|
+
"askResponseWithToolCallIdSchema",
|
|
44
|
+
"askSurfaceSchema",
|
|
45
|
+
"pendingAskListItemSchema",
|
|
46
|
+
"pendingAskListSchema",
|
|
47
|
+
"pendingAskSummarySchema",
|
|
48
|
+
"turnRequestSchema",
|
|
49
|
+
"turnResultSchema",
|
|
50
|
+
|
|
51
|
+
"askJsonSchemas",
|
|
52
|
+
|
|
53
|
+
"formDefaultValues",
|
|
54
|
+
"formTextMaxLength",
|
|
55
|
+
|
|
56
|
+
"ASK_LIMITS",
|
|
57
|
+
|
|
58
|
+
"askPromptSection",
|
|
59
|
+
|
|
60
|
+
"ASK_CANCEL_REASONS",
|
|
61
|
+
"ASK_KINDS",
|
|
62
|
+
"ASK_SURFACES",
|
|
63
|
+
"CHOICE_SELECT_MODES",
|
|
64
|
+
"COMPACT_ASK_KINDS",
|
|
65
|
+
"askAcceptResponseSchema",
|
|
66
|
+
"askAllowsDecline",
|
|
67
|
+
"askCancelResponseSchema",
|
|
68
|
+
"askDeclineResponseSchema",
|
|
69
|
+
"askInputSchemaFor",
|
|
70
|
+
"askInputSchemas",
|
|
71
|
+
"askKindsForSurface",
|
|
72
|
+
"askOutputSchemas",
|
|
73
|
+
"askResponseSchema",
|
|
74
|
+
"choiceAnswerSchema",
|
|
75
|
+
"choiceAskInputSchema",
|
|
76
|
+
"choiceAskResponseSchema",
|
|
77
|
+
"choiceOptionSchema",
|
|
78
|
+
"choiceSelectionBounds",
|
|
79
|
+
"compactAskInputSchemas",
|
|
80
|
+
"compactChoiceAskInputSchema",
|
|
81
|
+
"confirmAnswerSchema",
|
|
82
|
+
"confirmAskInputSchema",
|
|
83
|
+
"confirmAskResponseSchema",
|
|
84
|
+
"confirmButtonLabels",
|
|
85
|
+
"FORM_FIELD_TYPES",
|
|
86
|
+
"askFileRefSchema",
|
|
87
|
+
"filesAnswerSchema",
|
|
88
|
+
"filesAskInputSchema",
|
|
89
|
+
"filesAskResponseSchema",
|
|
90
|
+
"filesCountBounds",
|
|
91
|
+
"formAnswerSchema",
|
|
92
|
+
"formAskInputSchema",
|
|
93
|
+
"formAskResponseSchema",
|
|
94
|
+
"formFieldSchema",
|
|
95
|
+
"isCompactAskKind",
|
|
96
|
+
"markdownAnswerSchema",
|
|
97
|
+
"markdownAskInputSchema",
|
|
98
|
+
"markdownAskResponseSchema",
|
|
99
|
+
"markdownLengthBounds",
|
|
100
|
+
|
|
101
|
+
"SIMPLE_CARD_BUTTON_STYLES",
|
|
102
|
+
"resolveButtonAnswer",
|
|
103
|
+
"simpleCardButtonSchema",
|
|
104
|
+
"simpleCardSchema",
|
|
105
|
+
"toSimpleCard",
|
|
106
|
+
|
|
107
|
+
"validateAskInput",
|
|
108
|
+
"validateAskResponse",
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
it("exports exactly the public runtime API", () => {
|
|
112
|
+
expect(Object.keys(terrenoBlocks).sort()).toEqual([...expectedExports].sort());
|
|
113
|
+
});
|
|
114
|
+
});
|