@contentful/experience-design-system-extraction 2.33.1-dev-build-1b6f259.0 → 2.33.1-dev-build-db909d4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-extraction",
3
- "version": "2.33.1-dev-build-1b6f259.0",
3
+ "version": "2.33.1-dev-build-db909d4.0",
4
4
  "description": "Component extraction engine for the Contentful Experience Design System SDK",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,9 +1,7 @@
1
1
  import { basename } from 'node:path';
2
+ import { readFile } from 'node:fs/promises';
2
3
  import os from 'node:os';
3
4
  import { Project, Node } from 'ts-morph';
4
- import { createSortedExtractionResult, runFileExtractionWorkers } from './file-extraction-workers.js';
5
- import { resolveTypeProperty } from './resolve-type-property.js';
6
- import { getSourceLineMetadata } from './source-line-metadata.js';
7
5
  function extractAllowedValues(typeText) {
8
6
  // Check if the type is a union of string literals like 'a' | 'b' | 'c'
9
7
  const parts = typeText.split('|').map((p) => p.trim());
@@ -32,8 +30,8 @@ function extractBindingPropName(element) {
32
30
  return null;
33
31
  return element.getPropertyNameNode()?.getText() ?? element.getNameNode().getText();
34
32
  }
35
- function createAstroFrontmatterProject() {
36
- return new Project({
33
+ function extractFallbackPropsFromFrontmatter(frontmatter) {
34
+ const project = new Project({
37
35
  compilerOptions: {
38
36
  strict: false,
39
37
  target: 99,
@@ -43,33 +41,27 @@ function createAstroFrontmatterProject() {
43
41
  useInMemoryFileSystem: true,
44
42
  skipAddingFilesFromTsConfig: true,
45
43
  });
46
- }
47
- function forEachAstroPropsBinding(frontmatter, visit) {
48
- const sf = createAstroFrontmatterProject().createSourceFile('__frontmatter__.ts', frontmatter);
44
+ const sf = project.createSourceFile('__frontmatter__.ts', frontmatter);
45
+ const props = new Map();
49
46
  sf.forEachDescendant((node) => {
50
47
  if (!Node.isVariableDeclaration(node))
51
48
  return;
52
49
  const initializer = node.getInitializer();
53
- if (!initializer || !usesAstroProps(initializer))
50
+ if (!usesAstroProps(initializer))
54
51
  return;
55
52
  const nameNode = node.getNameNode();
56
53
  if (!Node.isObjectBindingPattern(nameNode))
57
54
  return;
58
- for (const element of nameNode.getElements())
59
- visit(element);
60
- });
61
- }
62
- function extractFallbackPropsFromFrontmatter(frontmatter) {
63
- const props = new Map();
64
- forEachAstroPropsBinding(frontmatter, (element) => {
65
- const propName = extractBindingPropName(element);
66
- if (!propName)
67
- return;
68
- props.set(propName, {
69
- name: propName,
70
- type: 'any',
71
- required: !element.getInitializer(),
72
- });
55
+ for (const element of nameNode.getElements()) {
56
+ const propName = extractBindingPropName(element);
57
+ if (!propName)
58
+ continue;
59
+ props.set(propName, {
60
+ name: propName,
61
+ type: 'any',
62
+ required: !element.getInitializer(),
63
+ });
64
+ }
73
65
  });
74
66
  return [...props.values()].sort((a, b) => a.name.localeCompare(b.name));
75
67
  }
@@ -90,7 +82,17 @@ function mergeProps(...propGroups) {
90
82
  return [...merged.values()].sort((a, b) => a.name.localeCompare(b.name));
91
83
  }
92
84
  function extractPropsFromFrontmatter(frontmatter) {
93
- const sf = createAstroFrontmatterProject().createSourceFile('__frontmatter__.ts', frontmatter);
85
+ const project = new Project({
86
+ compilerOptions: {
87
+ strict: false,
88
+ target: 99, // ESNext
89
+ module: 99, // ESNext
90
+ allowJs: true,
91
+ },
92
+ useInMemoryFileSystem: true,
93
+ skipAddingFilesFromTsConfig: true,
94
+ });
95
+ const sf = project.createSourceFile('__frontmatter__.ts', frontmatter);
94
96
  const props = [];
95
97
  // Find `interface Props` or `type Props = ...`
96
98
  const propsInterface = sf.getInterface('Props');
@@ -114,17 +116,25 @@ function extractPropsFromFrontmatter(frontmatter) {
114
116
  else if (propsTypeAlias) {
115
117
  const type = propsTypeAlias.getType();
116
118
  for (const property of type.getProperties()) {
117
- const resolved = resolveTypeProperty(property);
118
- if (!resolved)
119
+ const name = property.getName();
120
+ const decl = property.getValueDeclaration() ?? property.getDeclarations()[0];
121
+ if (!decl)
119
122
  continue;
120
- const { name, declaration: decl, typeText, required } = resolved;
123
+ const propType = property.getTypeAtLocation(decl);
124
+ const typeText = propType.getText(decl);
125
+ const required = !property.isOptional();
121
126
  const allowedValues = extractAllowedValues(typeText);
122
127
  props.push({
123
128
  name,
124
129
  type: typeText,
125
130
  required,
126
131
  ...(allowedValues && { allowedValues }),
127
- ...getSourceLineMetadata(decl),
132
+ ...(typeof decl.getStartLineNumber === 'function'
133
+ ? {
134
+ sourceStartLine: decl.getStartLineNumber(),
135
+ sourceEndLine: decl.getEndLineNumber(),
136
+ }
137
+ : {}),
128
138
  });
129
139
  }
130
140
  }
@@ -132,15 +142,38 @@ function extractPropsFromFrontmatter(frontmatter) {
132
142
  }
133
143
  function extractDefaultsFromFrontmatter(frontmatter) {
134
144
  const defaults = new Map();
135
- forEachAstroPropsBinding(frontmatter, (element) => {
136
- const propName = extractBindingPropName(element);
137
- if (!propName)
145
+ const project = new Project({
146
+ compilerOptions: {
147
+ strict: false,
148
+ target: 99,
149
+ module: 99,
150
+ allowJs: true,
151
+ },
152
+ useInMemoryFileSystem: true,
153
+ skipAddingFilesFromTsConfig: true,
154
+ });
155
+ const sf = project.createSourceFile('__frontmatter__.ts', frontmatter);
156
+ sf.forEachDescendant((node) => {
157
+ if (!Node.isVariableDeclaration(node))
158
+ return;
159
+ const initializer = node.getInitializer();
160
+ if (!initializer)
138
161
  return;
139
- const elementInitializer = element.getInitializer();
140
- if (!elementInitializer)
162
+ if (!usesAstroProps(initializer))
141
163
  return;
142
- const value = elementInitializer.getText().replace(/^['"]|['"]$/g, '');
143
- defaults.set(propName, value);
164
+ const nameNode = node.getNameNode();
165
+ if (!Node.isObjectBindingPattern(nameNode))
166
+ return;
167
+ for (const element of nameNode.getElements()) {
168
+ const propName = extractBindingPropName(element);
169
+ if (!propName)
170
+ continue;
171
+ const elementInitializer = element.getInitializer();
172
+ if (!elementInitializer)
173
+ continue;
174
+ const value = elementInitializer.getText().replace(/^['"]|['"]$/g, '');
175
+ defaults.set(propName, value);
176
+ }
144
177
  });
145
178
  return defaults;
146
179
  }
@@ -220,8 +253,37 @@ function extractFromAstroFile(filePath, source) {
220
253
  const ASTRO_EXTRACT_CONCURRENCY = Number(process.env['EDS_EXTRACT_CONCURRENCY'] ?? 0) || os.cpus().length;
221
254
  export async function extractAstroComponents(filePaths, onProgress) {
222
255
  const astroFiles = filePaths.filter((f) => f.endsWith('.astro'));
223
- const { items: components, warnings } = await runFileExtractionWorkers(astroFiles, ASTRO_EXTRACT_CONCURRENCY, async (filePath, source) => ({
224
- item: extractFromAstroFile(filePath, source),
225
- }), (filePath, error) => `Failed to extract from ${filePath}: ${error instanceof Error ? error.message : String(error)}`, onProgress);
226
- return createSortedExtractionResult(components, warnings);
256
+ if (astroFiles.length === 0) {
257
+ return { components: [], warnings: [] };
258
+ }
259
+ const warnings = [];
260
+ const components = [];
261
+ let filesProcessed = 0;
262
+ let componentsFound = 0;
263
+ const queue = [...astroFiles];
264
+ async function worker() {
265
+ while (queue.length > 0) {
266
+ const filePath = queue.shift();
267
+ if (!filePath)
268
+ break;
269
+ try {
270
+ const source = await readFile(filePath, 'utf-8');
271
+ const component = extractFromAstroFile(filePath, source);
272
+ if (component) {
273
+ components.push(component);
274
+ componentsFound++;
275
+ }
276
+ }
277
+ catch (e) {
278
+ warnings.push(`Failed to extract from ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
279
+ }
280
+ filesProcessed++;
281
+ onProgress?.({ filesProcessed, componentsFound });
282
+ }
283
+ }
284
+ await Promise.all(Array.from({ length: Math.min(ASTRO_EXTRACT_CONCURRENCY, astroFiles.length) }, worker));
285
+ return {
286
+ components: components.sort((a, b) => a.name.localeCompare(b.name)),
287
+ warnings,
288
+ };
227
289
  }
@@ -1,5 +1,5 @@
1
1
  import type { RawComponentDefinition } from '../types.js';
2
- interface NonAuthorableResult {
2
+ export interface NonAuthorableResult {
3
3
  skip: boolean;
4
4
  reason?: string;
5
5
  }
@@ -14,4 +14,3 @@ interface NonAuthorableResult {
14
14
  * other repos.
15
15
  */
16
16
  export declare function isNonAuthorableComponent(component: RawComponentDefinition): NonAuthorableResult;
17
- export {};
@@ -1,7 +1,6 @@
1
1
  import type { ComponentExtractionResult, ExtractorOptions } from '../types.js';
2
- type ExtractProgress = {
2
+ export type ExtractProgress = {
3
3
  filesProcessed: number;
4
4
  componentsFound: number;
5
5
  };
6
6
  export declare function extractComponents(filePaths: string[], onProgress?: (progress: ExtractProgress) => void, opts?: ExtractorOptions): Promise<ComponentExtractionResult>;
7
- export {};