cmx-sdk 0.2.6 → 0.2.8

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.
Files changed (48) hide show
  1. package/README.md +16 -0
  2. package/dist/add-studio-YUDYE2OH.js +72 -0
  3. package/dist/{chunk-XPP5MZKG.js → chunk-7TDMLYBI.js} +17 -45
  4. package/dist/chunk-EDXXR5BE.js +80 -0
  5. package/dist/chunk-EZMBZWH7.js +121 -0
  6. package/dist/chunk-FPQYL5GE.js +128 -0
  7. package/dist/chunk-NZQ6SBFS.js +35 -0
  8. package/dist/cli.js +1152 -619
  9. package/dist/index.d.ts +253 -385
  10. package/dist/index.js +154 -25
  11. package/dist/index.js.map +1 -1
  12. package/dist/{init-NDNG5Q5T.js → init-FLRQXJX4.js} +23 -51
  13. package/dist/interactive-menu-FYVOQSTL.js +80 -0
  14. package/dist/studio-HAS6DYLO.js +8 -0
  15. package/dist/update-sdk-KJZ6VB4M.js +10 -0
  16. package/dist/update-studio-TWCYSYIS.js +14 -0
  17. package/package.json +18 -10
  18. package/templates/AGENTS.md +173 -0
  19. package/templates/CLAUDE.md +28 -0
  20. package/templates/claude/commands/check.md +64 -0
  21. package/templates/claude/commands/next-action.md +66 -0
  22. package/templates/claude/skills/cmx-cache/SKILL.md +50 -0
  23. package/templates/claude/skills/cmx-cache/references/cache-patterns.md +153 -0
  24. package/templates/claude/skills/cmx-component/SKILL.md +108 -0
  25. package/templates/claude/skills/cmx-component/references/component-schema.md +123 -0
  26. package/templates/claude/skills/cmx-content/SKILL.md +158 -0
  27. package/templates/claude/skills/cmx-content/references/migration-patterns.md +120 -0
  28. package/templates/claude/skills/cmx-content/references/seed-patterns.md +146 -0
  29. package/templates/claude/skills/cmx-dev/SKILL.md +266 -0
  30. package/templates/claude/skills/cmx-dev/references/api-patterns.md +220 -0
  31. package/templates/claude/skills/cmx-dev/references/cli-reference.md +54 -0
  32. package/templates/claude/skills/cmx-form/SKILL.md +103 -0
  33. package/templates/claude/skills/cmx-form/references/form-template.md +152 -0
  34. package/templates/claude/skills/cmx-migrate/SKILL.md +501 -0
  35. package/templates/claude/skills/cmx-migrate/references/analysis-guide.md +127 -0
  36. package/templates/claude/skills/cmx-migrate/references/html-to-mdx.md +99 -0
  37. package/templates/claude/skills/cmx-migrate/references/intermediate-format.md +196 -0
  38. package/templates/claude/skills/cmx-migrate/references/tool-setup.md +150 -0
  39. package/templates/claude/skills/cmx-schema/SKILL.md +159 -0
  40. package/templates/claude/skills/cmx-schema/references/field-types.md +164 -0
  41. package/templates/claude/skills/cmx-schema/references/migration-scenarios.md +44 -0
  42. package/templates/claude/skills/cmx-seo/SKILL.md +54 -0
  43. package/templates/claude/skills/cmx-seo/references/seo-patterns.md +216 -0
  44. package/templates/claude/skills/cmx-style/SKILL.md +48 -0
  45. package/templates/claude/skills/cmx-style/references/style-patterns.md +114 -0
  46. package/dist/add-studio-J7M7KOWM.js +0 -125
  47. package/dist/interactive-menu-RPPCBCOU.js +0 -66
  48. package/dist/studio-3YGVKWS4.js +0 -7
package/dist/index.js CHANGED
@@ -22,6 +22,46 @@ var CmxApiError = class extends Error {
22
22
 
23
23
  // src/core/sdk-fetcher.ts
24
24
  var DEFAULT_API_URL = "https://app.cmx-ai.org";
25
+ function stringifyErrorValue(value) {
26
+ if (typeof value === "string") return value;
27
+ if (value === null || value === void 0) return "";
28
+ if (typeof value === "object") {
29
+ const objectValue = value;
30
+ if (typeof objectValue.message === "string" && objectValue.message.length > 0) {
31
+ return objectValue.message;
32
+ }
33
+ try {
34
+ return JSON.stringify(value);
35
+ } catch {
36
+ return String(value);
37
+ }
38
+ }
39
+ return String(value);
40
+ }
41
+ function parseSdkErrorBody(body, status) {
42
+ const fallbackMessage = `API error: ${status}`;
43
+ if (!body) {
44
+ return { message: fallbackMessage };
45
+ }
46
+ try {
47
+ const parsed = JSON.parse(body);
48
+ const main = stringifyErrorValue(parsed.error ?? parsed.message);
49
+ const details = stringifyErrorValue(parsed.details);
50
+ const code = typeof parsed.code === "string" ? parsed.code : void 0;
51
+ const message = [main, details].filter((part, index, parts) => part.length > 0 && parts.indexOf(part) === index).join(" | ");
52
+ return {
53
+ message: message || fallbackMessage,
54
+ code
55
+ };
56
+ } catch {
57
+ return { message: body };
58
+ }
59
+ }
60
+ async function toCmxApiError(response) {
61
+ const body = await response.text();
62
+ const { message, code } = parseSdkErrorBody(body, response.status);
63
+ return new CmxApiError(message, response.status, code);
64
+ }
25
65
  function getSdkApiBaseUrl() {
26
66
  const apiUrl = process.env.CMX_API_URL || DEFAULT_API_URL;
27
67
  return `${apiUrl}/api/v1/sdk`;
@@ -50,8 +90,7 @@ async function sdkFetcher(path, options) {
50
90
  };
51
91
  const response = await fetch(url, fetchOptions);
52
92
  if (!response.ok) {
53
- const error = await response.json().catch(() => ({ error: "Unknown error" }));
54
- throw new CmxApiError(error.error || `API error: ${response.status}`, response.status, error.code);
93
+ throw await toCmxApiError(response);
55
94
  }
56
95
  return response.json();
57
96
  }
@@ -68,8 +107,7 @@ async function sdkCustomInstance(url, options) {
68
107
  }
69
108
  });
70
109
  if (!response.ok) {
71
- const error = await response.json().catch(() => ({ error: "Unknown error" }));
72
- throw new CmxApiError(error.error || `API error: ${response.status}`, response.status, error.code);
110
+ throw await toCmxApiError(response);
73
111
  }
74
112
  return response.json();
75
113
  }
@@ -90,8 +128,7 @@ async function sdkFetchWithTags(path, tags, revalidate) {
90
128
  };
91
129
  const response = await fetch(url, fetchOptions);
92
130
  if (!response.ok) {
93
- const error = await response.json().catch(() => ({ error: "Unknown error" }));
94
- throw new CmxApiError(error.error || `API error: ${response.status}`, response.status, error.code);
131
+ throw await toCmxApiError(response);
95
132
  }
96
133
  return response.json();
97
134
  }
@@ -109,8 +146,7 @@ async function sdkPostFetcher(path, body) {
109
146
  cache: "no-store"
110
147
  });
111
148
  if (!response.ok) {
112
- const error = await response.json().catch(() => ({ error: "Unknown error" }));
113
- throw new CmxApiError(error.error || `API error: ${response.status}`, response.status, error.code);
149
+ throw await toCmxApiError(response);
114
150
  }
115
151
  return response.json();
116
152
  }
@@ -783,7 +819,7 @@ function getZodTypeName(zodType) {
783
819
  // src/mdx/validator.ts
784
820
  import { compile } from "@mdx-js/mdx";
785
821
  var FORBIDDEN_PATTERNS = [
786
- // import/export statements
822
+ // import/export statements (at MDX level, not inside code blocks)
787
823
  { pattern: /^\s*import\s+/m, message: "import\u6587\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093" },
788
824
  { pattern: /^\s*export\s+/m, message: "export\u6587\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093" },
789
825
  // JS expressions in curly braces (except component props)
@@ -800,21 +836,111 @@ var FORBIDDEN_PATTERNS = [
800
836
  // data: URLs (for images - can be XSS vector)
801
837
  { pattern: /src\s*=\s*["']?\s*data:/i, message: "data: URL\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093" }
802
838
  ];
839
+ function stripCodeBlocksForPatternCheck(mdx) {
840
+ let result = mdx.replace(/<CodeBlock[^>]*>([^]*?)<\/CodeBlock>/g, (_match, content) => {
841
+ const newlineCount = (content.match(/\n/g) || []).length;
842
+ return "<CodeBlock>__CODE_PLACEHOLDER__" + "\n".repeat(newlineCount) + "</CodeBlock>";
843
+ });
844
+ result = result.replace(/```[\s\S]*?```/g, (match) => {
845
+ const newlineCount = (match.match(/\n/g) || []).length;
846
+ return "```__CODE_PLACEHOLDER__" + "\n".repeat(Math.max(0, newlineCount - 1)) + "```";
847
+ });
848
+ return result;
849
+ }
850
+ function escapeCodeBlocksForCompile(mdx) {
851
+ let result = mdx.replace(/<CodeBlock([^>]*)>([^]*?)<\/CodeBlock>/g, (_match, attrs, content) => {
852
+ const escapedContent = content.replace(/^(\s*)(import|export)\s/gm, "$1/* $2 */ ").replace(/\{/g, "&#123;").replace(/\}/g, "&#125;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
853
+ return `<CodeBlock${attrs}>${escapedContent}</CodeBlock>`;
854
+ });
855
+ result = result.replace(/```([a-z]*)\n([\s\S]*?)```/g, (_match, lang, content) => {
856
+ const escapedContent = content.replace(/^(\s*)(import|export)\s/gm, "$1/* $2 */ ").replace(/\{/g, "&#123;").replace(/\}/g, "&#125;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
857
+ return "```" + lang + "\n" + escapedContent + "```";
858
+ });
859
+ return result;
860
+ }
803
861
  function extractComponents(mdx) {
804
862
  const components = [];
805
863
  const lines = mdx.split("\n");
806
- const componentPattern = /<([A-Z][a-zA-Z0-9]*)\s*([^>]*?)\s*\/?>/g;
807
- for (let i = 0; i < lines.length; i++) {
808
- const line = lines[i];
809
- let match;
810
- while ((match = componentPattern.exec(line)) !== null) {
811
- const name = match[1];
812
- const propsString = match[2];
813
- const props = parseProps(propsString);
864
+ const lineOffsets = [];
865
+ let offset = 0;
866
+ for (const line of lines) {
867
+ lineOffsets.push(offset);
868
+ offset += line.length + 1;
869
+ }
870
+ function getLineNumber(index) {
871
+ let lo = 0, hi = lineOffsets.length - 1;
872
+ while (lo < hi) {
873
+ const mid = Math.floor((lo + hi + 1) / 2);
874
+ if (lineOffsets[mid] <= index) {
875
+ lo = mid;
876
+ } else {
877
+ hi = mid - 1;
878
+ }
879
+ }
880
+ return lo + 1;
881
+ }
882
+ const stack = [];
883
+ let i = 0;
884
+ while (i < mdx.length) {
885
+ if (mdx[i] !== "<") {
886
+ i++;
887
+ continue;
888
+ }
889
+ const tagStart = i;
890
+ i++;
891
+ if (mdx[i] === "/") {
892
+ i++;
893
+ const closeMatch = mdx.slice(i).match(/^([A-Z][a-zA-Z0-9]*)\s*>/);
894
+ if (closeMatch) {
895
+ const closingName = closeMatch[1];
896
+ i += closeMatch[0].length;
897
+ for (let s = stack.length - 1; s >= 0; s--) {
898
+ if (stack[s].name === closingName) {
899
+ const opening = stack[s];
900
+ const children = mdx.slice(opening.contentStart, tagStart).trim();
901
+ const props = parseProps(opening.propsString);
902
+ if (children) {
903
+ props.children = children;
904
+ }
905
+ components.push({
906
+ name: opening.name,
907
+ props,
908
+ line: opening.line
909
+ });
910
+ stack.splice(s, 1);
911
+ break;
912
+ }
913
+ }
914
+ }
915
+ continue;
916
+ }
917
+ if (mdx[i] === "!" && mdx[i + 1] === "-" && mdx[i + 2] === "-") {
918
+ const commentEnd = mdx.indexOf("-->", i + 3);
919
+ i = commentEnd !== -1 ? commentEnd + 3 : mdx.length;
920
+ continue;
921
+ }
922
+ const tagMatch = mdx.slice(i).match(/^([A-Z][a-zA-Z0-9]*)([\s\S]*?)(\/)?>/);
923
+ if (!tagMatch) {
924
+ continue;
925
+ }
926
+ const name = tagMatch[1];
927
+ const attrsPart = tagMatch[2].trim();
928
+ const isSelfClosing = tagMatch[3] === "/";
929
+ i += tagMatch[0].length;
930
+ if (isSelfClosing) {
814
931
  components.push({
815
932
  name,
816
- props,
817
- line: i + 1
933
+ props: parseProps(attrsPart),
934
+ line: getLineNumber(tagStart)
935
+ });
936
+ } else {
937
+ stack.push({
938
+ name,
939
+ propsString: attrsPart,
940
+ tagStart,
941
+ contentStart: tagStart + 1 + tagMatch[0].length,
942
+ // after '>'
943
+ line: getLineNumber(tagStart)
818
944
  });
819
945
  }
820
946
  }
@@ -879,9 +1005,10 @@ function extractReferences(components) {
879
1005
  async function validateMdx(mdx) {
880
1006
  const errors = [];
881
1007
  const warnings = [];
1008
+ const mdxWithoutCodeBlocks = stripCodeBlocksForPatternCheck(mdx);
882
1009
  for (const { pattern, message } of FORBIDDEN_PATTERNS) {
883
- if (pattern.test(mdx)) {
884
- const lines = mdx.split("\n");
1010
+ if (pattern.test(mdxWithoutCodeBlocks)) {
1011
+ const lines = mdxWithoutCodeBlocks.split("\n");
885
1012
  for (let i = 0; i < lines.length; i++) {
886
1013
  if (pattern.test(lines[i])) {
887
1014
  errors.push({
@@ -894,10 +1021,10 @@ async function validateMdx(mdx) {
894
1021
  }
895
1022
  }
896
1023
  }
1024
+ const escapedMdx = escapeCodeBlocksForCompile(mdx);
897
1025
  try {
898
- await compile(mdx, {
1026
+ await compile(escapedMdx, {
899
1027
  development: false
900
- // Minimal compilation to check syntax
901
1028
  });
902
1029
  } catch (error) {
903
1030
  const err = error;
@@ -908,7 +1035,8 @@ async function validateMdx(mdx) {
908
1035
  column: err.column
909
1036
  });
910
1037
  }
911
- const components = extractComponents(mdx);
1038
+ const mdxForComponentExtraction = stripCodeBlocksForPatternCheck(mdx);
1039
+ const components = extractComponents(mdxForComponentExtraction);
912
1040
  for (const component of components) {
913
1041
  if (!isValidComponent(component.name)) {
914
1042
  errors.push({
@@ -941,8 +1069,9 @@ async function validateMdx(mdx) {
941
1069
  }
942
1070
  function quickValidateMdx(mdx) {
943
1071
  const errors = [];
1072
+ const mdxWithoutCodeBlocks = stripCodeBlocksForPatternCheck(mdx);
944
1073
  for (const { pattern, message } of FORBIDDEN_PATTERNS) {
945
- if (pattern.test(mdx)) {
1074
+ if (pattern.test(mdxWithoutCodeBlocks)) {
946
1075
  errors.push({
947
1076
  type: "forbidden",
948
1077
  message