@elastic/isomer-sdk 0.0.0 → 0.2.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/LICENSE.txt +93 -0
- package/NOTICE.txt +1861 -0
- package/README.md +69 -0
- package/THIRD_PARTY_LICENSES.md +957 -0
- package/dist/author/authored_fields.d.ts +153 -0
- package/dist/author/authored_fields.d.ts.map +1 -0
- package/dist/author/authored_fields.js +227 -0
- package/dist/author/authored_fields.js.map +1 -0
- package/dist/author/authoring_input.d.ts +7 -0
- package/dist/author/authoring_input.d.ts.map +1 -0
- package/dist/author/authoring_input.js +60 -0
- package/dist/author/authoring_input.js.map +1 -0
- package/dist/author/authoring_model.d.ts +27 -0
- package/dist/author/authoring_model.d.ts.map +1 -0
- package/dist/author/authoring_model.js +98 -0
- package/dist/author/authoring_model.js.map +1 -0
- package/dist/author/declarations.d.ts +13 -0
- package/dist/author/declarations.d.ts.map +1 -0
- package/dist/author/declarations.js +277 -0
- package/dist/author/declarations.js.map +1 -0
- package/dist/author/index.d.ts +7 -0
- package/dist/author/index.d.ts.map +1 -0
- package/dist/author/index.js +12 -0
- package/dist/author/index.js.map +1 -0
- package/dist/author/jsx.d.ts +21 -0
- package/dist/author/jsx.d.ts.map +1 -0
- package/dist/author/jsx.js +20 -0
- package/dist/author/jsx.js.map +1 -0
- package/dist/author/jsx_shim.d.ts +117 -0
- package/dist/author/jsx_shim.d.ts.map +1 -0
- package/dist/author/jsx_shim.js +270 -0
- package/dist/author/jsx_shim.js.map +1 -0
- package/dist/author/prompt.d.ts +58 -0
- package/dist/author/prompt.d.ts.map +1 -0
- package/dist/author/prompt.js +148 -0
- package/dist/author/prompt.js.map +1 -0
- package/dist/author/schema_to_typescript.d.ts +37 -0
- package/dist/author/schema_to_typescript.d.ts.map +1 -0
- package/dist/author/schema_to_typescript.js +286 -0
- package/dist/author/schema_to_typescript.js.map +1 -0
- package/dist/cjs/author/authored_fields.js +233 -0
- package/dist/cjs/author/authored_fields.js.map +1 -0
- package/dist/cjs/author/authoring_input.js +64 -0
- package/dist/cjs/author/authoring_input.js.map +1 -0
- package/dist/cjs/author/authoring_model.js +104 -0
- package/dist/cjs/author/authoring_model.js.map +1 -0
- package/dist/cjs/author/declarations.js +281 -0
- package/dist/cjs/author/declarations.js.map +1 -0
- package/dist/cjs/author/index.js +25 -0
- package/dist/cjs/author/index.js.map +1 -0
- package/dist/cjs/author/jsx.js +24 -0
- package/dist/cjs/author/jsx.js.map +1 -0
- package/dist/cjs/author/jsx_shim.js +276 -0
- package/dist/cjs/author/jsx_shim.js.map +1 -0
- package/dist/cjs/author/prompt.js +153 -0
- package/dist/cjs/author/prompt.js.map +1 -0
- package/dist/cjs/author/schema_to_typescript.js +295 -0
- package/dist/cjs/author/schema_to_typescript.js.map +1 -0
- package/dist/cjs/composition/action_event.js +9 -0
- package/dist/cjs/composition/action_event.js.map +1 -0
- package/dist/cjs/composition/body_node_base.js +112 -0
- package/dist/cjs/composition/body_node_base.js.map +1 -0
- package/dist/cjs/composition/composition.js +9 -0
- package/dist/cjs/composition/composition.js.map +1 -0
- package/dist/cjs/composition/error.js +73 -0
- package/dist/cjs/composition/error.js.map +1 -0
- package/dist/cjs/composition/index.js +32 -0
- package/dist/cjs/composition/index.js.map +1 -0
- package/dist/cjs/composition/map_nodes.js +85 -0
- package/dist/cjs/composition/map_nodes.js.map +1 -0
- package/dist/cjs/composition/named_color.js +20 -0
- package/dist/cjs/composition/named_color.js.map +1 -0
- package/dist/cjs/composition/node.js +9 -0
- package/dist/cjs/composition/node.js.map +1 -0
- package/dist/cjs/composition/one_line.js +23 -0
- package/dist/cjs/composition/one_line.js.map +1 -0
- package/dist/cjs/composition/structured_value.js +21 -0
- package/dist/cjs/composition/structured_value.js.map +1 -0
- package/dist/cjs/composition/validation_error.js +40 -0
- package/dist/cjs/composition/validation_error.js.map +1 -0
- package/dist/cjs/define/frame.js +31 -0
- package/dist/cjs/define/frame.js.map +1 -0
- package/dist/cjs/define/index.js +31 -0
- package/dist/cjs/define/index.js.map +1 -0
- package/dist/cjs/define/markdown_content.js +12 -0
- package/dist/cjs/define/markdown_content.js.map +1 -0
- package/dist/cjs/define/primitive_example.js +26 -0
- package/dist/cjs/define/primitive_example.js.map +1 -0
- package/dist/cjs/define/primitive_icon.js +17 -0
- package/dist/cjs/define/primitive_icon.js.map +1 -0
- package/dist/cjs/define/primitive_module.js +118 -0
- package/dist/cjs/define/primitive_module.js.map +1 -0
- package/dist/cjs/define/slack_assets.js +9 -0
- package/dist/cjs/define/slack_assets.js.map +1 -0
- package/dist/cjs/define/slack_blocks.js +9 -0
- package/dist/cjs/define/slack_blocks.js.map +1 -0
- package/dist/cjs/define/zod_format.js +122 -0
- package/dist/cjs/define/zod_format.js.map +1 -0
- package/dist/cjs/define/zod_helpers.js +26 -0
- package/dist/cjs/define/zod_helpers.js.map +1 -0
- package/dist/cjs/entries/html.js +12 -0
- package/dist/cjs/entries/html.js.map +1 -0
- package/dist/cjs/entries/index.js +80 -0
- package/dist/cjs/entries/index.js.map +1 -0
- package/dist/cjs/entries/markdown.js +14 -0
- package/dist/cjs/entries/markdown.js.map +1 -0
- package/dist/cjs/entries/react.js +20 -0
- package/dist/cjs/entries/react.js.map +1 -0
- package/dist/cjs/entries/slack.js +25 -0
- package/dist/cjs/entries/slack.js.map +1 -0
- package/dist/cjs/entries/text.js +12 -0
- package/dist/cjs/entries/text.js.map +1 -0
- package/dist/cjs/pack/capabilities.js +40 -0
- package/dist/cjs/pack/capabilities.js.map +1 -0
- package/dist/cjs/pack/compose.js +59 -0
- package/dist/cjs/pack/compose.js.map +1 -0
- package/dist/cjs/pack/enhancements.js +65 -0
- package/dist/cjs/pack/enhancements.js.map +1 -0
- package/dist/cjs/pack/index.js +18 -0
- package/dist/cjs/pack/index.js.map +1 -0
- package/dist/cjs/pack/primitive_pack.js +97 -0
- package/dist/cjs/pack/primitive_pack.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/render/anchors.js +167 -0
- package/dist/cjs/render/anchors.js.map +1 -0
- package/dist/cjs/render/context_view.js +54 -0
- package/dist/cjs/render/context_view.js.map +1 -0
- package/dist/cjs/render/format_display_value.js +143 -0
- package/dist/cjs/render/format_display_value.js.map +1 -0
- package/dist/cjs/render/format_number.js +46 -0
- package/dist/cjs/render/format_number.js.map +1 -0
- package/dist/cjs/render/html/enhancements.js +30 -0
- package/dist/cjs/render/html/enhancements.js.map +1 -0
- package/dist/cjs/render/html/envelope.js +218 -0
- package/dist/cjs/render/html/envelope.js.map +1 -0
- package/dist/cjs/render/html/index.js +12 -0
- package/dist/cjs/render/html/index.js.map +1 -0
- package/dist/cjs/render/index.js +25 -0
- package/dist/cjs/render/index.js.map +1 -0
- package/dist/cjs/render/layout_check.js +133 -0
- package/dist/cjs/render/layout_check.js.map +1 -0
- package/dist/cjs/render/markdown/builder.js +195 -0
- package/dist/cjs/render/markdown/builder.js.map +1 -0
- package/dist/cjs/render/markdown/envelope.js +33 -0
- package/dist/cjs/render/markdown/envelope.js.map +1 -0
- package/dist/cjs/render/markdown/format.js +208 -0
- package/dist/cjs/render/markdown/format.js.map +1 -0
- package/dist/cjs/render/markdown/index.js +15 -0
- package/dist/cjs/render/markdown/index.js.map +1 -0
- package/dist/cjs/render/measure_dom.js +61 -0
- package/dist/cjs/render/measure_dom.js.map +1 -0
- package/dist/cjs/render/payload.js +13 -0
- package/dist/cjs/render/payload.js.map +1 -0
- package/dist/cjs/render/primitive_dispatch.js +173 -0
- package/dist/cjs/render/primitive_dispatch.js.map +1 -0
- package/dist/cjs/render/react/content.js +44 -0
- package/dist/cjs/render/react/content.js.map +1 -0
- package/dist/cjs/render/react/enhancements.js +32 -0
- package/dist/cjs/render/react/enhancements.js.map +1 -0
- package/dist/cjs/render/react/index.js +15 -0
- package/dist/cjs/render/react/index.js.map +1 -0
- package/dist/cjs/render/slack/assets.js +45 -0
- package/dist/cjs/render/slack/assets.js.map +1 -0
- package/dist/cjs/render/slack/blocks.js +80 -0
- package/dist/cjs/render/slack/blocks.js.map +1 -0
- package/dist/cjs/render/slack/envelope.js +551 -0
- package/dist/cjs/render/slack/envelope.js.map +1 -0
- package/dist/cjs/render/slack/format.js +225 -0
- package/dist/cjs/render/slack/format.js.map +1 -0
- package/dist/cjs/render/slack/index.js +30 -0
- package/dist/cjs/render/slack/index.js.map +1 -0
- package/dist/cjs/render/slack/markdown_content.js +409 -0
- package/dist/cjs/render/slack/markdown_content.js.map +1 -0
- package/dist/cjs/render/text/envelope.js +21 -0
- package/dist/cjs/render/text/envelope.js.map +1 -0
- package/dist/cjs/render/text/index.js +12 -0
- package/dist/cjs/render/text/index.js.map +1 -0
- package/dist/cjs/testing/conformance.js +312 -0
- package/dist/cjs/testing/conformance.js.map +1 -0
- package/dist/cjs/testing/icon.js +248 -0
- package/dist/cjs/testing/icon.js.map +1 -0
- package/dist/cjs/testing/index.js +18 -0
- package/dist/cjs/testing/index.js.map +1 -0
- package/dist/cjs/testing/registration.js +142 -0
- package/dist/cjs/testing/registration.js.map +1 -0
- package/dist/cjs/validate/authoring_schema.js +312 -0
- package/dist/cjs/validate/authoring_schema.js.map +1 -0
- package/dist/cjs/validate/composition_schema.js +135 -0
- package/dist/cjs/validate/composition_schema.js.map +1 -0
- package/dist/cjs/validate/index.js +53 -0
- package/dist/cjs/validate/index.js.map +1 -0
- package/dist/cjs/validate/input_budget.js +156 -0
- package/dist/cjs/validate/input_budget.js.map +1 -0
- package/dist/cjs/validate/json_schema.js +72 -0
- package/dist/cjs/validate/json_schema.js.map +1 -0
- package/dist/cjs/validate/node_issues.js +65 -0
- package/dist/cjs/validate/node_issues.js.map +1 -0
- package/dist/cjs/validate/url.js +116 -0
- package/dist/cjs/validate/url.js.map +1 -0
- package/dist/cjs/validate/validation.js +165 -0
- package/dist/cjs/validate/validation.js.map +1 -0
- package/dist/cjs/validate/value_schemas.js +53 -0
- package/dist/cjs/validate/value_schemas.js.map +1 -0
- package/dist/composition/action_event.d.ts +13 -0
- package/dist/composition/action_event.d.ts.map +1 -0
- package/dist/composition/action_event.js +8 -0
- package/dist/composition/action_event.js.map +1 -0
- package/dist/composition/body_node_base.d.ts +72 -0
- package/dist/composition/body_node_base.d.ts.map +1 -0
- package/dist/composition/body_node_base.js +104 -0
- package/dist/composition/body_node_base.js.map +1 -0
- package/dist/composition/composition.d.ts +71 -0
- package/dist/composition/composition.d.ts.map +1 -0
- package/dist/composition/composition.js +8 -0
- package/dist/composition/composition.js.map +1 -0
- package/dist/composition/error.d.ts +61 -0
- package/dist/composition/error.d.ts.map +1 -0
- package/dist/composition/error.js +69 -0
- package/dist/composition/error.js.map +1 -0
- package/dist/composition/index.d.ts +11 -0
- package/dist/composition/index.d.ts.map +1 -0
- package/dist/composition/index.js +14 -0
- package/dist/composition/index.js.map +1 -0
- package/dist/composition/map_nodes.d.ts +16 -0
- package/dist/composition/map_nodes.d.ts.map +1 -0
- package/dist/composition/map_nodes.js +81 -0
- package/dist/composition/map_nodes.js.map +1 -0
- package/dist/composition/named_color.d.ts +9 -0
- package/dist/composition/named_color.d.ts.map +1 -0
- package/dist/composition/named_color.js +17 -0
- package/dist/composition/named_color.js.map +1 -0
- package/dist/composition/node.d.ts +11 -0
- package/dist/composition/node.d.ts.map +1 -0
- package/dist/composition/node.js +8 -0
- package/dist/composition/node.js.map +1 -0
- package/dist/composition/one_line.d.ts +7 -0
- package/dist/composition/one_line.d.ts.map +1 -0
- package/dist/composition/one_line.js +17 -0
- package/dist/composition/one_line.js.map +1 -0
- package/dist/composition/structured_value.d.ts +27 -0
- package/dist/composition/structured_value.d.ts.map +1 -0
- package/dist/composition/structured_value.js +18 -0
- package/dist/composition/structured_value.js.map +1 -0
- package/dist/composition/validation_error.d.ts +33 -0
- package/dist/composition/validation_error.d.ts.map +1 -0
- package/dist/composition/validation_error.js +35 -0
- package/dist/composition/validation_error.js.map +1 -0
- package/dist/define/frame.d.ts +155 -0
- package/dist/define/frame.d.ts.map +1 -0
- package/dist/define/frame.js +27 -0
- package/dist/define/frame.js.map +1 -0
- package/dist/define/index.d.ts +10 -0
- package/dist/define/index.d.ts.map +1 -0
- package/dist/define/index.js +13 -0
- package/dist/define/index.js.map +1 -0
- package/dist/define/markdown_content.d.ts +15 -0
- package/dist/define/markdown_content.d.ts.map +1 -0
- package/dist/define/markdown_content.js +9 -0
- package/dist/define/markdown_content.js.map +1 -0
- package/dist/define/primitive_example.d.ts +30 -0
- package/dist/define/primitive_example.d.ts.map +1 -0
- package/dist/define/primitive_example.js +21 -0
- package/dist/define/primitive_example.js.map +1 -0
- package/dist/define/primitive_icon.d.ts +11 -0
- package/dist/define/primitive_icon.d.ts.map +1 -0
- package/dist/define/primitive_icon.js +14 -0
- package/dist/define/primitive_icon.js.map +1 -0
- package/dist/define/primitive_module.d.ts +435 -0
- package/dist/define/primitive_module.d.ts.map +1 -0
- package/dist/define/primitive_module.js +112 -0
- package/dist/define/primitive_module.js.map +1 -0
- package/dist/define/slack_assets.d.ts +28 -0
- package/dist/define/slack_assets.d.ts.map +1 -0
- package/dist/define/slack_assets.js +8 -0
- package/dist/define/slack_assets.js.map +1 -0
- package/dist/define/slack_blocks.d.ts +234 -0
- package/dist/define/slack_blocks.d.ts.map +1 -0
- package/dist/define/slack_blocks.js +8 -0
- package/dist/define/slack_blocks.js.map +1 -0
- package/dist/define/zod_format.d.ts +33 -0
- package/dist/define/zod_format.d.ts.map +1 -0
- package/dist/define/zod_format.js +114 -0
- package/dist/define/zod_format.js.map +1 -0
- package/dist/define/zod_helpers.d.ts +10 -0
- package/dist/define/zod_helpers.d.ts.map +1 -0
- package/dist/define/zod_helpers.js +22 -0
- package/dist/define/zod_helpers.js.map +1 -0
- package/dist/entries/html.d.ts +3 -0
- package/dist/entries/html.d.ts.map +1 -0
- package/dist/entries/html.js +8 -0
- package/dist/entries/html.js.map +1 -0
- package/dist/entries/index.d.ts +6 -0
- package/dist/entries/index.d.ts.map +1 -0
- package/dist/entries/index.js +12 -0
- package/dist/entries/index.js.map +1 -0
- package/dist/entries/markdown.d.ts +3 -0
- package/dist/entries/markdown.d.ts.map +1 -0
- package/dist/entries/markdown.js +8 -0
- package/dist/entries/markdown.js.map +1 -0
- package/dist/entries/react.d.ts +5 -0
- package/dist/entries/react.d.ts.map +1 -0
- package/dist/entries/react.js +11 -0
- package/dist/entries/react.js.map +1 -0
- package/dist/entries/slack.d.ts +2 -0
- package/dist/entries/slack.d.ts.map +1 -0
- package/dist/entries/slack.js +8 -0
- package/dist/entries/slack.js.map +1 -0
- package/dist/entries/text.d.ts +2 -0
- package/dist/entries/text.d.ts.map +1 -0
- package/dist/entries/text.js +8 -0
- package/dist/entries/text.js.map +1 -0
- package/dist/pack/capabilities.d.ts +41 -0
- package/dist/pack/capabilities.d.ts.map +1 -0
- package/dist/pack/capabilities.js +36 -0
- package/dist/pack/capabilities.js.map +1 -0
- package/dist/pack/compose.d.ts +24 -0
- package/dist/pack/compose.d.ts.map +1 -0
- package/dist/pack/compose.js +55 -0
- package/dist/pack/compose.js.map +1 -0
- package/dist/pack/enhancements.d.ts +65 -0
- package/dist/pack/enhancements.d.ts.map +1 -0
- package/dist/pack/enhancements.js +59 -0
- package/dist/pack/enhancements.js.map +1 -0
- package/dist/pack/index.d.ts +5 -0
- package/dist/pack/index.d.ts.map +1 -0
- package/dist/pack/index.js +11 -0
- package/dist/pack/index.js.map +1 -0
- package/dist/pack/primitive_pack.d.ts +164 -0
- package/dist/pack/primitive_pack.d.ts.map +1 -0
- package/dist/pack/primitive_pack.js +92 -0
- package/dist/pack/primitive_pack.js.map +1 -0
- package/dist/render/anchors.d.ts +82 -0
- package/dist/render/anchors.d.ts.map +1 -0
- package/dist/render/anchors.js +153 -0
- package/dist/render/anchors.js.map +1 -0
- package/dist/render/context_view.d.ts +10 -0
- package/dist/render/context_view.d.ts.map +1 -0
- package/dist/render/context_view.js +49 -0
- package/dist/render/context_view.js.map +1 -0
- package/dist/render/format_display_value.d.ts +20 -0
- package/dist/render/format_display_value.d.ts.map +1 -0
- package/dist/render/format_display_value.js +137 -0
- package/dist/render/format_display_value.js.map +1 -0
- package/dist/render/format_number.d.ts +9 -0
- package/dist/render/format_number.d.ts.map +1 -0
- package/dist/render/format_number.js +42 -0
- package/dist/render/format_number.js.map +1 -0
- package/dist/render/html/enhancements.d.ts +10 -0
- package/dist/render/html/enhancements.d.ts.map +1 -0
- package/dist/render/html/enhancements.js +25 -0
- package/dist/render/html/enhancements.js.map +1 -0
- package/dist/render/html/envelope.d.ts +182 -0
- package/dist/render/html/envelope.d.ts.map +1 -0
- package/dist/render/html/envelope.js +214 -0
- package/dist/render/html/envelope.js.map +1 -0
- package/dist/render/html/index.d.ts +3 -0
- package/dist/render/html/index.d.ts.map +1 -0
- package/dist/render/html/index.js +8 -0
- package/dist/render/html/index.js.map +1 -0
- package/dist/render/index.d.ts +6 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +11 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/layout_check.d.ts +43 -0
- package/dist/render/layout_check.d.ts.map +1 -0
- package/dist/render/layout_check.js +129 -0
- package/dist/render/layout_check.js.map +1 -0
- package/dist/render/markdown/builder.d.ts +46 -0
- package/dist/render/markdown/builder.d.ts.map +1 -0
- package/dist/render/markdown/builder.js +190 -0
- package/dist/render/markdown/builder.js.map +1 -0
- package/dist/render/markdown/envelope.d.ts +20 -0
- package/dist/render/markdown/envelope.d.ts.map +1 -0
- package/dist/render/markdown/envelope.js +29 -0
- package/dist/render/markdown/envelope.js.map +1 -0
- package/dist/render/markdown/format.d.ts +10 -0
- package/dist/render/markdown/format.d.ts.map +1 -0
- package/dist/render/markdown/format.js +202 -0
- package/dist/render/markdown/format.js.map +1 -0
- package/dist/render/markdown/index.d.ts +3 -0
- package/dist/render/markdown/index.d.ts.map +1 -0
- package/dist/render/markdown/index.js +9 -0
- package/dist/render/markdown/index.js.map +1 -0
- package/dist/render/measure_dom.d.ts +10 -0
- package/dist/render/measure_dom.d.ts.map +1 -0
- package/dist/render/measure_dom.js +57 -0
- package/dist/render/measure_dom.js.map +1 -0
- package/dist/render/payload.d.ts +16 -0
- package/dist/render/payload.d.ts.map +1 -0
- package/dist/render/payload.js +9 -0
- package/dist/render/payload.js.map +1 -0
- package/dist/render/primitive_dispatch.d.ts +72 -0
- package/dist/render/primitive_dispatch.d.ts.map +1 -0
- package/dist/render/primitive_dispatch.js +169 -0
- package/dist/render/primitive_dispatch.js.map +1 -0
- package/dist/render/react/content.d.ts +40 -0
- package/dist/render/react/content.d.ts.map +1 -0
- package/dist/render/react/content.js +39 -0
- package/dist/render/react/content.js.map +1 -0
- package/dist/render/react/enhancements.d.ts +15 -0
- package/dist/render/react/enhancements.d.ts.map +1 -0
- package/dist/render/react/enhancements.js +28 -0
- package/dist/render/react/enhancements.js.map +1 -0
- package/dist/render/react/index.d.ts +3 -0
- package/dist/render/react/index.d.ts.map +1 -0
- package/dist/render/react/index.js +9 -0
- package/dist/render/react/index.js.map +1 -0
- package/dist/render/slack/assets.d.ts +16 -0
- package/dist/render/slack/assets.d.ts.map +1 -0
- package/dist/render/slack/assets.js +40 -0
- package/dist/render/slack/assets.js.map +1 -0
- package/dist/render/slack/blocks.d.ts +72 -0
- package/dist/render/slack/blocks.d.ts.map +1 -0
- package/dist/render/slack/blocks.js +77 -0
- package/dist/render/slack/blocks.js.map +1 -0
- package/dist/render/slack/envelope.d.ts +52 -0
- package/dist/render/slack/envelope.d.ts.map +1 -0
- package/dist/render/slack/envelope.js +547 -0
- package/dist/render/slack/envelope.js.map +1 -0
- package/dist/render/slack/format.d.ts +70 -0
- package/dist/render/slack/format.d.ts.map +1 -0
- package/dist/render/slack/format.js +209 -0
- package/dist/render/slack/format.js.map +1 -0
- package/dist/render/slack/index.d.ts +6 -0
- package/dist/render/slack/index.d.ts.map +1 -0
- package/dist/render/slack/index.js +12 -0
- package/dist/render/slack/index.js.map +1 -0
- package/dist/render/slack/markdown_content.d.ts +17 -0
- package/dist/render/slack/markdown_content.d.ts.map +1 -0
- package/dist/render/slack/markdown_content.js +404 -0
- package/dist/render/slack/markdown_content.js.map +1 -0
- package/dist/render/text/envelope.d.ts +15 -0
- package/dist/render/text/envelope.d.ts.map +1 -0
- package/dist/render/text/envelope.js +17 -0
- package/dist/render/text/envelope.js.map +1 -0
- package/dist/render/text/index.d.ts +2 -0
- package/dist/render/text/index.d.ts.map +1 -0
- package/dist/render/text/index.js +8 -0
- package/dist/render/text/index.js.map +1 -0
- package/dist/testing/conformance.d.ts +145 -0
- package/dist/testing/conformance.d.ts.map +1 -0
- package/dist/testing/conformance.js +303 -0
- package/dist/testing/conformance.js.map +1 -0
- package/dist/testing/icon.d.ts +11 -0
- package/dist/testing/icon.d.ts.map +1 -0
- package/dist/testing/icon.js +244 -0
- package/dist/testing/icon.js.map +1 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +10 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/registration.d.ts +32 -0
- package/dist/testing/registration.d.ts.map +1 -0
- package/dist/testing/registration.js +105 -0
- package/dist/testing/registration.js.map +1 -0
- package/dist/validate/authoring_schema.d.ts +33 -0
- package/dist/validate/authoring_schema.d.ts.map +1 -0
- package/dist/validate/authoring_schema.js +306 -0
- package/dist/validate/authoring_schema.js.map +1 -0
- package/dist/validate/composition_schema.d.ts +80 -0
- package/dist/validate/composition_schema.d.ts.map +1 -0
- package/dist/validate/composition_schema.js +127 -0
- package/dist/validate/composition_schema.js.map +1 -0
- package/dist/validate/index.d.ts +9 -0
- package/dist/validate/index.d.ts.map +1 -0
- package/dist/validate/index.js +15 -0
- package/dist/validate/index.js.map +1 -0
- package/dist/validate/input_budget.d.ts +35 -0
- package/dist/validate/input_budget.d.ts.map +1 -0
- package/dist/validate/input_budget.js +151 -0
- package/dist/validate/input_budget.js.map +1 -0
- package/dist/validate/json_schema.d.ts +32 -0
- package/dist/validate/json_schema.d.ts.map +1 -0
- package/dist/validate/json_schema.js +68 -0
- package/dist/validate/json_schema.js.map +1 -0
- package/dist/validate/node_issues.d.ts +12 -0
- package/dist/validate/node_issues.d.ts.map +1 -0
- package/dist/validate/node_issues.js +61 -0
- package/dist/validate/node_issues.js.map +1 -0
- package/dist/validate/url.d.ts +50 -0
- package/dist/validate/url.d.ts.map +1 -0
- package/dist/validate/url.js +107 -0
- package/dist/validate/url.js.map +1 -0
- package/dist/validate/validation.d.ts +95 -0
- package/dist/validate/validation.d.ts.map +1 -0
- package/dist/validate/validation.js +157 -0
- package/dist/validate/validation.js.map +1 -0
- package/dist/validate/value_schemas.d.ts +53 -0
- package/dist/validate/value_schemas.d.ts.map +1 -0
- package/dist/validate/value_schemas.js +50 -0
- package/dist/validate/value_schemas.js.map +1 -0
- package/package.json +119 -5
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ValidationError } from '../composition/validation_error.js';
|
|
2
|
+
/** Objects and arrays nested in one another, the input itself included. */
|
|
3
|
+
export declare const MAX_INPUT_DEPTH = 64;
|
|
4
|
+
/** Every object, array, and leaf counts once. */
|
|
5
|
+
export declare const MAX_INPUT_VALUES = 20000;
|
|
6
|
+
/** Every object key and string, and each other leaf as `String` prints it. */
|
|
7
|
+
export declare const MAX_INPUT_CHARACTERS = 1000000;
|
|
8
|
+
/** Overrides for the limits {@link checkInputBudget} enforces; an omitted one keeps its default. */
|
|
9
|
+
export interface InputBudget {
|
|
10
|
+
/** Defaults to {@link MAX_INPUT_DEPTH}. Zod parses what passes recursively, so a few hundred nested containers can exhaust the call stack. */
|
|
11
|
+
depth?: number;
|
|
12
|
+
/** Defaults to {@link MAX_INPUT_VALUES}. */
|
|
13
|
+
values?: number;
|
|
14
|
+
/** Defaults to {@link MAX_INPUT_CHARACTERS}. */
|
|
15
|
+
characters?: number;
|
|
16
|
+
}
|
|
17
|
+
/** Whether `error` is a refusal before parsing, which no validation mode collects. */
|
|
18
|
+
export declare const isInputRefusal: ({ code, }: Pick<ValidationError, "code">) => boolean;
|
|
19
|
+
/** A plain copy of the input to parse in its place, or why there is none. */
|
|
20
|
+
export type InputBudgetCheck = {
|
|
21
|
+
valid: true;
|
|
22
|
+
value: unknown;
|
|
23
|
+
} | {
|
|
24
|
+
valid: false;
|
|
25
|
+
error: ValidationError;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* A plain copy of `value` within `budget`, or why there is none: it is over `budget` or is not plain data.
|
|
29
|
+
*
|
|
30
|
+
* Plain data is arrays without holes, objects whose prototype is `Object.prototype` or `null`, enumerable own data properties with string keys, and primitives other than functions.
|
|
31
|
+
* Each property is read once, so a caller that parses the copy parses exactly what was checked; an array's other own properties are left out.
|
|
32
|
+
* Iterative and cycle-safe. Its cost is linear in the input's size: it lists a container's own keys, then refuses past the value limit before reading any of them.
|
|
33
|
+
*/
|
|
34
|
+
export declare const checkInputBudget: (value: unknown, budget?: InputBudget) => InputBudgetCheck;
|
|
35
|
+
//# sourceMappingURL=input_budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input_budget.d.ts","sourceRoot":"","sources":["../../src/validate/input_budget.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,2EAA2E;AAC3E,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,iDAAiD;AACjD,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAEvC,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,UAAY,CAAC;AAE9C,oGAAoG;AACpG,MAAM,WAAW,WAAW;IAC1B,8IAA8I;IAC9I,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAQD,sFAAsF;AACtF,eAAO,MAAM,cAAc,GAAI,WAE5B,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,KAAG,OAAwC,CAAC;AAE5E,6EAA6E;AAC7E,MAAM,MAAM,gBAAgB,GAC1B;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,CAAC;AAiD7E;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAC3B,OAAO,OAAO,EACd,SAAQ,WAAgB,KACvB,gBA6FF,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
3
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
4
|
+
* 2.0; you may not use this file except in compliance with the Elastic License
|
|
5
|
+
* 2.0.
|
|
6
|
+
*/
|
|
7
|
+
import { ISOMER_ERROR_CODES } from '../composition/error.js';
|
|
8
|
+
/** Objects and arrays nested in one another, the input itself included. */
|
|
9
|
+
export const MAX_INPUT_DEPTH = 64;
|
|
10
|
+
/** Every object, array, and leaf counts once. */
|
|
11
|
+
export const MAX_INPUT_VALUES = 20_000;
|
|
12
|
+
/** Every object key and string, and each other leaf as `String` prints it. */
|
|
13
|
+
export const MAX_INPUT_CHARACTERS = 1_000_000;
|
|
14
|
+
/** The codes {@link checkInputBudget} refuses with. */
|
|
15
|
+
const INPUT_REFUSAL_CODES = new Set([
|
|
16
|
+
ISOMER_ERROR_CODES.INPUT_NOT_PLAIN_DATA,
|
|
17
|
+
ISOMER_ERROR_CODES.INPUT_OVER_BUDGET,
|
|
18
|
+
]);
|
|
19
|
+
/** Whether `error` is a refusal before parsing, which no validation mode collects. */
|
|
20
|
+
export const isInputRefusal = ({ code, }) => INPUT_REFUSAL_CODES.has(code);
|
|
21
|
+
class Refusal extends Error {
|
|
22
|
+
error;
|
|
23
|
+
constructor(error) {
|
|
24
|
+
super(error.message);
|
|
25
|
+
this.error = error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const overBudget = (message) => new Refusal({
|
|
29
|
+
path: '',
|
|
30
|
+
message,
|
|
31
|
+
code: ISOMER_ERROR_CODES.INPUT_OVER_BUDGET,
|
|
32
|
+
});
|
|
33
|
+
const notPlainData = (what) => new Refusal({
|
|
34
|
+
path: '',
|
|
35
|
+
message: `input holds ${what}, which is not plain data`,
|
|
36
|
+
code: ISOMER_ERROR_CODES.INPUT_NOT_PLAIN_DATA,
|
|
37
|
+
});
|
|
38
|
+
const leafLength = (value) => typeof value === 'string' ? value.length : String(value).length;
|
|
39
|
+
/** Reads `key` once, through its descriptor. */
|
|
40
|
+
const plainProperty = (source, key) => {
|
|
41
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(source, key);
|
|
42
|
+
if (descriptor === undefined) {
|
|
43
|
+
throw notPlainData('an array hole');
|
|
44
|
+
}
|
|
45
|
+
if (!('value' in descriptor)) {
|
|
46
|
+
throw notPlainData('an accessor property');
|
|
47
|
+
}
|
|
48
|
+
if (!descriptor.enumerable) {
|
|
49
|
+
throw notPlainData('a non-enumerable property');
|
|
50
|
+
}
|
|
51
|
+
return descriptor.value;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* A plain copy of `value` within `budget`, or why there is none: it is over `budget` or is not plain data.
|
|
55
|
+
*
|
|
56
|
+
* Plain data is arrays without holes, objects whose prototype is `Object.prototype` or `null`, enumerable own data properties with string keys, and primitives other than functions.
|
|
57
|
+
* Each property is read once, so a caller that parses the copy parses exactly what was checked; an array's other own properties are left out.
|
|
58
|
+
* Iterative and cycle-safe. Its cost is linear in the input's size: it lists a container's own keys, then refuses past the value limit before reading any of them.
|
|
59
|
+
*/
|
|
60
|
+
export const checkInputBudget = (value, budget = {}) => {
|
|
61
|
+
const { depth: maxDepth = MAX_INPUT_DEPTH, values: maxValues = MAX_INPUT_VALUES, characters: maxCharacters = MAX_INPUT_CHARACTERS, } = budget;
|
|
62
|
+
const tooManyValues = `input holds more than ${maxValues} values`;
|
|
63
|
+
const ancestors = new Set();
|
|
64
|
+
const stack = [];
|
|
65
|
+
let values = 0;
|
|
66
|
+
let characters = 0;
|
|
67
|
+
const countCharacters = (count) => {
|
|
68
|
+
characters += count;
|
|
69
|
+
if (characters > maxCharacters) {
|
|
70
|
+
throw overBudget(`input holds more than ${maxCharacters} characters`);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const enqueue = (child, depth, keyLength) => {
|
|
74
|
+
values += 1;
|
|
75
|
+
if (values > maxValues) {
|
|
76
|
+
throw overBudget(tooManyValues);
|
|
77
|
+
}
|
|
78
|
+
if (typeof child === 'function') {
|
|
79
|
+
throw notPlainData('a function');
|
|
80
|
+
}
|
|
81
|
+
if (typeof child !== 'object' || child === null) {
|
|
82
|
+
countCharacters(keyLength + leafLength(child));
|
|
83
|
+
return child;
|
|
84
|
+
}
|
|
85
|
+
let copy = [];
|
|
86
|
+
if (!Array.isArray(child)) {
|
|
87
|
+
const prototype = Reflect.getPrototypeOf(child);
|
|
88
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
89
|
+
throw notPlainData('an object that is not a plain object or array');
|
|
90
|
+
}
|
|
91
|
+
copy = Object.create(prototype);
|
|
92
|
+
}
|
|
93
|
+
countCharacters(keyLength);
|
|
94
|
+
stack.push({ source: child, copy, depth });
|
|
95
|
+
return copy;
|
|
96
|
+
};
|
|
97
|
+
const copyChildren = ({ source, copy, depth }) => {
|
|
98
|
+
const keys = Array.isArray(copy) ? undefined : Reflect.ownKeys(source);
|
|
99
|
+
const count = keys?.length ?? source.length;
|
|
100
|
+
if (values + count > maxValues) {
|
|
101
|
+
throw overBudget(tooManyValues);
|
|
102
|
+
}
|
|
103
|
+
for (let index = 0; index < count; index += 1) {
|
|
104
|
+
const key = keys === undefined ? index : keys[index];
|
|
105
|
+
if (typeof key === 'symbol') {
|
|
106
|
+
throw notPlainData('a symbol key');
|
|
107
|
+
}
|
|
108
|
+
const child = plainProperty(source, key);
|
|
109
|
+
if (Array.isArray(copy)) {
|
|
110
|
+
copy.push(enqueue(child, depth, 0));
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
Object.defineProperty(copy, key, {
|
|
114
|
+
value: enqueue(child, depth, String(key).length),
|
|
115
|
+
writable: true,
|
|
116
|
+
enumerable: true,
|
|
117
|
+
configurable: true,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
try {
|
|
123
|
+
const root = enqueue(value, 1, 0);
|
|
124
|
+
while (stack.length > 0) {
|
|
125
|
+
const entry = stack.pop();
|
|
126
|
+
const { source, depth, leave } = entry;
|
|
127
|
+
if (leave) {
|
|
128
|
+
ancestors.delete(source);
|
|
129
|
+
}
|
|
130
|
+
else if (ancestors.has(source)) {
|
|
131
|
+
throw overBudget('input contains itself');
|
|
132
|
+
}
|
|
133
|
+
else if (depth > maxDepth) {
|
|
134
|
+
throw overBudget(`input nests deeper than ${maxDepth} levels`);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
ancestors.add(source);
|
|
138
|
+
stack.push({ ...entry, leave: true });
|
|
139
|
+
copyChildren({ ...entry, depth: depth + 1 });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return { valid: true, value: root };
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
if (error instanceof Refusal) {
|
|
146
|
+
return { valid: false, error: error.error };
|
|
147
|
+
}
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=input_budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input_budget.js","sourceRoot":"","sources":["../../src/validate/input_budget.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,2EAA2E;AAC3E,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC,iDAAiD;AACjD,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEvC,8EAA8E;AAC9E,MAAM,CAAC,MAAM,oBAAoB,GAAG,SAAS,CAAC;AAY9C,uDAAuD;AACvD,MAAM,mBAAmB,GAAoC,IAAI,GAAG,CAAC;IACnE,kBAAkB,CAAC,oBAAoB;IACvC,kBAAkB,CAAC,iBAAiB;CACrC,CAAC,CAAC;AAEH,sFAAsF;AACtF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAC7B,IAAI,GAC0B,EAAW,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAe5E,MAAM,OAAQ,SAAQ,KAAK;IACJ;IAArB,YAAqB,KAAsB;QACzC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QADF,UAAK,GAAL,KAAK,CAAiB;IAE3C,CAAC;CACF;AAED,MAAM,UAAU,GAAG,CAAC,OAAe,EAAW,EAAE,CAC9C,IAAI,OAAO,CAAC;IACV,IAAI,EAAE,EAAE;IACR,OAAO;IACP,IAAI,EAAE,kBAAkB,CAAC,iBAAiB;CAC3C,CAAC,CAAC;AAEL,MAAM,YAAY,GAAG,CAAC,IAAY,EAAW,EAAE,CAC7C,IAAI,OAAO,CAAC;IACV,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,eAAe,IAAI,2BAA2B;IACvD,IAAI,EAAE,kBAAkB,CAAC,oBAAoB;CAC9C,CAAC,CAAC;AAEL,MAAM,UAAU,GAAG,CAAC,KAAc,EAAU,EAAE,CAC5C,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;AAElE,gDAAgD;AAChD,MAAM,aAAa,GAAG,CAAC,MAAc,EAAE,GAAoB,EAAW,EAAE;IACtE,MAAM,UAAU,GAAG,OAAO,CAAC,wBAAwB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjE,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,YAAY,CAAC,eAAe,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC,EAAE,CAAC;QAC7B,MAAM,YAAY,CAAC,sBAAsB,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;QAC3B,MAAM,YAAY,CAAC,2BAA2B,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,UAAU,CAAC,KAAK,CAAC;AAC1B,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAAc,EACd,SAAsB,EAAE,EACN,EAAE;IACpB,MAAM,EACJ,KAAK,EAAE,QAAQ,GAAG,eAAe,EACjC,MAAM,EAAE,SAAS,GAAG,gBAAgB,EACpC,UAAU,EAAE,aAAa,GAAG,oBAAoB,GACjD,GAAG,MAAM,CAAC;IACX,MAAM,aAAa,GAAG,yBAAyB,SAAS,SAAS,CAAC;IAClE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,KAAK,GAAY,EAAE,CAAC;IAC1B,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,eAAe,GAAG,CAAC,KAAa,EAAQ,EAAE;QAC9C,UAAU,IAAI,KAAK,CAAC;QACpB,IAAI,UAAU,GAAG,aAAa,EAAE,CAAC;YAC/B,MAAM,UAAU,CAAC,yBAAyB,aAAa,aAAa,CAAC,CAAC;QACxE,CAAC;IACH,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,CACd,KAAc,EACd,KAAa,EACb,SAAiB,EACR,EAAE;QACX,MAAM,IAAI,CAAC,CAAC;QACZ,IAAI,MAAM,GAAG,SAAS,EAAE,CAAC;YACvB,MAAM,UAAU,CAAC,aAAa,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;YAChC,MAAM,YAAY,CAAC,YAAY,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAChD,eAAe,CAAC,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;YAC/C,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,IAAI,GAAmB,EAAE,CAAC;QAC9B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,SAAS,GAAG,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAChD,IAAI,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;gBACzD,MAAM,YAAY,CAAC,+CAA+C,CAAC,CAAC;YACtE,CAAC;YACD,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAA4B,CAAC;QAC7D,CAAC;QACD,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAS,EAAQ,EAAE;QAC5D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACvE,MAAM,KAAK,GAAG,IAAI,EAAE,MAAM,IAAK,MAAoB,CAAC,MAAM,CAAC;QAC3D,IAAI,MAAM,GAAG,KAAK,GAAG,SAAS,EAAE,CAAC;YAC/B,MAAM,UAAU,CAAC,aAAa,CAAC,CAAC;QAClC,CAAC;QACD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC9C,MAAM,GAAG,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAE,CAAC;YACtD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC5B,MAAM,YAAY,CAAC,cAAc,CAAC,CAAC;YACrC,CAAC;YACD,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACzC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE;oBAC/B,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;oBAChD,QAAQ,EAAE,IAAI;oBACd,UAAU,EAAE,IAAI;oBAChB,YAAY,EAAE,IAAI;iBACnB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAClC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;YAC3B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;YACvC,IAAI,KAAK,EAAE,CAAC;gBACV,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC3B,CAAC;iBAAM,IAAI,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjC,MAAM,UAAU,CAAC,uBAAuB,CAAC,CAAC;YAC5C,CAAC;iBAAM,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;gBAC5B,MAAM,UAAU,CAAC,2BAA2B,QAAQ,SAAS,CAAC,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtC,YAAY,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,OAAO,EAAE,CAAC;YAC7B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;QAC9C,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CAAC","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport { ISOMER_ERROR_CODES } from '../composition/error';\nimport type { ValidationError } from '../composition/validation_error';\n\n/** Objects and arrays nested in one another, the input itself included. */\nexport const MAX_INPUT_DEPTH = 64;\n\n/** Every object, array, and leaf counts once. */\nexport const MAX_INPUT_VALUES = 20_000;\n\n/** Every object key and string, and each other leaf as `String` prints it. */\nexport const MAX_INPUT_CHARACTERS = 1_000_000;\n\n/** Overrides for the limits {@link checkInputBudget} enforces; an omitted one keeps its default. */\nexport interface InputBudget {\n /** Defaults to {@link MAX_INPUT_DEPTH}. Zod parses what passes recursively, so a few hundred nested containers can exhaust the call stack. */\n depth?: number;\n /** Defaults to {@link MAX_INPUT_VALUES}. */\n values?: number;\n /** Defaults to {@link MAX_INPUT_CHARACTERS}. */\n characters?: number;\n}\n\n/** The codes {@link checkInputBudget} refuses with. */\nconst INPUT_REFUSAL_CODES: ReadonlySet<string | undefined> = new Set([\n ISOMER_ERROR_CODES.INPUT_NOT_PLAIN_DATA,\n ISOMER_ERROR_CODES.INPUT_OVER_BUDGET,\n]);\n\n/** Whether `error` is a refusal before parsing, which no validation mode collects. */\nexport const isInputRefusal = ({\n code,\n}: Pick<ValidationError, 'code'>): boolean => INPUT_REFUSAL_CODES.has(code);\n\n/** A plain copy of the input to parse in its place, or why there is none. */\nexport type InputBudgetCheck =\n { valid: true; value: unknown } | { valid: false; error: ValidationError };\n\ntype PlainContainer = unknown[] | Record<string, unknown>;\n\ninterface Entry {\n source: object;\n copy: PlainContainer;\n depth: number;\n leave?: true;\n}\n\nclass Refusal extends Error {\n constructor(readonly error: ValidationError) {\n super(error.message);\n }\n}\n\nconst overBudget = (message: string): Refusal =>\n new Refusal({\n path: '',\n message,\n code: ISOMER_ERROR_CODES.INPUT_OVER_BUDGET,\n });\n\nconst notPlainData = (what: string): Refusal =>\n new Refusal({\n path: '',\n message: `input holds ${what}, which is not plain data`,\n code: ISOMER_ERROR_CODES.INPUT_NOT_PLAIN_DATA,\n });\n\nconst leafLength = (value: unknown): number =>\n typeof value === 'string' ? value.length : String(value).length;\n\n/** Reads `key` once, through its descriptor. */\nconst plainProperty = (source: object, key: string | number): unknown => {\n const descriptor = Reflect.getOwnPropertyDescriptor(source, key);\n if (descriptor === undefined) {\n throw notPlainData('an array hole');\n }\n if (!('value' in descriptor)) {\n throw notPlainData('an accessor property');\n }\n if (!descriptor.enumerable) {\n throw notPlainData('a non-enumerable property');\n }\n return descriptor.value;\n};\n\n/**\n * A plain copy of `value` within `budget`, or why there is none: it is over `budget` or is not plain data.\n *\n * Plain data is arrays without holes, objects whose prototype is `Object.prototype` or `null`, enumerable own data properties with string keys, and primitives other than functions.\n * Each property is read once, so a caller that parses the copy parses exactly what was checked; an array's other own properties are left out.\n * Iterative and cycle-safe. Its cost is linear in the input's size: it lists a container's own keys, then refuses past the value limit before reading any of them.\n */\nexport const checkInputBudget = (\n value: unknown,\n budget: InputBudget = {}\n): InputBudgetCheck => {\n const {\n depth: maxDepth = MAX_INPUT_DEPTH,\n values: maxValues = MAX_INPUT_VALUES,\n characters: maxCharacters = MAX_INPUT_CHARACTERS,\n } = budget;\n const tooManyValues = `input holds more than ${maxValues} values`;\n const ancestors = new Set<object>();\n const stack: Entry[] = [];\n let values = 0;\n let characters = 0;\n const countCharacters = (count: number): void => {\n characters += count;\n if (characters > maxCharacters) {\n throw overBudget(`input holds more than ${maxCharacters} characters`);\n }\n };\n const enqueue = (\n child: unknown,\n depth: number,\n keyLength: number\n ): unknown => {\n values += 1;\n if (values > maxValues) {\n throw overBudget(tooManyValues);\n }\n if (typeof child === 'function') {\n throw notPlainData('a function');\n }\n if (typeof child !== 'object' || child === null) {\n countCharacters(keyLength + leafLength(child));\n return child;\n }\n let copy: PlainContainer = [];\n if (!Array.isArray(child)) {\n const prototype = Reflect.getPrototypeOf(child);\n if (prototype !== Object.prototype && prototype !== null) {\n throw notPlainData('an object that is not a plain object or array');\n }\n copy = Object.create(prototype) as Record<string, unknown>;\n }\n countCharacters(keyLength);\n stack.push({ source: child, copy, depth });\n return copy;\n };\n const copyChildren = ({ source, copy, depth }: Entry): void => {\n const keys = Array.isArray(copy) ? undefined : Reflect.ownKeys(source);\n const count = keys?.length ?? (source as unknown[]).length;\n if (values + count > maxValues) {\n throw overBudget(tooManyValues);\n }\n for (let index = 0; index < count; index += 1) {\n const key = keys === undefined ? index : keys[index]!;\n if (typeof key === 'symbol') {\n throw notPlainData('a symbol key');\n }\n const child = plainProperty(source, key);\n if (Array.isArray(copy)) {\n copy.push(enqueue(child, depth, 0));\n } else {\n Object.defineProperty(copy, key, {\n value: enqueue(child, depth, String(key).length),\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n }\n };\n try {\n const root = enqueue(value, 1, 0);\n while (stack.length > 0) {\n const entry = stack.pop()!;\n const { source, depth, leave } = entry;\n if (leave) {\n ancestors.delete(source);\n } else if (ancestors.has(source)) {\n throw overBudget('input contains itself');\n } else if (depth > maxDepth) {\n throw overBudget(`input nests deeper than ${maxDepth} levels`);\n } else {\n ancestors.add(source);\n stack.push({ ...entry, leave: true });\n copyChildren({ ...entry, depth: depth + 1 });\n }\n }\n return { valid: true, value: root };\n } catch (error) {\n if (error instanceof Refusal) {\n return { valid: false, error: error.error };\n }\n throw error;\n }\n};\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ZodType } from 'zod';
|
|
2
|
+
import type { AnyPrimitiveDefinition } from '../define/primitive_module.js';
|
|
3
|
+
type JsonSchema = Record<string, unknown>;
|
|
4
|
+
/** Options for {@link buildCompositionJsonSchema}. */
|
|
5
|
+
export interface CompositionJsonSchemaOptions {
|
|
6
|
+
/** Base URI for the emitted schema, which `$ref`s resolve against. */
|
|
7
|
+
$id?: string;
|
|
8
|
+
/** Reaches the model, so it keeps the word "view". Defaults to `'View'`. */
|
|
9
|
+
title?: string;
|
|
10
|
+
/** Reaches the model too, so write it as guidance rather than as a type note. */
|
|
11
|
+
description?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Extra schemas to name in `$defs`, for types a pack references by `$ref`.
|
|
14
|
+
* Each `id` becomes the `$defs` key, so it must be unique.
|
|
15
|
+
*/
|
|
16
|
+
extraDefs?: readonly {
|
|
17
|
+
schema: ZodType;
|
|
18
|
+
id: string;
|
|
19
|
+
}[];
|
|
20
|
+
/** `ref` gives a repeated schema its own `$def`; `inline` repeats it. Defaults to `ref`. */
|
|
21
|
+
reused?: 'ref' | 'inline';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Projects the composition schema to JSON Schema draft 2020-12, for hosts
|
|
25
|
+
* that validate outside TypeScript.
|
|
26
|
+
*
|
|
27
|
+
* `$defs` are named per primitive type, plus `bodyNode` for the union.
|
|
28
|
+
* Agent-facing prompt text uses `buildAuthoringJsonSchema` instead.
|
|
29
|
+
*/
|
|
30
|
+
export declare const buildCompositionJsonSchema: (definitions: readonly AnyPrimitiveDefinition[], options?: CompositionJsonSchemaOptions) => JsonSchema;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=json_schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json_schema.d.ts","sourceRoot":"","sources":["../../src/validate/json_schema.ts"],"names":[],"mappings":"AAOA,OAAO,EAAK,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAEtC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAOzE,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1C,sDAAsD;AACtD,MAAM,WAAW,4BAA4B;IAC3C,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvD,4FAA4F;IAC5F,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GACrC,aAAa,SAAS,sBAAsB,EAAE,EAC9C,UAAS,4BAAiC,KACzC,UAmDF,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
3
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
4
|
+
* 2.0; you may not use this file except in compliance with the Elastic License
|
|
5
|
+
* 2.0.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { buildCompositionSchema, resolveVocabulary, } from './composition_schema.js';
|
|
9
|
+
/**
|
|
10
|
+
* Projects the composition schema to JSON Schema draft 2020-12, for hosts
|
|
11
|
+
* that validate outside TypeScript.
|
|
12
|
+
*
|
|
13
|
+
* `$defs` are named per primitive type, plus `bodyNode` for the union.
|
|
14
|
+
* Agent-facing prompt text uses `buildAuthoringJsonSchema` instead.
|
|
15
|
+
*/
|
|
16
|
+
export const buildCompositionJsonSchema = (definitions, options = {}) => {
|
|
17
|
+
// Members, not `definition.schema`: a container's member is built by
|
|
18
|
+
// `schemaFor`, and the registry is keyed on identity.
|
|
19
|
+
const composed = resolveVocabulary(definitions);
|
|
20
|
+
const { bodyNodeSchema, members } = composed;
|
|
21
|
+
const compositionSchema = buildCompositionSchema({ bodyNodeSchema });
|
|
22
|
+
// `metadata` replaces `z.toJSONSchema`'s default registry rather than
|
|
23
|
+
// extending it, and `z.globalRegistry` is where every `.describe()` lives,
|
|
24
|
+
// so ids are added to the global registry for the duration of this call
|
|
25
|
+
// and the prior entries restored in `finally`. Only a schema's first
|
|
26
|
+
// registration is recorded: a schema named twice (an `extraDefs` entry that
|
|
27
|
+
// is also a member) must restore its original entry, not the first id.
|
|
28
|
+
const previous = new Map();
|
|
29
|
+
const registerId = (schema, id) => {
|
|
30
|
+
if (!previous.has(schema)) {
|
|
31
|
+
previous.set(schema, z.globalRegistry.get(schema));
|
|
32
|
+
}
|
|
33
|
+
z.globalRegistry.add(schema, { ...z.globalRegistry.get(schema), id });
|
|
34
|
+
};
|
|
35
|
+
registerId(bodyNodeSchema, 'bodyNode');
|
|
36
|
+
for (const extra of options.extraDefs ?? []) {
|
|
37
|
+
registerId(extra.schema, extra.id);
|
|
38
|
+
}
|
|
39
|
+
for (const [type, schema] of members) {
|
|
40
|
+
registerId(schema, type);
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
return {
|
|
44
|
+
...z.toJSONSchema(compositionSchema, {
|
|
45
|
+
target: 'draft-2020-12',
|
|
46
|
+
metadata: z.globalRegistry,
|
|
47
|
+
reused: options.reused ?? 'ref',
|
|
48
|
+
cycles: 'ref',
|
|
49
|
+
unrepresentable: 'any',
|
|
50
|
+
}),
|
|
51
|
+
...(options.$id ? { $id: options.$id } : {}),
|
|
52
|
+
title: options.title ?? 'View',
|
|
53
|
+
description: options.description ??
|
|
54
|
+
'A compact view that may include registered primitives.',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
for (const [schema, entry] of previous) {
|
|
59
|
+
if (entry === undefined) {
|
|
60
|
+
z.globalRegistry.remove(schema);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
z.globalRegistry.add(schema, entry);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=json_schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json_schema.js","sourceRoot":"","sources":["../../src/validate/json_schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAgB,MAAM,KAAK,CAAC;AAItC,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAqB9B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CACxC,WAA8C,EAC9C,UAAwC,EAAE,EAC9B,EAAE;IACd,qEAAqE;IACrE,sDAAsD;IACtD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;IAC7C,MAAM,iBAAiB,GAAG,sBAAsB,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC;IAErE,sEAAsE;IACtE,2EAA2E;IAC3E,wEAAwE;IACxE,qEAAqE;IACrE,4EAA4E;IAC5E,uEAAuE;IACvE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC7C,MAAM,UAAU,GAAG,CAAC,MAAe,EAAE,EAAU,EAAQ,EAAE;QACvD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QACrD,CAAC;QACD,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACxE,CAAC,CAAC;IACF,UAAU,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;QAC5C,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACrC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC;IACD,IAAI,CAAC;QACH,OAAO;YACL,GAAG,CAAC,CAAC,YAAY,CAAC,iBAAiB,EAAE;gBACnC,MAAM,EAAE,eAAe;gBACvB,QAAQ,EAAE,CAAC,CAAC,cAAc;gBAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;gBAC/B,MAAM,EAAE,KAAK;gBACb,eAAe,EAAE,KAAK;aACvB,CAAC;YACF,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,MAAM;YAC9B,WAAW,EACT,OAAO,CAAC,WAAW;gBACnB,wDAAwD;SAC3D,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,QAAQ,EAAE,CAAC;YACvC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACN,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,KAAc,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC,CAAC","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport { z, type ZodType } from 'zod';\n\nimport type { AnyPrimitiveDefinition } from '../define/primitive_module';\n\nimport {\n buildCompositionSchema,\n resolveVocabulary,\n} from './composition_schema';\n\ntype JsonSchema = Record<string, unknown>;\n\n/** Options for {@link buildCompositionJsonSchema}. */\nexport interface CompositionJsonSchemaOptions {\n /** Base URI for the emitted schema, which `$ref`s resolve against. */\n $id?: string;\n /** Reaches the model, so it keeps the word \"view\". Defaults to `'View'`. */\n title?: string;\n /** Reaches the model too, so write it as guidance rather than as a type note. */\n description?: string;\n /**\n * Extra schemas to name in `$defs`, for types a pack references by `$ref`.\n * Each `id` becomes the `$defs` key, so it must be unique.\n */\n extraDefs?: readonly { schema: ZodType; id: string }[];\n /** `ref` gives a repeated schema its own `$def`; `inline` repeats it. Defaults to `ref`. */\n reused?: 'ref' | 'inline';\n}\n\n/**\n * Projects the composition schema to JSON Schema draft 2020-12, for hosts\n * that validate outside TypeScript.\n *\n * `$defs` are named per primitive type, plus `bodyNode` for the union.\n * Agent-facing prompt text uses `buildAuthoringJsonSchema` instead.\n */\nexport const buildCompositionJsonSchema = (\n definitions: readonly AnyPrimitiveDefinition[],\n options: CompositionJsonSchemaOptions = {}\n): JsonSchema => {\n // Members, not `definition.schema`: a container's member is built by\n // `schemaFor`, and the registry is keyed on identity.\n const composed = resolveVocabulary(definitions);\n const { bodyNodeSchema, members } = composed;\n const compositionSchema = buildCompositionSchema({ bodyNodeSchema });\n\n // `metadata` replaces `z.toJSONSchema`'s default registry rather than\n // extending it, and `z.globalRegistry` is where every `.describe()` lives,\n // so ids are added to the global registry for the duration of this call\n // and the prior entries restored in `finally`. Only a schema's first\n // registration is recorded: a schema named twice (an `extraDefs` entry that\n // is also a member) must restore its original entry, not the first id.\n const previous = new Map<ZodType, unknown>();\n const registerId = (schema: ZodType, id: string): void => {\n if (!previous.has(schema)) {\n previous.set(schema, z.globalRegistry.get(schema));\n }\n z.globalRegistry.add(schema, { ...z.globalRegistry.get(schema), id });\n };\n registerId(bodyNodeSchema, 'bodyNode');\n for (const extra of options.extraDefs ?? []) {\n registerId(extra.schema, extra.id);\n }\n for (const [type, schema] of members) {\n registerId(schema, type);\n }\n try {\n return {\n ...z.toJSONSchema(compositionSchema, {\n target: 'draft-2020-12',\n metadata: z.globalRegistry,\n reused: options.reused ?? 'ref',\n cycles: 'ref',\n unrepresentable: 'any',\n }),\n ...(options.$id ? { $id: options.$id } : {}),\n title: options.title ?? 'View',\n description:\n options.description ??\n 'A compact view that may include registered primitives.',\n };\n } finally {\n for (const [schema, entry] of previous) {\n if (entry === undefined) {\n z.globalRegistry.remove(schema);\n } else {\n z.globalRegistry.add(schema, entry as never);\n }\n }\n }\n};\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { core } from 'zod';
|
|
2
|
+
import type { ValidationError } from '../composition/validation_error.js';
|
|
3
|
+
import type { AnyPrimitiveDefinition } from '../define/primitive_module.js';
|
|
4
|
+
/** A node an issue path can start from, and its path. */
|
|
5
|
+
export type IssueRoot = readonly [node: unknown, path: string];
|
|
6
|
+
/**
|
|
7
|
+
* Builds the formatter that converts Zod issues with {@link formatZodIssue},
|
|
8
|
+
* each error naming the innermost node its path lands in when that node's type
|
|
9
|
+
* is known, and an unknown key on a node appending {@link declaredFieldsNote}.
|
|
10
|
+
*/
|
|
11
|
+
export declare const createNodeIssueFormatter: (definitions: readonly AnyPrimitiveDefinition[]) => ((roots: readonly IssueRoot[], issues: ReadonlyArray<core.$ZodIssue>, basePath?: string) => ValidationError[]);
|
|
12
|
+
//# sourceMappingURL=node_issues.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node_issues.d.ts","sourceRoot":"","sources":["../../src/validate/node_issues.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAOhC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAOzE,yDAAyD;AACzD,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AA8B/D;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GACnC,aAAa,SAAS,sBAAsB,EAAE,KAC7C,CAAC,CACF,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,KACd,eAAe,EAAE,CAiCrB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
3
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
4
|
+
* 2.0; you may not use this file except in compliance with the Elastic License
|
|
5
|
+
* 2.0.
|
|
6
|
+
*/
|
|
7
|
+
import { childNodePath, createChildNodeWalker, } from '../composition/body_node_base.js';
|
|
8
|
+
import { declaredFieldsNote, formatPath, formatZodIssue, } from '../define/zod_format.js';
|
|
9
|
+
/**
|
|
10
|
+
* The raw `type` of each node `walk` reaches from `roots`, keyed by its path.
|
|
11
|
+
* The input has failed a schema, so a node whose children cannot be walked adds none.
|
|
12
|
+
*/
|
|
13
|
+
const nodeTypesByPath = (roots, walk) => {
|
|
14
|
+
const types = new Map();
|
|
15
|
+
const visit = (node, path) => {
|
|
16
|
+
if (typeof node !== 'object' || node === null) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
types.set(path, node.type);
|
|
20
|
+
let children;
|
|
21
|
+
try {
|
|
22
|
+
children = walk(node);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
children.forEach(({ node: child, path: field }) => {
|
|
28
|
+
visit(child, childNodePath(path, field));
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
roots.forEach(([node, path]) => visit(node, path));
|
|
32
|
+
return types;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Builds the formatter that converts Zod issues with {@link formatZodIssue},
|
|
36
|
+
* each error naming the innermost node its path lands in when that node's type
|
|
37
|
+
* is known, and an unknown key on a node appending {@link declaredFieldsNote}.
|
|
38
|
+
*/
|
|
39
|
+
export const createNodeIssueFormatter = (definitions) => {
|
|
40
|
+
const walk = createChildNodeWalker(definitions);
|
|
41
|
+
const fieldNotes = new Map(definitions.map(({ type, schema }) => [type, declaredFieldsNote(schema)]));
|
|
42
|
+
const knownType = (type) => typeof type === 'string' && fieldNotes.has(type) ? type : undefined;
|
|
43
|
+
return (roots, issues, basePath = '') => {
|
|
44
|
+
const nodes = nodeTypesByPath(roots, walk);
|
|
45
|
+
const nodeTypeAt = (segments) => segments
|
|
46
|
+
.reduce((paths, segment) => [...paths, formatPath([segment], paths.at(-1))], [basePath])
|
|
47
|
+
.reduce((found, path) => nodes.has(path) ? knownType(nodes.get(path)) : found, undefined);
|
|
48
|
+
return issues.map((issue) => {
|
|
49
|
+
const error = formatZodIssue(issue, basePath);
|
|
50
|
+
const nodeType = nodeTypeAt(issue.path);
|
|
51
|
+
if (nodeType === undefined) {
|
|
52
|
+
return error;
|
|
53
|
+
}
|
|
54
|
+
const message = issue.code === 'unrecognized_keys' && nodes.get(error.path) === nodeType
|
|
55
|
+
? `${error.message}; ${fieldNotes.get(nodeType)}`
|
|
56
|
+
: error.message;
|
|
57
|
+
return { ...error, message, nodeType };
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=node_issues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node_issues.js","sourceRoot":"","sources":["../../src/validate/node_issues.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport type { core } from 'zod';\n\nimport {\n childNodePath,\n type ChildNodeWalker,\n createChildNodeWalker,\n} from '../composition/body_node_base';\nimport type { ValidationError } from '../composition/validation_error';\nimport type { AnyPrimitiveDefinition } from '../define/primitive_module';\nimport {\n declaredFieldsNote,\n formatPath,\n formatZodIssue,\n} from '../define/zod_format';\n\n/** A node an issue path can start from, and its path. */\nexport type IssueRoot = readonly [node: unknown, path: string];\n\n/**\n * The raw `type` of each node `walk` reaches from `roots`, keyed by its path.\n * The input has failed a schema, so a node whose children cannot be walked adds none.\n */\nconst nodeTypesByPath = (\n roots: readonly IssueRoot[],\n walk: ChildNodeWalker\n): Map<string, unknown> => {\n const types = new Map<string, unknown>();\n const visit = (node: unknown, path: string): void => {\n if (typeof node !== 'object' || node === null) {\n return;\n }\n types.set(path, (node as { type?: unknown }).type);\n let children: ReturnType<ChildNodeWalker>;\n try {\n children = walk(node);\n } catch {\n return;\n }\n children.forEach(({ node: child, path: field }) => {\n visit(child, childNodePath(path, field));\n });\n };\n roots.forEach(([node, path]) => visit(node, path));\n return types;\n};\n\n/**\n * Builds the formatter that converts Zod issues with {@link formatZodIssue},\n * each error naming the innermost node its path lands in when that node's type\n * is known, and an unknown key on a node appending {@link declaredFieldsNote}.\n */\nexport const createNodeIssueFormatter = (\n definitions: readonly AnyPrimitiveDefinition[]\n): ((\n roots: readonly IssueRoot[],\n issues: ReadonlyArray<core.$ZodIssue>,\n basePath?: string\n) => ValidationError[]) => {\n const walk = createChildNodeWalker(definitions);\n const fieldNotes = new Map(\n definitions.map(({ type, schema }) => [type, declaredFieldsNote(schema)])\n );\n const knownType = (type: unknown): string | undefined =>\n typeof type === 'string' && fieldNotes.has(type) ? type : undefined;\n return (roots, issues, basePath = '') => {\n const nodes = nodeTypesByPath(roots, walk);\n const nodeTypeAt = (segments: readonly PropertyKey[]) =>\n segments\n .reduce(\n (paths, segment) => [...paths, formatPath([segment], paths.at(-1))],\n [basePath]\n )\n .reduce<string | undefined>(\n (found, path) =>\n nodes.has(path) ? knownType(nodes.get(path)) : found,\n undefined\n );\n return issues.map((issue) => {\n const error = formatZodIssue(issue, basePath);\n const nodeType = nodeTypeAt(issue.path);\n if (nodeType === undefined) {\n return error;\n }\n const message =\n issue.code === 'unrecognized_keys' && nodes.get(error.path) === nodeType\n ? `${error.message}; ${fieldNotes.get(nodeType)}`\n : error.message;\n return { ...error, message, nodeType };\n });\n };\n};\n"]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the URL, trimmed and with control characters stripped, when it
|
|
3
|
+
* satisfies the navigation policy (`https:` / `http:` / `mailto:` / relative
|
|
4
|
+
* path), `null` otherwise.
|
|
5
|
+
*/
|
|
6
|
+
export declare const sanitizeNavigationHref: (href: string) => string | null;
|
|
7
|
+
/**
|
|
8
|
+
* Returns the URL, trimmed and with control characters stripped, when it
|
|
9
|
+
* satisfies the asset policy (`https:` / `http:` / relative path /
|
|
10
|
+
* `data:image/*`), `null` otherwise.
|
|
11
|
+
*/
|
|
12
|
+
export declare const sanitizeAssetUrl: (url: string) => string | null;
|
|
13
|
+
/** Checks a Markdown parser's decoded destination without decoding it again. */
|
|
14
|
+
export declare const sanitizeParsedNavigationHref: (href: string) => string | null;
|
|
15
|
+
/** Checks a Markdown parser's decoded image destination. */
|
|
16
|
+
export declare const sanitizeParsedAssetUrl: (url: string) => string | null;
|
|
17
|
+
/**
|
|
18
|
+
* Render-time replacement for a navigation href that failed the policy: an
|
|
19
|
+
* inert same-document link, so the label stays visible without a destination.
|
|
20
|
+
*/
|
|
21
|
+
export declare const BLOCKED_HREF = "#";
|
|
22
|
+
/** What {@link navigationHref} accepts, for a field description to state. */
|
|
23
|
+
export declare const NAVIGATION_HREF_RULE = "an https, http, or mailto URL, or a relative path";
|
|
24
|
+
/** What {@link assetUrl} accepts, for a field description to state. */
|
|
25
|
+
export declare const ASSET_URL_RULE = "an https, http, or data:image URL, or a relative path";
|
|
26
|
+
/** Validation message for {@link navigationHref}. */
|
|
27
|
+
export declare const NAVIGATION_HREF_MESSAGE = "must be an https, http, or mailto URL, or a relative path";
|
|
28
|
+
/** Validation message for {@link assetUrl}. */
|
|
29
|
+
export declare const ASSET_URL_MESSAGE = "must be an https, http, or data:image URL, or a relative path";
|
|
30
|
+
/** Options for {@link navigationHref} and {@link assetUrl}. */
|
|
31
|
+
export interface UrlSchemaOptions {
|
|
32
|
+
/** Longest accepted value, in characters. */
|
|
33
|
+
max?: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Zod schema for an `href`-like field: the validation layer of the two-layer
|
|
37
|
+
* policy, paired with {@link sanitizeNavigationHref} at render time.
|
|
38
|
+
*
|
|
39
|
+
* Its description states the rule, since a refinement's message does not
|
|
40
|
+
* reach the authoring JSON Schema. A field that describes itself should end
|
|
41
|
+
* with {@link NAVIGATION_HREF_RULE} so the model still reads it.
|
|
42
|
+
*/
|
|
43
|
+
export declare const navigationHref: (options?: UrlSchemaOptions) => import("zod").ZodString;
|
|
44
|
+
/**
|
|
45
|
+
* Zod schema for a `src`-like field, paired with {@link sanitizeAssetUrl} at
|
|
46
|
+
* render time. Describes itself as {@link navigationHref} does, with
|
|
47
|
+
* {@link ASSET_URL_RULE}.
|
|
48
|
+
*/
|
|
49
|
+
export declare const assetUrl: (options?: UrlSchemaOptions) => import("zod").ZodString;
|
|
50
|
+
//# sourceMappingURL=url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/validate/url.ts"],"names":[],"mappings":"AAsEA;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,MAAM,MAAM,KAAG,MAAM,GAAG,IACgB,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IACgB,CAAC;AAEzE,gFAAgF;AAChF,eAAO,MAAM,4BAA4B,GAAI,MAAM,MAAM,KAAG,MAAM,GAAG,IAGpE,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAG7D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,MAAM,CAAC;AAEhC,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,sDACoB,CAAC;AAEtD,uEAAuE;AACvE,eAAO,MAAM,cAAc,0DAC8B,CAAC;AAE1D,qDAAqD;AACrD,eAAO,MAAM,uBAAuB,8DAAoC,CAAC;AAEzE,+CAA+C;AAC/C,eAAO,MAAM,iBAAiB,kEAA8B,CAAC;AAE7D,+DAA+D;AAC/D,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAYD;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GAAI,UAAS,gBAAqB,4BAM1D,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAS,gBAAqB,4BAMpD,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
3
|
+
* or more contributor license agreements. Licensed under the Elastic License
|
|
4
|
+
* 2.0; you may not use this file except in compliance with the Elastic License
|
|
5
|
+
* 2.0.
|
|
6
|
+
*/
|
|
7
|
+
import { requiredString } from '../define/zod_helpers.js';
|
|
8
|
+
// The one URL trust policy every URL-bearing field goes through, as a Zod
|
|
9
|
+
// refinement and again as render-time sanitization. See `docs/url-trust.md`.
|
|
10
|
+
const NAMED_REFERENCES = {
|
|
11
|
+
bsol: '\\',
|
|
12
|
+
colon: ':',
|
|
13
|
+
gt: '>',
|
|
14
|
+
lt: '<',
|
|
15
|
+
newline: '\n',
|
|
16
|
+
sol: '/',
|
|
17
|
+
tab: '\t',
|
|
18
|
+
};
|
|
19
|
+
// Numeric references, which browsers decode without a trailing `;`, and the
|
|
20
|
+
// named ones that spell a scheme, path, or tag character.
|
|
21
|
+
const CHARACTER_REFERENCE_RE = /&(?:#x([0-9a-f]+);?|#([0-9]+);?|(bsol|colon|gt|lt|newline|sol|tab);)/gi;
|
|
22
|
+
const decodeReference = (match, hex, decimal, name) => {
|
|
23
|
+
if (name)
|
|
24
|
+
return NAMED_REFERENCES[name.toLowerCase()] ?? match;
|
|
25
|
+
const codePoint = Number.parseInt(hex ?? decimal ?? '', hex ? 16 : 10);
|
|
26
|
+
return codePoint > 0 && codePoint <= 0x10ffff
|
|
27
|
+
? String.fromCodePoint(codePoint)
|
|
28
|
+
: '\ufffd';
|
|
29
|
+
};
|
|
30
|
+
// The control characters browsers drop when parsing a URL.
|
|
31
|
+
const stripControls = (value) =>
|
|
32
|
+
// eslint-disable-next-line no-control-regex -- stripping control characters is the point.
|
|
33
|
+
value.replace(/[\u0000-\u001f\u007f]/g, '').trim();
|
|
34
|
+
// The URL as a sink sees it: references decoded once, then controls stripped,
|
|
35
|
+
// so an obfuscated scheme is checked as it would act. Only the decision reads
|
|
36
|
+
// it; the policy returns the authored value, since a consumer that decodes
|
|
37
|
+
// again must decode what was checked, not a decoded copy.
|
|
38
|
+
const decisionForm = (value) => stripControls(value.replace(CHARACTER_REFERENCE_RE, decodeReference));
|
|
39
|
+
// `<` and `>` must be percent-encoded in a URL, so their unencoded presence
|
|
40
|
+
// means the value is malformed or a parser-confusion attempt (an unterminated
|
|
41
|
+
// `<dest` would otherwise read as a relative path). Reject rather than strip.
|
|
42
|
+
const HAS_ANGLE_BRACKET_RE = /[<>]/;
|
|
43
|
+
const HAS_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;
|
|
44
|
+
const NAVIGATION_SCHEME_RE = /^(?:https?|mailto):/i;
|
|
45
|
+
const ASSET_SCHEME_RE = /^(?:https?:|data:image\/)/i;
|
|
46
|
+
// `//host` — and the `\` variants browsers fold into `/` — resolve against the
|
|
47
|
+
// current protocol onto a foreign host, so they are not relative paths.
|
|
48
|
+
const PROTOCOL_RELATIVE_RE = /^[/\\][/\\]/;
|
|
49
|
+
// Whether a URL in decision form passes, given which schemes are allowed.
|
|
50
|
+
const passes = (decided, schemes) => decided !== '' &&
|
|
51
|
+
!PROTOCOL_RELATIVE_RE.test(decided) &&
|
|
52
|
+
!HAS_ANGLE_BRACKET_RE.test(decided) &&
|
|
53
|
+
(!HAS_SCHEME_RE.test(decided) || schemes.test(decided));
|
|
54
|
+
/**
|
|
55
|
+
* Returns the URL, trimmed and with control characters stripped, when it
|
|
56
|
+
* satisfies the navigation policy (`https:` / `http:` / `mailto:` / relative
|
|
57
|
+
* path), `null` otherwise.
|
|
58
|
+
*/
|
|
59
|
+
export const sanitizeNavigationHref = (href) => passes(decisionForm(href), NAVIGATION_SCHEME_RE) ? stripControls(href) : null;
|
|
60
|
+
/**
|
|
61
|
+
* Returns the URL, trimmed and with control characters stripped, when it
|
|
62
|
+
* satisfies the asset policy (`https:` / `http:` / relative path /
|
|
63
|
+
* `data:image/*`), `null` otherwise.
|
|
64
|
+
*/
|
|
65
|
+
export const sanitizeAssetUrl = (url) => passes(decisionForm(url), ASSET_SCHEME_RE) ? stripControls(url) : null;
|
|
66
|
+
/** Checks a Markdown parser's decoded destination without decoding it again. */
|
|
67
|
+
export const sanitizeParsedNavigationHref = (href) => {
|
|
68
|
+
const normalized = stripControls(href);
|
|
69
|
+
return passes(normalized, NAVIGATION_SCHEME_RE) ? normalized : null;
|
|
70
|
+
};
|
|
71
|
+
/** Checks a Markdown parser's decoded image destination. */
|
|
72
|
+
export const sanitizeParsedAssetUrl = (url) => {
|
|
73
|
+
const normalized = stripControls(url);
|
|
74
|
+
return passes(normalized, ASSET_SCHEME_RE) ? normalized : null;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Render-time replacement for a navigation href that failed the policy: an
|
|
78
|
+
* inert same-document link, so the label stays visible without a destination.
|
|
79
|
+
*/
|
|
80
|
+
export const BLOCKED_HREF = '#';
|
|
81
|
+
/** What {@link navigationHref} accepts, for a field description to state. */
|
|
82
|
+
export const NAVIGATION_HREF_RULE = 'an https, http, or mailto URL, or a relative path';
|
|
83
|
+
/** What {@link assetUrl} accepts, for a field description to state. */
|
|
84
|
+
export const ASSET_URL_RULE = 'an https, http, or data:image URL, or a relative path';
|
|
85
|
+
/** Validation message for {@link navigationHref}. */
|
|
86
|
+
export const NAVIGATION_HREF_MESSAGE = `must be ${NAVIGATION_HREF_RULE}`;
|
|
87
|
+
/** Validation message for {@link assetUrl}. */
|
|
88
|
+
export const ASSET_URL_MESSAGE = `must be ${ASSET_URL_RULE}`;
|
|
89
|
+
const urlSchema = (passes, rule, message, { max }) => (max === undefined ? requiredString() : requiredString().max(max))
|
|
90
|
+
.refine(passes, { error: message })
|
|
91
|
+
.describe(`${rule[0].toUpperCase()}${rule.slice(1)}.`);
|
|
92
|
+
/**
|
|
93
|
+
* Zod schema for an `href`-like field: the validation layer of the two-layer
|
|
94
|
+
* policy, paired with {@link sanitizeNavigationHref} at render time.
|
|
95
|
+
*
|
|
96
|
+
* Its description states the rule, since a refinement's message does not
|
|
97
|
+
* reach the authoring JSON Schema. A field that describes itself should end
|
|
98
|
+
* with {@link NAVIGATION_HREF_RULE} so the model still reads it.
|
|
99
|
+
*/
|
|
100
|
+
export const navigationHref = (options = {}) => urlSchema((value) => sanitizeNavigationHref(value) !== null, NAVIGATION_HREF_RULE, NAVIGATION_HREF_MESSAGE, options);
|
|
101
|
+
/**
|
|
102
|
+
* Zod schema for a `src`-like field, paired with {@link sanitizeAssetUrl} at
|
|
103
|
+
* render time. Describes itself as {@link navigationHref} does, with
|
|
104
|
+
* {@link ASSET_URL_RULE}.
|
|
105
|
+
*/
|
|
106
|
+
export const assetUrl = (options = {}) => urlSchema((value) => sanitizeAssetUrl(value) !== null, ASSET_URL_RULE, ASSET_URL_MESSAGE, options);
|
|
107
|
+
//# sourceMappingURL=url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/validate/url.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport { requiredString } from '../define/zod_helpers';\n\n// The one URL trust policy every URL-bearing field goes through, as a Zod\n// refinement and again as render-time sanitization. See `docs/url-trust.md`.\n\nconst NAMED_REFERENCES: Readonly<Record<string, string>> = {\n bsol: '\\\\',\n colon: ':',\n gt: '>',\n lt: '<',\n newline: '\\n',\n sol: '/',\n tab: '\\t',\n};\n\n// Numeric references, which browsers decode without a trailing `;`, and the\n// named ones that spell a scheme, path, or tag character.\nconst CHARACTER_REFERENCE_RE =\n /&(?:#x([0-9a-f]+);?|#([0-9]+);?|(bsol|colon|gt|lt|newline|sol|tab);)/gi;\n\nconst decodeReference = (\n match: string,\n hex: string | undefined,\n decimal: string | undefined,\n name: string | undefined\n): string => {\n if (name) return NAMED_REFERENCES[name.toLowerCase()] ?? match;\n const codePoint = Number.parseInt(hex ?? decimal ?? '', hex ? 16 : 10);\n return codePoint > 0 && codePoint <= 0x10ffff\n ? String.fromCodePoint(codePoint)\n : '\\ufffd';\n};\n\n// The control characters browsers drop when parsing a URL.\nconst stripControls = (value: string): string =>\n // eslint-disable-next-line no-control-regex -- stripping control characters is the point.\n value.replace(/[\\u0000-\\u001f\\u007f]/g, '').trim();\n\n// The URL as a sink sees it: references decoded once, then controls stripped,\n// so an obfuscated scheme is checked as it would act. Only the decision reads\n// it; the policy returns the authored value, since a consumer that decodes\n// again must decode what was checked, not a decoded copy.\nconst decisionForm = (value: string): string =>\n stripControls(value.replace(CHARACTER_REFERENCE_RE, decodeReference));\n\n// `<` and `>` must be percent-encoded in a URL, so their unencoded presence\n// means the value is malformed or a parser-confusion attempt (an unterminated\n// `<dest` would otherwise read as a relative path). Reject rather than strip.\nconst HAS_ANGLE_BRACKET_RE = /[<>]/;\nconst HAS_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;\nconst NAVIGATION_SCHEME_RE = /^(?:https?|mailto):/i;\nconst ASSET_SCHEME_RE = /^(?:https?:|data:image\\/)/i;\n// `//host` — and the `\\` variants browsers fold into `/` — resolve against the\n// current protocol onto a foreign host, so they are not relative paths.\nconst PROTOCOL_RELATIVE_RE = /^[/\\\\][/\\\\]/;\n\n// Whether a URL in decision form passes, given which schemes are allowed.\nconst passes = (decided: string, schemes: RegExp): boolean =>\n decided !== '' &&\n !PROTOCOL_RELATIVE_RE.test(decided) &&\n !HAS_ANGLE_BRACKET_RE.test(decided) &&\n (!HAS_SCHEME_RE.test(decided) || schemes.test(decided));\n\n/**\n * Returns the URL, trimmed and with control characters stripped, when it\n * satisfies the navigation policy (`https:` / `http:` / `mailto:` / relative\n * path), `null` otherwise.\n */\nexport const sanitizeNavigationHref = (href: string): string | null =>\n passes(decisionForm(href), NAVIGATION_SCHEME_RE) ? stripControls(href) : null;\n\n/**\n * Returns the URL, trimmed and with control characters stripped, when it\n * satisfies the asset policy (`https:` / `http:` / relative path /\n * `data:image/*`), `null` otherwise.\n */\nexport const sanitizeAssetUrl = (url: string): string | null =>\n passes(decisionForm(url), ASSET_SCHEME_RE) ? stripControls(url) : null;\n\n/** Checks a Markdown parser's decoded destination without decoding it again. */\nexport const sanitizeParsedNavigationHref = (href: string): string | null => {\n const normalized = stripControls(href);\n return passes(normalized, NAVIGATION_SCHEME_RE) ? normalized : null;\n};\n\n/** Checks a Markdown parser's decoded image destination. */\nexport const sanitizeParsedAssetUrl = (url: string): string | null => {\n const normalized = stripControls(url);\n return passes(normalized, ASSET_SCHEME_RE) ? normalized : null;\n};\n\n/**\n * Render-time replacement for a navigation href that failed the policy: an\n * inert same-document link, so the label stays visible without a destination.\n */\nexport const BLOCKED_HREF = '#';\n\n/** What {@link navigationHref} accepts, for a field description to state. */\nexport const NAVIGATION_HREF_RULE =\n 'an https, http, or mailto URL, or a relative path';\n\n/** What {@link assetUrl} accepts, for a field description to state. */\nexport const ASSET_URL_RULE =\n 'an https, http, or data:image URL, or a relative path';\n\n/** Validation message for {@link navigationHref}. */\nexport const NAVIGATION_HREF_MESSAGE = `must be ${NAVIGATION_HREF_RULE}`;\n\n/** Validation message for {@link assetUrl}. */\nexport const ASSET_URL_MESSAGE = `must be ${ASSET_URL_RULE}`;\n\n/** Options for {@link navigationHref} and {@link assetUrl}. */\nexport interface UrlSchemaOptions {\n /** Longest accepted value, in characters. */\n max?: number;\n}\n\nconst urlSchema = (\n passes: (value: string) => boolean,\n rule: string,\n message: string,\n { max }: UrlSchemaOptions\n) =>\n (max === undefined ? requiredString() : requiredString().max(max))\n .refine(passes, { error: message })\n .describe(`${rule[0]!.toUpperCase()}${rule.slice(1)}.`);\n\n/**\n * Zod schema for an `href`-like field: the validation layer of the two-layer\n * policy, paired with {@link sanitizeNavigationHref} at render time.\n *\n * Its description states the rule, since a refinement's message does not\n * reach the authoring JSON Schema. A field that describes itself should end\n * with {@link NAVIGATION_HREF_RULE} so the model still reads it.\n */\nexport const navigationHref = (options: UrlSchemaOptions = {}) =>\n urlSchema(\n (value) => sanitizeNavigationHref(value) !== null,\n NAVIGATION_HREF_RULE,\n NAVIGATION_HREF_MESSAGE,\n options\n );\n\n/**\n * Zod schema for a `src`-like field, paired with {@link sanitizeAssetUrl} at\n * render time. Describes itself as {@link navigationHref} does, with\n * {@link ASSET_URL_RULE}.\n */\nexport const assetUrl = (options: UrlSchemaOptions = {}) =>\n urlSchema(\n (value) => sanitizeAssetUrl(value) !== null,\n ASSET_URL_RULE,\n ASSET_URL_MESSAGE,\n options\n );\n"]}
|