@living-architecture/riviere-extract-ts 0.1.2 → 0.1.4

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,3 +1,4 @@
1
+ import type { Project } from 'ts-morph';
1
2
  import type { ExtractionConfig, ComponentType } from '@living-architecture/riviere-extract-config';
2
3
  export interface DraftComponent {
3
4
  type: ComponentType;
@@ -8,5 +9,5 @@ export interface DraftComponent {
8
9
  };
9
10
  domain: string;
10
11
  }
11
- export declare function extractComponents(_sourceFilePaths: string[], _config: ExtractionConfig): DraftComponent[];
12
+ export declare function extractComponents(project: Project, sourceFilePaths: string[], config: ExtractionConfig): DraftComponent[];
12
13
  //# sourceMappingURL=extractor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../src/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAAE,aAAa,EAChC,MAAM,6CAA6C,CAAA;AAEpD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,aAAa,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,iBAAiB,CAC/B,gBAAgB,EAAE,MAAM,EAAE,EAC1B,OAAO,EAAE,gBAAgB,GACxB,cAAc,EAAE,CAElB"}
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../src/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,OAAO,EAER,MAAM,UAAU,CAAA;AAEjB,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EAGd,MAAM,6CAA6C,CAAA;AAGpD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,aAAa,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,MAAM,EAAE,MAAM,CAAA;CACf;AA4BD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,MAAM,EAAE,EACzB,MAAM,EAAE,gBAAgB,GACvB,cAAc,EAAE,CAElB"}
package/dist/extractor.js CHANGED
@@ -1,3 +1,130 @@
1
- export function extractComponents(_sourceFilePaths, _config) {
1
+ import { minimatch } from 'minimatch';
2
+ import { evaluatePredicate } from './predicates';
3
+ const COMPONENT_TYPES = [
4
+ 'api',
5
+ 'useCase',
6
+ 'domainOp',
7
+ 'event',
8
+ 'eventHandler',
9
+ 'ui',
10
+ ];
11
+ const FIND_TARGETS = ['classes', 'methods', 'functions'];
12
+ function hasProperty(obj, key) {
13
+ return key in obj;
14
+ }
15
+ function isDetectionRule(rule) {
16
+ /* istanbul ignore if -- @preserve: unreachable with typed ExtractionConfig; defensive guard */
17
+ if (typeof rule !== 'object' || rule === null) {
18
+ return false;
19
+ }
20
+ if (!hasProperty(rule, 'find') || !hasProperty(rule, 'where')) {
21
+ return false;
22
+ }
23
+ return typeof rule.find === 'string' && FIND_TARGETS.includes(rule.find);
24
+ }
25
+ export function extractComponents(project, sourceFilePaths, config) {
26
+ return sourceFilePaths.flatMap((filePath) => extractFromFile(project, filePath, config));
27
+ }
28
+ function extractFromFile(project, filePath, config) {
29
+ const sourceFile = project.getSourceFile(filePath);
30
+ if (sourceFile === undefined) {
31
+ return [];
32
+ }
33
+ const matchingModule = findMatchingModule(filePath, config.modules);
34
+ if (matchingModule === undefined) {
35
+ return [];
36
+ }
37
+ return extractFromModule(sourceFile, filePath, matchingModule);
38
+ }
39
+ function extractFromModule(sourceFile, filePath, module) {
40
+ return COMPONENT_TYPES.flatMap((componentType) => extractComponentType(sourceFile, filePath, module, componentType));
41
+ }
42
+ function extractComponentType(sourceFile, filePath, module, componentType) {
43
+ const rule = module[componentType];
44
+ if (!isDetectionRule(rule)) {
45
+ return [];
46
+ }
47
+ if (rule.find === 'classes') {
48
+ return extractClasses(sourceFile, filePath, module.name, componentType, rule);
49
+ }
50
+ if (rule.find === 'methods') {
51
+ return extractMethods(sourceFile, filePath, module.name, componentType, rule);
52
+ }
53
+ /* istanbul ignore else -- @preserve: false branch is unreachable; FindTarget is exhaustive */
54
+ if (rule.find === 'functions') {
55
+ return extractFunctions(sourceFile, filePath, module.name, componentType, rule);
56
+ }
57
+ /* istanbul ignore next -- @preserve: unreachable with valid FindTarget type; defensive fallback */
2
58
  return [];
3
59
  }
60
+ function extractClasses(sourceFile, filePath, domain, componentType, rule) {
61
+ return sourceFile
62
+ .getClasses()
63
+ .filter((c) => evaluatePredicate(c, rule.where))
64
+ .flatMap((c) => createClassComponent(c, filePath, domain, componentType));
65
+ }
66
+ function extractMethods(sourceFile, filePath, domain, componentType, rule) {
67
+ return sourceFile
68
+ .getClasses()
69
+ .flatMap((c) => c.getMethods())
70
+ .filter((m) => evaluatePredicate(m, rule.where))
71
+ .flatMap((m) => createMethodComponent(m, filePath, domain, componentType));
72
+ }
73
+ function extractFunctions(sourceFile, filePath, domain, componentType, rule) {
74
+ return sourceFile
75
+ .getFunctions()
76
+ .filter((f) => evaluatePredicate(f, rule.where))
77
+ .flatMap((f) => createFunctionComponent(f, filePath, domain, componentType));
78
+ }
79
+ function createClassComponent(classDecl, filePath, domain, componentType) {
80
+ const name = classDecl.getName();
81
+ if (name === undefined) {
82
+ return [];
83
+ }
84
+ return [
85
+ {
86
+ type: componentType,
87
+ name,
88
+ location: {
89
+ file: filePath,
90
+ line: classDecl.getStartLineNumber(),
91
+ },
92
+ domain,
93
+ },
94
+ ];
95
+ }
96
+ function createMethodComponent(method, filePath, domain, componentType) {
97
+ const name = method.getName();
98
+ return [
99
+ {
100
+ type: componentType,
101
+ name,
102
+ location: {
103
+ file: filePath,
104
+ line: method.getStartLineNumber(),
105
+ },
106
+ domain,
107
+ },
108
+ ];
109
+ }
110
+ function createFunctionComponent(func, filePath, domain, componentType) {
111
+ const name = func.getName();
112
+ if (name === undefined) {
113
+ return [];
114
+ }
115
+ return [
116
+ {
117
+ type: componentType,
118
+ name,
119
+ location: {
120
+ file: filePath,
121
+ line: func.getStartLineNumber(),
122
+ },
123
+ domain,
124
+ },
125
+ ];
126
+ }
127
+ function findMatchingModule(filePath, modules) {
128
+ const normalized = filePath.replaceAll(/\\+/g, '/');
129
+ return modules.find((m) => minimatch(normalized, m.path));
130
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@living-architecture/riviere-extract-ts",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -22,7 +22,8 @@
22
22
  "!**/*.tsbuildinfo"
23
23
  ],
24
24
  "dependencies": {
25
+ "minimatch": "^10.0.1",
25
26
  "ts-morph": "^24.0.0",
26
- "@living-architecture/riviere-extract-config": "0.1.6"
27
+ "@living-architecture/riviere-extract-config": "0.1.8"
27
28
  }
28
29
  }
@@ -1,3 +0,0 @@
1
- import type { ExtractionConfig } from '@living-architecture/riviere-extract-config';
2
- export declare function createMinimalConfig(): ExtractionConfig;
3
- //# sourceMappingURL=test-fixtures.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-fixtures.d.ts","sourceRoot":"","sources":["../src/test-fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6CAA6C,CAAA;AAEnF,wBAAgB,mBAAmB,IAAI,gBAAgB,CActD"}
@@ -1,15 +0,0 @@
1
- export function createMinimalConfig() {
2
- return {
3
- modules: [
4
- {
5
- path: '**/*.ts',
6
- api: { notUsed: true },
7
- useCase: { notUsed: true },
8
- domainOp: { notUsed: true },
9
- event: { notUsed: true },
10
- eventHandler: { notUsed: true },
11
- ui: { notUsed: true },
12
- },
13
- ],
14
- };
15
- }