@morit/cli 1.4.2 → 1.5.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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "sdk_version": "1.7.12",
2
+ "sdk_version": "1.7.13",
3
3
  "manifest_schema_versions": [1, 2],
4
4
  "recommended_schema_version": 2,
5
5
  "package_content_type": "application/vnd.morit.plugin+zip",
@@ -293,7 +293,8 @@
293
293
  ,"suggestions_source"
294
294
  ,"searchable"
295
295
  ,"options_source"
296
- ,"submit_label"
296
+ ,"submit_label",
297
+ "gradient_colors", "item_key", "font_size", "font_weight", "line_height", "selected_background_color", "selected_foreground_color", "disabled_background_color", "pressed_color"
297
298
  ],
298
299
  "app_bar_fields": ["title", "subtitle", "center_title", "pinned", "leading", "actions"],
299
300
  "navigation_fields": ["type", "items", "selected_state_key", "persist", "label_behavior", "rail_breakpoint"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morit/cli",
3
- "version": "1.4.2",
3
+ "version": "1.5.0",
4
4
  "description": "Official Morit Developer CLI for Cloud Projects, validation, builds, and deployments",
5
5
  "type": "module",
6
6
  "bin": {
package/src/workspace.js CHANGED
@@ -152,7 +152,7 @@ export class LocalWorkspace {
152
152
  version: "1.0.0",
153
153
  cloud_project_id: null,
154
154
  required_secrets: [],
155
- min_morit_version: "1.7.12",
155
+ min_morit_version: "1.7.13",
156
156
  max_morit_version: "1.999.999",
157
157
  permissions: [],
158
158
  capabilities: [],
@@ -738,6 +738,14 @@ function validateMetadata(pluginId, name, publisher, description) {
738
738
  if (typeof description !== "string" || description.length > 4000) throw new Error("description must not exceed 4000 characters");
739
739
  }
740
740
 
741
+ function usesUi1713(node) {
742
+ if (!node || typeof node !== "object") return false;
743
+ const props = node.props || {};
744
+ return ["gradient_colors", "item_key", "font_size", "font_weight", "line_height", "selected_background_color", "selected_foreground_color", "disabled_background_color", "pressed_color"].some(key => Object.hasOwn(props, key))
745
+ || (node.type === "list" && props.scroll_direction === "horizontal")
746
+ || (Array.isArray(node.children) && node.children.some(usesUi1713));
747
+ }
748
+
741
749
  function validateManifest(manifest, files) {
742
750
  assertObject(manifest, "manifest");
743
751
  rejectUnknownFields(manifest, MANIFEST_FIELDS, "manifest");
@@ -782,6 +790,8 @@ function validateManifest(manifest, files) {
782
790
  if (!["purge", "retain"].includes(manifest.data_policy)) throw new Error("manifest.data_policy must be purge or retain");
783
791
  const capabilities = objectCollection(manifest.capabilities, "manifest.capabilities", 64);
784
792
  const uiExtensions = objectCollection(manifest.ui_extensions, "manifest.ui_extensions", 64);
793
+ const minimum = manifest.min_morit_version.split(".").map(Number);
794
+ if ((minimum[0] < 1 || (minimum[0] === 1 && (minimum[1] < 7 || (minimum[1] === 7 && minimum[2] < 13)))) && uiExtensions.some(extension => usesUi1713(extension.config?.view))) throw new Error("new UI properties require min_morit_version 1.7.13 or newer");
785
795
  const credentials = objectCollection(manifest.credentials === undefined ? [] : manifest.credentials, "manifest.credentials", 16);
786
796
  const slashCommands = objectCollection(manifest.slash_commands === undefined ? [] : manifest.slash_commands, "manifest.slash_commands", 32);
787
797
  const connectors = objectCollection(manifest.connectors === undefined ? [] : manifest.connectors, "manifest.connectors", 32);
@@ -1691,8 +1701,9 @@ function validateUiProps(nodeType, props, sources, stateKeys) {
1691
1701
  const allowed = new Set(contract.ui_runtime.prop_fields);
1692
1702
  rejectUnknownFields(props, allowed, "UI component props");
1693
1703
  const surfaceProps = new Set([
1704
+ "selected",
1694
1705
  "spacing", "padding", "margin", "width", "height", "min_width", "max_width", "min_height", "max_height",
1695
- "alignment", "color", "background_color", "foreground_color", "border_color", "border_width",
1706
+ "alignment", "color", "gradient_colors", "selected_background_color", "selected_foreground_color", "disabled_background_color", "pressed_color", "background_color", "foreground_color", "border_color", "border_width",
1696
1707
  "border_radius", "elevation", "opacity", "clip", "enabled", "tooltip", "semantic_label", "exclude_semantics",
1697
1708
  ]);
1698
1709
  if (nodeType === "surface") rejectUnknownFields(props, surfaceProps, "surface UI component props");
@@ -1726,7 +1737,15 @@ function validateUiProps(nodeType, props, sources, stateKeys) {
1726
1737
  if (props.main_axis_alignment !== undefined && !["start", "end", "center", "space_between", "space_around", "space_evenly"].includes(props.main_axis_alignment)) throw new Error("UI main-axis alignment is invalid");
1727
1738
  if (props.cross_axis_alignment !== undefined && !["start", "end", "center", "stretch", "baseline"].includes(props.cross_axis_alignment)) throw new Error("UI cross-axis alignment is invalid");
1728
1739
  if (props.main_axis_size !== undefined && !["min", "max"].includes(props.main_axis_size)) throw new Error("UI main-axis size is invalid");
1729
- for (const key of ["color", "background_color", "foreground_color", "border_color"]) if (props[key] !== undefined) validateUiColor(props[key], `UI ${key}`);
1740
+ if (props.font_size !== undefined) validateUiNumber(props.font_size, "UI font_size", 10, 64);
1741
+ if (props.line_height !== undefined) validateUiNumber(props.line_height, "UI line_height", 1, 2.5);
1742
+ if (props.font_weight !== undefined && (!Number.isInteger(props.font_weight) || props.font_weight < 100 || props.font_weight > 900 || props.font_weight % 100)) throw new Error("invalid UI font_weight");
1743
+ if (props.gradient_colors !== undefined) {
1744
+ if (!Array.isArray(props.gradient_colors) || props.gradient_colors.length < 2 || props.gradient_colors.length > 8) throw new Error("invalid UI gradient_colors: expected 2–8 colors");
1745
+ for (const color of props.gradient_colors) validateUiColor(color, "UI gradient_colors");
1746
+ }
1747
+ if (props.item_key !== undefined && (typeof props.item_key !== "string" || !/^[A-Za-z0-9_-]{1,80}$/.test(props.item_key))) throw new Error("invalid UI item_key");
1748
+ for (const key of ["color", "background_color", "foreground_color", "border_color", "selected_background_color", "selected_foreground_color", "disabled_background_color", "pressed_color"]) if (props[key] !== undefined) validateUiColor(props[key], `UI ${key}`);
1730
1749
  if (props.border_width !== undefined) validateUiNumber(props.border_width, "UI border width", 0, 8);
1731
1750
  if (props.border_radius !== undefined) validateUiNumber(props.border_radius, "UI border radius", 0, 64);
1732
1751
  if (props.elevation !== undefined) validateUiNumber(props.elevation, "UI elevation", 0, 24);
@@ -1748,7 +1767,7 @@ function validateUiProps(nodeType, props, sources, stateKeys) {
1748
1767
  )) throw new Error("positioned UI component over-constrains an axis");
1749
1768
  if (nodeType !== "positioned" && ["left", "top", "right", "bottom"].some((key) => props[key] !== undefined)) throw new Error("position offsets require a positioned UI component");
1750
1769
  if (nodeType !== "expanded" && props.flex !== undefined) throw new Error("flex requires an expanded UI component");
1751
- if (nodeType !== "scroll" && ["scroll_direction", "shrink_wrap"].some((key) => props[key] !== undefined)) throw new Error("scroll properties require a scroll UI component");
1770
+ if ((nodeType !== "scroll" && props.shrink_wrap !== undefined) || (!["scroll", "list"].includes(nodeType) && props.scroll_direction !== undefined)) throw new Error("scroll properties require a scroll UI component");
1752
1771
  if (["list", "timeline", "calendar", "chart", "table"].includes(nodeType)) {
1753
1772
  if (typeof props.source !== "string" || !UI_BINDING.test(props.source) || !props.source.startsWith("data.") || !sources.has(props.source.split(".")[1])) throw new Error("UI list source is invalid");
1754
1773
  }