@suss/contract-storybook 0.30.0 → 0.31.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/dist/index.cjs CHANGED
@@ -58,7 +58,7 @@ function generateSummariesFromStories(filePaths, options = {}) {
58
58
  for (const sf of project.getSourceFiles()) {
59
59
  const absPath = sf.getFilePath();
60
60
  const relPath = import_node_path.default.relative(projectRoot, absPath);
61
- const meta = extractMeta(sf);
61
+ const meta = extractMeta(sf, resolution);
62
62
  if (meta === null) {
63
63
  continue;
64
64
  }
@@ -69,72 +69,22 @@ function generateSummariesFromStories(filePaths, options = {}) {
69
69
  }
70
70
  return summaries;
71
71
  }
72
- function extractMeta(sf) {
73
- const defaultExport = sf.getDefaultExportSymbol();
74
- if (defaultExport === void 0) {
75
- return null;
76
- }
77
- for (const decl of defaultExport.getDeclarations()) {
78
- const objLit = findMetaObjectLiteral(decl);
79
- if (objLit === null) {
80
- continue;
81
- }
82
- const componentProp = objLit.getProperty("component");
83
- if (componentProp === void 0) {
84
- continue;
85
- }
86
- if (!componentProp.isKind(import_ts_morph.SyntaxKind.PropertyAssignment)) {
72
+ function extractMeta(sf, resolution) {
73
+ for (const exported of resolution.exportsOf(sf).get("default") ?? []) {
74
+ const meta = objectBehind(exported, resolution);
75
+ if (meta === null) {
87
76
  continue;
88
77
  }
89
- const initializer = componentProp.getInitializer();
90
- if (initializer === void 0) {
91
- continue;
78
+ const component = (0, import_adapter_typescript.propertyOf)(meta, "component", resolution);
79
+ if (component !== null) {
80
+ return { componentName: component.getText() };
92
81
  }
93
- return { componentName: initializer.getText() };
94
- }
95
- return null;
96
- }
97
- function findMetaObjectLiteral(node) {
98
- if (node.isKind(import_ts_morph.SyntaxKind.ExportAssignment)) {
99
- return unwrapToObjectLiteral(node.getExpression());
100
- }
101
- if (node.isKind(import_ts_morph.SyntaxKind.VariableDeclaration)) {
102
- const init = node.getInitializer();
103
- return init === void 0 ? null : unwrapToObjectLiteral(init);
104
82
  }
105
83
  return null;
106
84
  }
107
- function unwrapToObjectLiteral(node) {
108
- if (node.isKind(import_ts_morph.SyntaxKind.ObjectLiteralExpression)) {
109
- return node;
110
- }
111
- if (node.isKind(import_ts_morph.SyntaxKind.SatisfiesExpression)) {
112
- return unwrapToObjectLiteral(node.getExpression());
113
- }
114
- if (node.isKind(import_ts_morph.SyntaxKind.ParenthesizedExpression)) {
115
- return unwrapToObjectLiteral(node.getExpression());
116
- }
117
- if (node.isKind(import_ts_morph.SyntaxKind.AsExpression)) {
118
- return unwrapToObjectLiteral(node.getExpression());
119
- }
120
- if (node.isKind(import_ts_morph.SyntaxKind.Identifier)) {
121
- const sym = node.getSymbol();
122
- if (sym === void 0) {
123
- return null;
124
- }
125
- for (const d of sym.getDeclarations()) {
126
- if (d.isKind(import_ts_morph.SyntaxKind.VariableDeclaration)) {
127
- const init = d.getInitializer();
128
- if (init !== void 0) {
129
- const unwrapped = unwrapToObjectLiteral(init);
130
- if (unwrapped !== null) {
131
- return unwrapped;
132
- }
133
- }
134
- }
135
- }
136
- }
137
- return null;
85
+ function objectBehind(value, resolution) {
86
+ const resolved = resolution.resolveObject(value);
87
+ return resolved !== null && import_ts_morph.Node.isObjectLiteralExpression(resolved) ? resolved : null;
138
88
  }
139
89
  function extractStories(sf, resolution) {
140
90
  const results = [];
@@ -143,43 +93,36 @@ function extractStories(sf, resolution) {
143
93
  continue;
144
94
  }
145
95
  for (const decl of decls) {
146
- if (!decl.isKind(import_ts_morph.SyntaxKind.VariableDeclaration)) {
147
- continue;
148
- }
149
- const init = decl.getInitializer();
150
- if (init === void 0) {
151
- continue;
152
- }
153
- const objLit = unwrapToObjectLiteral(init);
154
- if (objLit === null) {
96
+ const story = objectBehind(decl, resolution);
97
+ if (story === null) {
155
98
  continue;
156
99
  }
157
- const argsProp = objLit.getProperty("args");
158
- const args = {};
159
- if (argsProp?.isKind(import_ts_morph.SyntaxKind.PropertyAssignment)) {
160
- const argsInit = argsProp.getInitializer();
161
- if (argsInit?.isKind(import_ts_morph.SyntaxKind.ObjectLiteralExpression)) {
162
- for (const prop of argsInit.getProperties()) {
163
- if (prop.isKind(import_ts_morph.SyntaxKind.PropertyAssignment)) {
164
- const value = prop.getInitializer();
165
- if (value !== void 0) {
166
- args[prop.getName()] = value.getText();
167
- }
168
- } else if (prop.isKind(import_ts_morph.SyntaxKind.ShorthandPropertyAssignment)) {
169
- args[prop.getName()] = prop.getName();
170
- }
171
- }
172
- }
173
- }
174
100
  results.push({
175
101
  name,
176
- args,
102
+ args: storyArgs(story, resolution),
177
103
  line: decl.getStartLineNumber()
178
104
  });
179
105
  }
180
106
  }
181
107
  return results;
182
108
  }
109
+ function storyArgs(story, resolution) {
110
+ const args = {};
111
+ const written = (0, import_adapter_typescript.propertyOf)(story, "args", resolution);
112
+ const object = written === null ? null : (0, import_adapter_typescript.objectLiteralOf)(written, resolution);
113
+ if (object === null) {
114
+ return args;
115
+ }
116
+ for (const property of (0, import_adapter_typescript.propertiesOf)(object, resolution)) {
117
+ const name = (0, import_adapter_typescript.propertyNameOf)(property);
118
+ const value = (0, import_adapter_typescript.propertyValueOf)(property);
119
+ if (name === null || value === null) {
120
+ continue;
121
+ }
122
+ args[name] = (0, import_adapter_typescript.stringValueOf)(value, resolution) ?? value.getText();
123
+ }
124
+ return args;
125
+ }
183
126
  function buildSummary(story, meta, filePath) {
184
127
  const inputs = Object.entries(story.args).map(([name, value]) => ({
185
128
  type: "parameter",
package/dist/index.js CHANGED
@@ -1,12 +1,18 @@
1
1
  // src/index.ts
2
2
  import path from "path";
3
3
  import {
4
- Project,
5
- SyntaxKind
4
+ Node as N,
5
+ Project
6
6
  } from "ts-morph";
7
7
  import {
8
8
  exportedDeclarationsOf,
9
- ResolutionStore
9
+ objectLiteralOf,
10
+ propertiesOf,
11
+ propertyNameOf,
12
+ propertyOf,
13
+ propertyValueOf,
14
+ ResolutionStore,
15
+ stringValueOf
10
16
  } from "@suss/adapter-typescript";
11
17
  import { functionCallBinding } from "@suss/behavioral-ir";
12
18
  function generateSummariesFromStories(filePaths, options = {}) {
@@ -30,7 +36,7 @@ function generateSummariesFromStories(filePaths, options = {}) {
30
36
  for (const sf of project.getSourceFiles()) {
31
37
  const absPath = sf.getFilePath();
32
38
  const relPath = path.relative(projectRoot, absPath);
33
- const meta = extractMeta(sf);
39
+ const meta = extractMeta(sf, resolution);
34
40
  if (meta === null) {
35
41
  continue;
36
42
  }
@@ -41,72 +47,22 @@ function generateSummariesFromStories(filePaths, options = {}) {
41
47
  }
42
48
  return summaries;
43
49
  }
44
- function extractMeta(sf) {
45
- const defaultExport = sf.getDefaultExportSymbol();
46
- if (defaultExport === void 0) {
47
- return null;
48
- }
49
- for (const decl of defaultExport.getDeclarations()) {
50
- const objLit = findMetaObjectLiteral(decl);
51
- if (objLit === null) {
52
- continue;
53
- }
54
- const componentProp = objLit.getProperty("component");
55
- if (componentProp === void 0) {
56
- continue;
57
- }
58
- if (!componentProp.isKind(SyntaxKind.PropertyAssignment)) {
50
+ function extractMeta(sf, resolution) {
51
+ for (const exported of resolution.exportsOf(sf).get("default") ?? []) {
52
+ const meta = objectBehind(exported, resolution);
53
+ if (meta === null) {
59
54
  continue;
60
55
  }
61
- const initializer = componentProp.getInitializer();
62
- if (initializer === void 0) {
63
- continue;
56
+ const component = propertyOf(meta, "component", resolution);
57
+ if (component !== null) {
58
+ return { componentName: component.getText() };
64
59
  }
65
- return { componentName: initializer.getText() };
66
- }
67
- return null;
68
- }
69
- function findMetaObjectLiteral(node) {
70
- if (node.isKind(SyntaxKind.ExportAssignment)) {
71
- return unwrapToObjectLiteral(node.getExpression());
72
- }
73
- if (node.isKind(SyntaxKind.VariableDeclaration)) {
74
- const init = node.getInitializer();
75
- return init === void 0 ? null : unwrapToObjectLiteral(init);
76
60
  }
77
61
  return null;
78
62
  }
79
- function unwrapToObjectLiteral(node) {
80
- if (node.isKind(SyntaxKind.ObjectLiteralExpression)) {
81
- return node;
82
- }
83
- if (node.isKind(SyntaxKind.SatisfiesExpression)) {
84
- return unwrapToObjectLiteral(node.getExpression());
85
- }
86
- if (node.isKind(SyntaxKind.ParenthesizedExpression)) {
87
- return unwrapToObjectLiteral(node.getExpression());
88
- }
89
- if (node.isKind(SyntaxKind.AsExpression)) {
90
- return unwrapToObjectLiteral(node.getExpression());
91
- }
92
- if (node.isKind(SyntaxKind.Identifier)) {
93
- const sym = node.getSymbol();
94
- if (sym === void 0) {
95
- return null;
96
- }
97
- for (const d of sym.getDeclarations()) {
98
- if (d.isKind(SyntaxKind.VariableDeclaration)) {
99
- const init = d.getInitializer();
100
- if (init !== void 0) {
101
- const unwrapped = unwrapToObjectLiteral(init);
102
- if (unwrapped !== null) {
103
- return unwrapped;
104
- }
105
- }
106
- }
107
- }
108
- }
109
- return null;
63
+ function objectBehind(value, resolution) {
64
+ const resolved = resolution.resolveObject(value);
65
+ return resolved !== null && N.isObjectLiteralExpression(resolved) ? resolved : null;
110
66
  }
111
67
  function extractStories(sf, resolution) {
112
68
  const results = [];
@@ -115,43 +71,36 @@ function extractStories(sf, resolution) {
115
71
  continue;
116
72
  }
117
73
  for (const decl of decls) {
118
- if (!decl.isKind(SyntaxKind.VariableDeclaration)) {
119
- continue;
120
- }
121
- const init = decl.getInitializer();
122
- if (init === void 0) {
123
- continue;
124
- }
125
- const objLit = unwrapToObjectLiteral(init);
126
- if (objLit === null) {
74
+ const story = objectBehind(decl, resolution);
75
+ if (story === null) {
127
76
  continue;
128
77
  }
129
- const argsProp = objLit.getProperty("args");
130
- const args = {};
131
- if (argsProp?.isKind(SyntaxKind.PropertyAssignment)) {
132
- const argsInit = argsProp.getInitializer();
133
- if (argsInit?.isKind(SyntaxKind.ObjectLiteralExpression)) {
134
- for (const prop of argsInit.getProperties()) {
135
- if (prop.isKind(SyntaxKind.PropertyAssignment)) {
136
- const value = prop.getInitializer();
137
- if (value !== void 0) {
138
- args[prop.getName()] = value.getText();
139
- }
140
- } else if (prop.isKind(SyntaxKind.ShorthandPropertyAssignment)) {
141
- args[prop.getName()] = prop.getName();
142
- }
143
- }
144
- }
145
- }
146
78
  results.push({
147
79
  name,
148
- args,
80
+ args: storyArgs(story, resolution),
149
81
  line: decl.getStartLineNumber()
150
82
  });
151
83
  }
152
84
  }
153
85
  return results;
154
86
  }
87
+ function storyArgs(story, resolution) {
88
+ const args = {};
89
+ const written = propertyOf(story, "args", resolution);
90
+ const object = written === null ? null : objectLiteralOf(written, resolution);
91
+ if (object === null) {
92
+ return args;
93
+ }
94
+ for (const property of propertiesOf(object, resolution)) {
95
+ const name = propertyNameOf(property);
96
+ const value = propertyValueOf(property);
97
+ if (name === null || value === null) {
98
+ continue;
99
+ }
100
+ args[name] = stringValueOf(value, resolution) ?? value.getText();
101
+ }
102
+ return args;
103
+ }
155
104
  function buildSummary(story, meta, filePath) {
156
105
  const inputs = Object.entries(story.args).map(([name, value]) => ({
157
106
  type: "parameter",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suss/contract-storybook",
3
- "version": "0.30.0",
3
+ "version": "0.31.0",
4
4
  "type": "module",
5
5
  "description": "Turn Storybook CSF stories into a suss contract and check the props they pass against the React components that receive them.",
6
6
  "keywords": [
@@ -47,8 +47,8 @@
47
47
  "typecheck": "tsc --noEmit"
48
48
  },
49
49
  "dependencies": {
50
- "@suss/adapter-typescript": "0.30.0",
51
- "@suss/behavioral-ir": "0.30.0"
50
+ "@suss/adapter-typescript": "0.31.0",
51
+ "@suss/behavioral-ir": "0.31.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "tsup": "*",