@forumone/throughline-components 0.0.1 → 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.
Files changed (68) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +117 -28
  4. package/dist/index.d.ts +3 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +2 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/manifest-source.d.ts +17 -0
  9. package/dist/manifest-source.d.ts.map +1 -0
  10. package/dist/manifest-source.js +60 -0
  11. package/dist/manifest-source.js.map +1 -0
  12. package/dist/matching/index.d.ts +3 -0
  13. package/dist/matching/index.d.ts.map +1 -0
  14. package/dist/matching/index.js +2 -0
  15. package/dist/matching/index.js.map +1 -0
  16. package/dist/matching/tfidf.d.ts +13 -0
  17. package/dist/matching/tfidf.d.ts.map +1 -0
  18. package/dist/matching/tfidf.js +118 -0
  19. package/dist/matching/tfidf.js.map +1 -0
  20. package/dist/matching/types.d.ts +22 -0
  21. package/dist/matching/types.d.ts.map +1 -0
  22. package/dist/matching/types.js +2 -0
  23. package/dist/matching/types.js.map +1 -0
  24. package/dist/options.d.ts +125 -0
  25. package/dist/options.d.ts.map +1 -0
  26. package/dist/options.js +42 -0
  27. package/dist/options.js.map +1 -0
  28. package/dist/plugin.d.ts +4 -0
  29. package/dist/plugin.d.ts.map +1 -0
  30. package/dist/plugin.js +83 -0
  31. package/dist/plugin.js.map +1 -0
  32. package/dist/tools/find-anti-pattern.d.ts +9 -0
  33. package/dist/tools/find-anti-pattern.d.ts.map +1 -0
  34. package/dist/tools/find-anti-pattern.js +37 -0
  35. package/dist/tools/find-anti-pattern.js.map +1 -0
  36. package/dist/tools/get-contract.d.ts +4 -0
  37. package/dist/tools/get-contract.d.ts.map +1 -0
  38. package/dist/tools/get-contract.js +19 -0
  39. package/dist/tools/get-contract.js.map +1 -0
  40. package/dist/tools/get-tokens.d.ts +4 -0
  41. package/dist/tools/get-tokens.d.ts.map +1 -0
  42. package/dist/tools/get-tokens.js +19 -0
  43. package/dist/tools/get-tokens.js.map +1 -0
  44. package/dist/tools/get-variants.d.ts +4 -0
  45. package/dist/tools/get-variants.d.ts.map +1 -0
  46. package/dist/tools/get-variants.js +19 -0
  47. package/dist/tools/get-variants.js.map +1 -0
  48. package/dist/tools/index.d.ts +8 -0
  49. package/dist/tools/index.d.ts.map +1 -0
  50. package/dist/tools/index.js +8 -0
  51. package/dist/tools/index.js.map +1 -0
  52. package/dist/tools/list-components.d.ts +4 -0
  53. package/dist/tools/list-components.d.ts.map +1 -0
  54. package/dist/tools/list-components.js +25 -0
  55. package/dist/tools/list-components.js.map +1 -0
  56. package/dist/tools/suggest-for-intent.d.ts +12 -0
  57. package/dist/tools/suggest-for-intent.d.ts.map +1 -0
  58. package/dist/tools/suggest-for-intent.js +86 -0
  59. package/dist/tools/suggest-for-intent.js.map +1 -0
  60. package/dist/tools/validate-composition.d.ts +9 -0
  61. package/dist/tools/validate-composition.d.ts.map +1 -0
  62. package/dist/tools/validate-composition.js +37 -0
  63. package/dist/tools/validate-composition.js.map +1 -0
  64. package/dist/validation/composition.d.ts +38 -0
  65. package/dist/validation/composition.d.ts.map +1 -0
  66. package/dist/validation/composition.js +135 -0
  67. package/dist/validation/composition.js.map +1 -0
  68. package/package.json +62 -7
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Validates a proposed page layout against the design system's composition
3
+ * rules: forbiddenAdjacent, maxPerPage, requiredSiblings, unknown components,
4
+ * unknown variants. Errors block; warnings advise.
5
+ */
6
+ export function validateComposition(input, manifest) {
7
+ const issues = [];
8
+ const counts = new Map();
9
+ for (let i = 0; i < input.blocks.length; i++) {
10
+ const block = input.blocks[i];
11
+ if (!block)
12
+ continue;
13
+ counts.set(block.type, (counts.get(block.type) ?? 0) + 1);
14
+ const contract = manifest.getComponent(block.type);
15
+ if (!contract) {
16
+ issues.push({
17
+ severity: 'error',
18
+ rule: 'unknown-component',
19
+ message: `Unknown component "${block.type}". Not present in the design system.`,
20
+ blockIndex: i,
21
+ });
22
+ continue;
23
+ }
24
+ if (block.variant && contract.content.variants) {
25
+ const has = contract.content.variants.some((v) => v.name === block.variant);
26
+ if (!has) {
27
+ issues.push({
28
+ severity: 'error',
29
+ rule: 'unknown-variant',
30
+ message: `Component "${block.type}" does not have variant "${block.variant}"`,
31
+ blockIndex: i,
32
+ });
33
+ }
34
+ }
35
+ const prev = i > 0 ? input.blocks[i - 1] : undefined;
36
+ const next = i < input.blocks.length - 1 ? input.blocks[i + 1] : undefined;
37
+ for (const forbidden of contract.composition.forbiddenAdjacent) {
38
+ if (prev?.type === forbidden) {
39
+ issues.push({
40
+ severity: 'error',
41
+ rule: 'forbidden-adjacent',
42
+ message: `"${block.type}" cannot appear directly after "${forbidden}"`,
43
+ blockIndex: i,
44
+ });
45
+ }
46
+ if (next?.type === forbidden) {
47
+ issues.push({
48
+ severity: 'error',
49
+ rule: 'forbidden-adjacent',
50
+ message: `"${block.type}" cannot appear directly before "${forbidden}"`,
51
+ blockIndex: i,
52
+ });
53
+ }
54
+ }
55
+ }
56
+ for (const [type, count] of counts) {
57
+ const contract = manifest.getComponent(type);
58
+ if (!contract)
59
+ continue;
60
+ const max = contract.composition.maxPerPage;
61
+ if (max !== null && count > max) {
62
+ issues.push({
63
+ severity: 'error',
64
+ rule: 'max-per-page',
65
+ message: `Component "${type}" appears ${count} times but the maximum allowed is ${max}`,
66
+ });
67
+ }
68
+ for (const required of contract.composition.requiredSiblings) {
69
+ if (!counts.has(required)) {
70
+ issues.push({
71
+ severity: 'warning',
72
+ rule: 'required-sibling-missing',
73
+ message: `Component "${type}" expects a sibling "${required}" but none is present`,
74
+ });
75
+ }
76
+ }
77
+ }
78
+ return { valid: issues.every((issue) => issue.severity !== 'error'), issues };
79
+ }
80
+ /**
81
+ * Surfaces structural anti-patterns inferred from each component's
82
+ * `antiExamples` plus position-aware heuristics. The current rule set is
83
+ * intentionally small and explicit; new rules should be added with care
84
+ * since false positives are worse than missed detections here.
85
+ */
86
+ export function findAntiPatterns(input, manifest) {
87
+ const matches = [];
88
+ const counts = new Map();
89
+ for (const block of input.blocks) {
90
+ counts.set(block.type, (counts.get(block.type) ?? 0) + 1);
91
+ }
92
+ for (let i = 0; i < input.blocks.length; i++) {
93
+ const block = input.blocks[i];
94
+ if (!block)
95
+ continue;
96
+ const contract = manifest.getComponent(block.type);
97
+ if (!contract)
98
+ continue;
99
+ const isLast = i === input.blocks.length - 1;
100
+ for (const anti of contract.antiExamples) {
101
+ const labelLower = anti.label.toLowerCase();
102
+ const isMultiplePattern = labelLower.includes('multiple') || labelLower.includes('two') || labelLower.includes('stacked');
103
+ if (isMultiplePattern && (counts.get(block.type) ?? 0) > 1) {
104
+ matches.push({
105
+ pattern: anti.label,
106
+ why: anti.why,
107
+ useInstead: anti.useInstead,
108
+ blockIndex: i,
109
+ });
110
+ continue;
111
+ }
112
+ const isEndOfPagePattern = labelLower.includes('end of') ||
113
+ labelLower.includes('bottom') ||
114
+ labelLower.includes('closer');
115
+ if (isEndOfPagePattern && isLast && contract.composition.placement.includes('page')) {
116
+ matches.push({
117
+ pattern: anti.label,
118
+ why: anti.why,
119
+ useInstead: anti.useInstead,
120
+ blockIndex: i,
121
+ });
122
+ }
123
+ }
124
+ }
125
+ // De-duplicate (same blockIndex + pattern can fire twice if both branches match)
126
+ const seen = new Set();
127
+ return matches.filter((m) => {
128
+ const key = `${m.blockIndex}:${m.pattern}`;
129
+ if (seen.has(key))
130
+ return false;
131
+ seen.add(key);
132
+ return true;
133
+ });
134
+ }
135
+ //# sourceMappingURL=composition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composition.js","sourceRoot":"","sources":["../../src/validation/composition.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,10 +1,65 @@
1
1
  {
2
2
  "name": "@forumone/throughline-components",
3
- "version": "0.0.1",
4
- "description": "OIDC trusted publishing setup package for @forumone/throughline-components",
3
+ "version": "0.2.0",
4
+ "description": "MCP server that exposes a design system manifest as conversational primitives for Throughline.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "CHANGELOG.md"
18
+ ],
5
19
  "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
9
- ]
10
- }
20
+ "throughline",
21
+ "design-system",
22
+ "mcp",
23
+ "payload"
24
+ ],
25
+ "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/forumone/throughline.git",
29
+ "directory": "packages/components"
30
+ },
31
+ "homepage": "https://github.com/forumone/throughline/tree/main/packages/components#readme",
32
+ "bugs": {
33
+ "url": "https://github.com/forumone/throughline/issues"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "peerDependencies": {
39
+ "payload": "^3.0.0"
40
+ },
41
+ "dependencies": {
42
+ "zod": "^3.23.0",
43
+ "@forumone/throughline-core": "0.2.0",
44
+ "@forumone/throughline-design-contract": "0.2.0",
45
+ "@forumone/throughline-plugin-contract": "0.0.0"
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^20.17.0",
49
+ "eslint": "^9.15.0",
50
+ "payload": "^3.83.0",
51
+ "typescript": "^5.6.0",
52
+ "vitest": "^2.1.0",
53
+ "@forumone/throughline-eslint-config": "0.0.0",
54
+ "@forumone/throughline-reference-ds": "0.2.0",
55
+ "@forumone/throughline-tsconfig": "0.0.0"
56
+ },
57
+ "scripts": {
58
+ "build": "tsc -b",
59
+ "dev": "tsc -b -w",
60
+ "clean": "rm -rf dist .turbo *.tsbuildinfo",
61
+ "typecheck": "tsc --noEmit",
62
+ "lint": "eslint src",
63
+ "test": "vitest run"
64
+ }
65
+ }