@unrdf/project-engine 5.0.1 → 26.4.2
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/package.json +16 -15
- package/src/golden-structure.mjs +2 -2
- package/src/materialize-apply.mjs +2 -2
- package/README.md +0 -53
- package/src/api-contract-validator.mjs +0 -711
- package/src/auto-test-generator.mjs +0 -444
- package/src/autonomic-mapek.mjs +0 -511
- package/src/capabilities-manifest.mjs +0 -125
- package/src/code-complexity-js.mjs +0 -368
- package/src/dependency-graph.mjs +0 -276
- package/src/doc-drift-checker.mjs +0 -172
- package/src/doc-generator.mjs +0 -229
- package/src/domain-infer.mjs +0 -966
- package/src/drift-snapshot.mjs +0 -775
- package/src/file-roles.mjs +0 -94
- package/src/fs-scan.mjs +0 -305
- package/src/gap-finder.mjs +0 -376
- package/src/hotspot-analyzer.mjs +0 -412
- package/src/index.mjs +0 -151
- package/src/initialize.mjs +0 -957
- package/src/lens/project-structure.mjs +0 -74
- package/src/mapek-orchestration.mjs +0 -665
- package/src/materialize-plan.mjs +0 -422
- package/src/materialize.mjs +0 -137
- package/src/policy-derivation.mjs +0 -869
- package/src/project-config.mjs +0 -142
- package/src/project-diff.mjs +0 -28
- package/src/project-engine/build-utils.mjs +0 -237
- package/src/project-engine/code-analyzer.mjs +0 -248
- package/src/project-engine/doc-generator.mjs +0 -407
- package/src/project-engine/infrastructure.mjs +0 -213
- package/src/project-engine/metrics.mjs +0 -146
- package/src/project-model.mjs +0 -111
- package/src/project-report.mjs +0 -348
- package/src/refactoring-guide.mjs +0 -242
- package/src/stack-detect.mjs +0 -102
- package/src/stack-linter.mjs +0 -213
- package/src/template-infer.mjs +0 -674
- package/src/type-auditor.mjs +0 -609
package/src/file-roles.mjs
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file File role classification
|
|
3
|
-
* @module project-engine/file-roles
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { UnrdfDataFactory as DataFactory } from '@unrdf/core/rdf/n3-justified-only';
|
|
7
|
-
import { z } from 'zod';
|
|
8
|
-
|
|
9
|
-
const { namedNode, literal } = DataFactory;
|
|
10
|
-
|
|
11
|
-
const FileRolesOptionsSchema = z.object({
|
|
12
|
-
fsStore: z.custom(val => val && typeof val.getQuads === 'function', {
|
|
13
|
-
message: 'fsStore must be an RDF store with getQuads method',
|
|
14
|
-
}),
|
|
15
|
-
stackInfo: z
|
|
16
|
-
.object({
|
|
17
|
-
uiFramework: z.string().nullable(),
|
|
18
|
-
webFramework: z.string().nullable(),
|
|
19
|
-
testFramework: z.string().nullable(),
|
|
20
|
-
})
|
|
21
|
-
.optional(),
|
|
22
|
-
baseIri: z.string().default('http://example.org/unrdf/project#'),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const ROLE_PATTERNS = {
|
|
26
|
-
Component: [/\.(tsx?|jsx?)$/, /(Component|View)\.tsx?$/],
|
|
27
|
-
Page: [/^(pages|src\/pages|src\/app|app)\//, /page\.(tsx?|jsx?)$/],
|
|
28
|
-
Api: [/(api|server|route)\.(tsx?|js)$/, /^(api|server|routes)\//],
|
|
29
|
-
Hook: [/use[A-Z]\w+\.(tsx?|jsx?)$/, /^hooks?\//],
|
|
30
|
-
Service: [/(service|client|repository)\.(tsx?|js)$/, /^(services?|clients?)\//],
|
|
31
|
-
Schema: [/(schema|type|interface)\.(tsx?|js)$/, /(schema|types?|interfaces?)\.(tsx?|json)$/],
|
|
32
|
-
State: [/(store|state|reducer|context)\.(tsx?|js)$/, /^(store|state|redux)\//],
|
|
33
|
-
Test: [/\.(test|spec)\.(tsx?|jsx?)$/, /^(__tests__|test|tests|spec)\//],
|
|
34
|
-
Doc: [/\.(md|mdx)$/, /^(docs?|README)/],
|
|
35
|
-
Config: [/\.(json|yaml|yml|toml|conf)$/, /(package\.json|tsconfig|eslintrc|prettier)/],
|
|
36
|
-
Build: [/(build|webpack|rollup|esbuild|vite|next\.config)/, /^scripts\//],
|
|
37
|
-
Other: [],
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Classify files with semantic roles
|
|
42
|
-
*
|
|
43
|
-
* @param {Object} options
|
|
44
|
-
* @param {Store} options.fsStore - FS store with project model
|
|
45
|
-
* @param {Object} [options.stackInfo] - Stack information from detectStackFromFs
|
|
46
|
-
* @param {string} [options.baseIri] - Base IRI for roles
|
|
47
|
-
* @returns {Store} Store with role classifications
|
|
48
|
-
*/
|
|
49
|
-
export function classifyFiles(options) {
|
|
50
|
-
const validated = FileRolesOptionsSchema.parse(options);
|
|
51
|
-
const { fsStore, baseIri } = validated;
|
|
52
|
-
|
|
53
|
-
const store = fsStore;
|
|
54
|
-
let _roleCount = 0;
|
|
55
|
-
|
|
56
|
-
const fileQuads = store.getQuads(
|
|
57
|
-
null,
|
|
58
|
-
namedNode('http://example.org/unrdf/filesystem#relativePath'),
|
|
59
|
-
null
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
for (const quad of fileQuads) {
|
|
63
|
-
const filePath = quad.object.value;
|
|
64
|
-
const fileIri = quad.subject;
|
|
65
|
-
const role = classifyPath(filePath);
|
|
66
|
-
|
|
67
|
-
if (role && role !== 'Other') {
|
|
68
|
-
const roleIri = namedNode(`${baseIri}${role}`);
|
|
69
|
-
store.addQuad(fileIri, namedNode('http://example.org/unrdf/project#hasRole'), roleIri);
|
|
70
|
-
store.addQuad(
|
|
71
|
-
fileIri,
|
|
72
|
-
namedNode('http://example.org/unrdf/project#roleString'),
|
|
73
|
-
literal(role)
|
|
74
|
-
);
|
|
75
|
-
_roleCount++;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return store;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Classify a file path to determine its role
|
|
84
|
-
*
|
|
85
|
-
* @private
|
|
86
|
-
*/
|
|
87
|
-
function classifyPath(filePath) {
|
|
88
|
-
for (const [role, patterns] of Object.entries(ROLE_PATTERNS)) {
|
|
89
|
-
if (patterns.some(pattern => pattern.test(filePath))) {
|
|
90
|
-
return role;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return 'Other';
|
|
94
|
-
}
|
package/src/fs-scan.mjs
DELETED
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Filesystem scanner - walk directory tree and emit RDF graph
|
|
3
|
-
* @module project-engine/fs-scan
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { promises as fs } from 'fs';
|
|
7
|
-
import path from 'path';
|
|
8
|
-
import { UnrdfDataFactory as DataFactory } from '@unrdf/core/rdf/n3-justified-only';
|
|
9
|
-
import { createStore } from '@unrdf/oxigraph'; // TODO: Replace with Oxigraph Store
|
|
10
|
-
import { trace, SpanStatusCode } from '@opentelemetry/api';
|
|
11
|
-
import { z } from 'zod';
|
|
12
|
-
|
|
13
|
-
const tracer = trace.getTracer('unrdf/fs-scan');
|
|
14
|
-
const { namedNode, literal } = DataFactory;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Default ignore patterns for filesystem scan
|
|
18
|
-
*/
|
|
19
|
-
const DEFAULT_IGNORE_PATTERNS = [
|
|
20
|
-
'node_modules',
|
|
21
|
-
'.git',
|
|
22
|
-
'.gitignore',
|
|
23
|
-
'dist',
|
|
24
|
-
'build',
|
|
25
|
-
'.next',
|
|
26
|
-
'.turbo',
|
|
27
|
-
'coverage',
|
|
28
|
-
'.cache',
|
|
29
|
-
'.venv',
|
|
30
|
-
'env',
|
|
31
|
-
'*.swp',
|
|
32
|
-
'.DS_Store',
|
|
33
|
-
'.env.local',
|
|
34
|
-
'.env.*.local',
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
const ScanOptionsSchema = z.object({
|
|
38
|
-
root: z.string(),
|
|
39
|
-
ignorePatterns: z.array(z.string()).optional(),
|
|
40
|
-
baseIri: z.string().default('http://example.org/unrdf/fs#'),
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Scan a filesystem directory and create RDF graph with NFO + UNRDF FS ontology
|
|
45
|
-
*
|
|
46
|
-
* @param {Object} options
|
|
47
|
-
* @param {string} options.root - Directory to scan
|
|
48
|
-
* @param {string[]} [options.ignorePatterns] - Glob patterns to ignore
|
|
49
|
-
* @param {string} [options.baseIri] - Base IRI for resource identifiers
|
|
50
|
-
* @returns {Promise<{store: Store, summary: {fileCount: number, folderCount: number, ignoredCount: number, rootIri: string}}>}
|
|
51
|
-
*/
|
|
52
|
-
export async function scanFileSystemToStore(options) {
|
|
53
|
-
const validated = ScanOptionsSchema.parse(options);
|
|
54
|
-
const { root, baseIri } = validated;
|
|
55
|
-
const ignorePatterns = validated.ignorePatterns || DEFAULT_IGNORE_PATTERNS;
|
|
56
|
-
|
|
57
|
-
return tracer.startActiveSpan('fs.scan', async span => {
|
|
58
|
-
try {
|
|
59
|
-
span.setAttributes({
|
|
60
|
-
'fs.root': root,
|
|
61
|
-
'fs.ignore_count': ignorePatterns.length,
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
const store = createStore();
|
|
65
|
-
const stats = {
|
|
66
|
-
fileCount: 0,
|
|
67
|
-
folderCount: 0,
|
|
68
|
-
ignoredCount: 0,
|
|
69
|
-
rootIri: `${baseIri}root`,
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// Add root as ProjectRoot
|
|
73
|
-
const rootIri = namedNode(`${baseIri}root`);
|
|
74
|
-
store.addQuad(
|
|
75
|
-
rootIri,
|
|
76
|
-
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
|
|
77
|
-
namedNode('http://example.org/unrdf/filesystem#ProjectRoot')
|
|
78
|
-
);
|
|
79
|
-
store.addQuad(
|
|
80
|
-
rootIri,
|
|
81
|
-
namedNode('http://example.org/unrdf/filesystem#relativePath'),
|
|
82
|
-
literal('.')
|
|
83
|
-
);
|
|
84
|
-
store.addQuad(
|
|
85
|
-
rootIri,
|
|
86
|
-
namedNode('http://example.org/unrdf/filesystem#depth'),
|
|
87
|
-
literal(0, namedNode('http://www.w3.org/2001/XMLSchema#integer'))
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
// Recursive walk
|
|
91
|
-
await walkDirectory(root, '.', rootIri, store, ignorePatterns, baseIri, stats);
|
|
92
|
-
|
|
93
|
-
span.setAttributes({
|
|
94
|
-
'fs.file_count': stats.fileCount,
|
|
95
|
-
'fs.folder_count': stats.folderCount,
|
|
96
|
-
'fs.ignored_count': stats.ignoredCount,
|
|
97
|
-
});
|
|
98
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
99
|
-
|
|
100
|
-
return { store, summary: stats };
|
|
101
|
-
} catch (error) {
|
|
102
|
-
span.setStatus({
|
|
103
|
-
code: SpanStatusCode.ERROR,
|
|
104
|
-
message: error.message,
|
|
105
|
-
});
|
|
106
|
-
throw error;
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Recursively walk directory and add quads to store
|
|
113
|
-
*
|
|
114
|
-
* @private
|
|
115
|
-
*/
|
|
116
|
-
async function walkDirectory(
|
|
117
|
-
diskPath,
|
|
118
|
-
relativePath,
|
|
119
|
-
parentIri,
|
|
120
|
-
store,
|
|
121
|
-
ignorePatterns,
|
|
122
|
-
baseIri,
|
|
123
|
-
stats
|
|
124
|
-
) {
|
|
125
|
-
try {
|
|
126
|
-
const entries = await fs.readdir(diskPath, { withFileTypes: true });
|
|
127
|
-
|
|
128
|
-
for (const entry of entries) {
|
|
129
|
-
// Check ignore patterns
|
|
130
|
-
if (shouldIgnore(entry.name, ignorePatterns)) {
|
|
131
|
-
stats.ignoredCount++;
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const entryRelPath = relativePath === '.' ? entry.name : `${relativePath}/${entry.name}`;
|
|
136
|
-
const entryDiskPath = path.join(diskPath, entry.name);
|
|
137
|
-
const entryIri = namedNode(`${baseIri}${encodeURIComponent(entryRelPath)}`);
|
|
138
|
-
|
|
139
|
-
// Determine type
|
|
140
|
-
if (entry.isDirectory()) {
|
|
141
|
-
await handleDirectory(
|
|
142
|
-
entryDiskPath,
|
|
143
|
-
entryRelPath,
|
|
144
|
-
entryIri,
|
|
145
|
-
parentIri,
|
|
146
|
-
store,
|
|
147
|
-
ignorePatterns,
|
|
148
|
-
baseIri,
|
|
149
|
-
stats
|
|
150
|
-
);
|
|
151
|
-
} else if (entry.isFile()) {
|
|
152
|
-
await handleFile(entryDiskPath, entryRelPath, entryIri, parentIri, store, stats);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
} catch (error) {
|
|
156
|
-
// Skip unreadable directories
|
|
157
|
-
console.warn(`Skipped: ${diskPath} (${error.message})`);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Handle a directory entry
|
|
163
|
-
*
|
|
164
|
-
* @private
|
|
165
|
-
*/
|
|
166
|
-
async function handleDirectory(
|
|
167
|
-
diskPath,
|
|
168
|
-
relativePath,
|
|
169
|
-
dirIri,
|
|
170
|
-
parentIri,
|
|
171
|
-
store,
|
|
172
|
-
ignorePatterns,
|
|
173
|
-
baseIri,
|
|
174
|
-
stats
|
|
175
|
-
) {
|
|
176
|
-
const depth = (relativePath.match(/\//g) || []).length;
|
|
177
|
-
|
|
178
|
-
// Determine folder type
|
|
179
|
-
let folderType = 'http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Folder';
|
|
180
|
-
if (relativePath.includes('/src') || relativePath === 'src') {
|
|
181
|
-
folderType = 'http://example.org/unrdf/filesystem#SourceFolder';
|
|
182
|
-
} else if (
|
|
183
|
-
relativePath.includes('/dist') ||
|
|
184
|
-
relativePath === 'dist' ||
|
|
185
|
-
relativePath.includes('/.next') ||
|
|
186
|
-
relativePath === '.next' ||
|
|
187
|
-
relativePath.includes('/build') ||
|
|
188
|
-
relativePath === 'build'
|
|
189
|
-
) {
|
|
190
|
-
folderType = 'http://example.org/unrdf/filesystem#BuildFolder';
|
|
191
|
-
} else if (
|
|
192
|
-
relativePath.includes('/config') ||
|
|
193
|
-
relativePath === 'config' ||
|
|
194
|
-
relativePath.includes('/.') ||
|
|
195
|
-
relativePath.startsWith('.')
|
|
196
|
-
) {
|
|
197
|
-
folderType = 'http://example.org/unrdf/filesystem#ConfigFolder';
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Add folder quads
|
|
201
|
-
store.addQuad(
|
|
202
|
-
dirIri,
|
|
203
|
-
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
|
|
204
|
-
namedNode(folderType)
|
|
205
|
-
);
|
|
206
|
-
store.addQuad(
|
|
207
|
-
dirIri,
|
|
208
|
-
namedNode('http://example.org/unrdf/filesystem#relativePath'),
|
|
209
|
-
literal(relativePath)
|
|
210
|
-
);
|
|
211
|
-
store.addQuad(
|
|
212
|
-
dirIri,
|
|
213
|
-
namedNode('http://example.org/unrdf/filesystem#depth'),
|
|
214
|
-
literal(depth, namedNode('http://www.w3.org/2001/XMLSchema#integer'))
|
|
215
|
-
);
|
|
216
|
-
store.addQuad(
|
|
217
|
-
dirIri,
|
|
218
|
-
namedNode('http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#containedFolders'),
|
|
219
|
-
namedNode('http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#FileDataObject')
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
// Link to parent
|
|
223
|
-
store.addQuad(dirIri, namedNode('http://example.org/unrdf/filesystem#containedIn'), parentIri);
|
|
224
|
-
|
|
225
|
-
stats.folderCount++;
|
|
226
|
-
|
|
227
|
-
// Recurse
|
|
228
|
-
await walkDirectory(diskPath, relativePath, dirIri, store, ignorePatterns, baseIri, stats);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Handle a file entry
|
|
233
|
-
*
|
|
234
|
-
* @private
|
|
235
|
-
*/
|
|
236
|
-
async function handleFile(diskPath, relativePath, fileIri, parentIri, store, stats) {
|
|
237
|
-
try {
|
|
238
|
-
const stat = await fs.stat(diskPath);
|
|
239
|
-
const depth = (relativePath.match(/\//g) || []).length;
|
|
240
|
-
const ext = path.extname(relativePath).replace(/^\./, '');
|
|
241
|
-
const isHidden = path.basename(relativePath).startsWith('.');
|
|
242
|
-
|
|
243
|
-
store.addQuad(
|
|
244
|
-
fileIri,
|
|
245
|
-
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
|
|
246
|
-
namedNode('http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#FileDataObject')
|
|
247
|
-
);
|
|
248
|
-
store.addQuad(
|
|
249
|
-
fileIri,
|
|
250
|
-
namedNode('http://example.org/unrdf/filesystem#relativePath'),
|
|
251
|
-
literal(relativePath)
|
|
252
|
-
);
|
|
253
|
-
store.addQuad(
|
|
254
|
-
fileIri,
|
|
255
|
-
namedNode('http://example.org/unrdf/filesystem#depth'),
|
|
256
|
-
literal(depth, namedNode('http://www.w3.org/2001/XMLSchema#integer'))
|
|
257
|
-
);
|
|
258
|
-
store.addQuad(
|
|
259
|
-
fileIri,
|
|
260
|
-
namedNode('http://example.org/unrdf/filesystem#byteSize'),
|
|
261
|
-
literal(stat.size, namedNode('http://www.w3.org/2001/XMLSchema#integer'))
|
|
262
|
-
);
|
|
263
|
-
store.addQuad(
|
|
264
|
-
fileIri,
|
|
265
|
-
namedNode('http://example.org/unrdf/filesystem#lastModified'),
|
|
266
|
-
literal(stat.mtime.toISOString(), namedNode('http://www.w3.org/2001/XMLSchema#dateTime'))
|
|
267
|
-
);
|
|
268
|
-
store.addQuad(
|
|
269
|
-
fileIri,
|
|
270
|
-
namedNode('http://example.org/unrdf/filesystem#isHidden'),
|
|
271
|
-
literal(isHidden, namedNode('http://www.w3.org/2001/XMLSchema#boolean'))
|
|
272
|
-
);
|
|
273
|
-
|
|
274
|
-
if (ext) {
|
|
275
|
-
store.addQuad(
|
|
276
|
-
fileIri,
|
|
277
|
-
namedNode('http://example.org/unrdf/filesystem#extension'),
|
|
278
|
-
literal(ext)
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// Link to parent
|
|
283
|
-
store.addQuad(fileIri, namedNode('http://example.org/unrdf/filesystem#containedIn'), parentIri);
|
|
284
|
-
|
|
285
|
-
stats.fileCount++;
|
|
286
|
-
} catch (error) {
|
|
287
|
-
console.warn(`Skipped file: ${diskPath} (${error.message})`);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Check if path matches ignore patterns
|
|
293
|
-
*
|
|
294
|
-
* @private
|
|
295
|
-
*/
|
|
296
|
-
function shouldIgnore(name, patterns) {
|
|
297
|
-
return patterns.some(pattern => {
|
|
298
|
-
if (pattern.includes('*')) {
|
|
299
|
-
// Simple glob: *.swp, .*, etc.
|
|
300
|
-
const regex = new RegExp(`^${pattern.replace(/\*/g, '.*')}$`);
|
|
301
|
-
return regex.test(name);
|
|
302
|
-
}
|
|
303
|
-
return name === pattern;
|
|
304
|
-
});
|
|
305
|
-
}
|