@unrdf/project-engine 5.0.1 → 26.4.3

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 (39) hide show
  1. package/package.json +6 -5
  2. package/src/golden-structure.mjs +2 -2
  3. package/src/materialize-apply.mjs +2 -2
  4. package/README.md +0 -53
  5. package/src/api-contract-validator.mjs +0 -711
  6. package/src/auto-test-generator.mjs +0 -444
  7. package/src/autonomic-mapek.mjs +0 -511
  8. package/src/capabilities-manifest.mjs +0 -125
  9. package/src/code-complexity-js.mjs +0 -368
  10. package/src/dependency-graph.mjs +0 -276
  11. package/src/doc-drift-checker.mjs +0 -172
  12. package/src/doc-generator.mjs +0 -229
  13. package/src/domain-infer.mjs +0 -966
  14. package/src/drift-snapshot.mjs +0 -775
  15. package/src/file-roles.mjs +0 -94
  16. package/src/fs-scan.mjs +0 -305
  17. package/src/gap-finder.mjs +0 -376
  18. package/src/hotspot-analyzer.mjs +0 -412
  19. package/src/index.mjs +0 -151
  20. package/src/initialize.mjs +0 -957
  21. package/src/lens/project-structure.mjs +0 -74
  22. package/src/mapek-orchestration.mjs +0 -665
  23. package/src/materialize-plan.mjs +0 -422
  24. package/src/materialize.mjs +0 -137
  25. package/src/policy-derivation.mjs +0 -869
  26. package/src/project-config.mjs +0 -142
  27. package/src/project-diff.mjs +0 -28
  28. package/src/project-engine/build-utils.mjs +0 -237
  29. package/src/project-engine/code-analyzer.mjs +0 -248
  30. package/src/project-engine/doc-generator.mjs +0 -407
  31. package/src/project-engine/infrastructure.mjs +0 -213
  32. package/src/project-engine/metrics.mjs +0 -146
  33. package/src/project-model.mjs +0 -111
  34. package/src/project-report.mjs +0 -348
  35. package/src/refactoring-guide.mjs +0 -242
  36. package/src/stack-detect.mjs +0 -102
  37. package/src/stack-linter.mjs +0 -213
  38. package/src/template-infer.mjs +0 -674
  39. package/src/type-auditor.mjs +0 -609
@@ -1,407 +0,0 @@
1
- /**
2
- * @file Documentation Generator - Auto-generate API docs from JSDoc
3
- * @module @unrdf/project-engine/doc-generator
4
- */
5
-
6
- import { readFile, readdir } from 'node:fs/promises';
7
- import { join, basename, relative } from 'node:path';
8
- import { z } from 'zod';
9
-
10
- /**
11
- * JSDoc tag schema
12
- */
13
- const _JSDocTagSchema = z.object({
14
- name: z.string(),
15
- description: z.string(),
16
- params: z.array(
17
- z.object({
18
- name: z.string(),
19
- type: z.string(),
20
- description: z.string(),
21
- })
22
- ),
23
- returns: z
24
- .object({
25
- type: z.string(),
26
- description: z.string(),
27
- })
28
- .optional(),
29
- throws: z.array(z.string()).optional(),
30
- examples: z.array(z.string()).optional(),
31
- });
32
-
33
- /**
34
- * Generate API documentation from JSDoc comments
35
- * @param {string} packagePath - Path to package directory
36
- * @returns {Promise<string>} Markdown API documentation
37
- *
38
- * @throws {TypeError} If packagePath is not a string
39
- * @throws {Error} If package directory doesn't exist
40
- *
41
- * @example
42
- * const docs = await generateApiDocs('./packages/core');
43
- * console.log(docs);
44
- */
45
- export async function generateApiDocs(packagePath) {
46
- if (typeof packagePath !== 'string') {
47
- throw new TypeError('generateApiDocs: packagePath must be a string');
48
- }
49
-
50
- try {
51
- const srcPath = join(packagePath, 'src');
52
- const files = await findSourceFiles(srcPath);
53
-
54
- const sections = [];
55
- sections.push('# API Documentation\n');
56
- sections.push(`Package: \`${basename(packagePath)}\`\n`);
57
-
58
- for (const file of files) {
59
- const content = await readFile(file, 'utf-8');
60
- const functions = extractFunctions(content);
61
-
62
- if (functions.length > 0) {
63
- const relPath = relative(srcPath, file);
64
- sections.push(`## ${relPath}\n`);
65
-
66
- for (const fn of functions) {
67
- sections.push(formatFunctionDoc(fn));
68
- }
69
- }
70
- }
71
-
72
- return sections.join('\n');
73
- } catch (error) {
74
- throw new Error(`generateApiDocs failed: ${error.message}`);
75
- }
76
- }
77
-
78
- /**
79
- * Generate package user guide template
80
- * @param {string} packagePath - Path to package directory
81
- * @returns {Promise<string>} Markdown user guide template
82
- *
83
- * @throws {TypeError} If packagePath is not a string
84
- * @throws {Error} If package.json cannot be read
85
- *
86
- * @example
87
- * const guide = await generatePackageGuide('./packages/core');
88
- * console.log(guide);
89
- */
90
- export async function generatePackageGuide(packagePath) {
91
- if (typeof packagePath !== 'string') {
92
- throw new TypeError('generatePackageGuide: packagePath must be a string');
93
- }
94
-
95
- try {
96
- const packageJsonPath = join(packagePath, 'package.json');
97
- const packageJsonContent = await readFile(packageJsonPath, 'utf-8');
98
- const packageJson = JSON.parse(packageJsonContent);
99
-
100
- const sections = [];
101
- sections.push(`# ${packageJson.name}\n`);
102
- sections.push(`${packageJson.description}\n`);
103
- sections.push('## Installation\n');
104
- sections.push('```bash');
105
- sections.push(`pnpm add ${packageJson.name}`);
106
- sections.push('```\n');
107
- sections.push('## Quick Start\n');
108
- sections.push('```javascript');
109
- sections.push(`import { /* exports */ } from '${packageJson.name}';`);
110
- sections.push('```\n');
111
- sections.push('## Features\n');
112
- sections.push('- Feature 1');
113
- sections.push('- Feature 2\n');
114
- sections.push('## API Reference\n');
115
- sections.push('See [API.md](./API.md) for detailed API documentation.\n');
116
- sections.push('## Examples\n');
117
- sections.push('### Basic Usage\n');
118
- sections.push('```javascript');
119
- sections.push('// Add example code here');
120
- sections.push('```\n');
121
- sections.push('## License\n');
122
- sections.push(`${packageJson.license || 'MIT'}\n`);
123
-
124
- return sections.join('\n');
125
- } catch (error) {
126
- throw new Error(`generatePackageGuide failed: ${error.message}`);
127
- }
128
- }
129
-
130
- /**
131
- * Generate changelog from git commits
132
- * @param {string} repoPath - Path to git repository
133
- * @returns {Promise<string>} Markdown changelog
134
- *
135
- * @throws {TypeError} If repoPath is not a string
136
- * @throws {Error} If git operations fail
137
- *
138
- * @example
139
- * const changelog = await generateChangelog('.');
140
- * console.log(changelog);
141
- */
142
- export async function generateChangelog(repoPath) {
143
- if (typeof repoPath !== 'string') {
144
- throw new TypeError('generateChangelog: repoPath must be a string');
145
- }
146
-
147
- try {
148
- const { execFile } = await import('node:child_process');
149
- const { promisify } = await import('node:util');
150
- const execFileAsync = promisify(execFile);
151
-
152
- // Get git log with commit messages
153
- const { stdout } = await execFileAsync(
154
- 'git',
155
- ['log', '--pretty=format:%H|%ai|%s|%an', '--no-merges'],
156
- { cwd: repoPath }
157
- );
158
-
159
- const commits = stdout
160
- .trim()
161
- .split('\n')
162
- .map(line => {
163
- const [hash, date, message, author] = line.split('|');
164
- return { hash, date, message, author };
165
- });
166
-
167
- const sections = [];
168
- sections.push('# Changelog\n');
169
-
170
- // Group by date (YYYY-MM-DD)
171
- const byDate = new Map();
172
- for (const commit of commits) {
173
- const dateKey = commit.date.split(' ')[0];
174
- if (!byDate.has(dateKey)) {
175
- byDate.set(dateKey, []);
176
- }
177
- byDate.get(dateKey).push(commit);
178
- }
179
-
180
- // Sort dates descending
181
- const sortedDates = Array.from(byDate.keys()).sort().reverse();
182
-
183
- for (const date of sortedDates.slice(0, 30)) {
184
- sections.push(`## ${date}\n`);
185
- const dateCommits = byDate.get(date);
186
- for (const commit of dateCommits) {
187
- sections.push(`- ${commit.message} (${commit.hash.slice(0, 7)})`);
188
- }
189
- sections.push('');
190
- }
191
-
192
- return sections.join('\n');
193
- } catch (error) {
194
- throw new Error(`generateChangelog failed: ${error.message}`);
195
- }
196
- }
197
-
198
- /**
199
- * Find all source files in directory
200
- * @param {string} dirPath - Directory path
201
- * @returns {Promise<Array<string>>} List of file paths
202
- */
203
- async function findSourceFiles(dirPath) {
204
- const files = [];
205
-
206
- try {
207
- const entries = await readdir(dirPath, { withFileTypes: true });
208
-
209
- for (const entry of entries) {
210
- const fullPath = join(dirPath, entry.name);
211
-
212
- if (entry.isDirectory()) {
213
- const subFiles = await findSourceFiles(fullPath);
214
- files.push(...subFiles);
215
- } else if (entry.isFile() && entry.name.endsWith('.mjs')) {
216
- files.push(fullPath);
217
- }
218
- }
219
- } catch (error) {
220
- // Directory doesn't exist or not accessible
221
- }
222
-
223
- return files;
224
- }
225
-
226
- /**
227
- * Extract function documentation from source code
228
- * @param {string} content - Source code content
229
- * @returns {Array<Object>} Function documentation objects
230
- */
231
- function extractFunctions(content) {
232
- const functions = [];
233
- const lines = content.split('\n');
234
-
235
- let currentDoc = null;
236
- let inDocComment = false;
237
-
238
- for (let i = 0; i < lines.length; i++) {
239
- const line = lines[i].trim();
240
-
241
- // Start of JSDoc comment
242
- if (line.startsWith('/**')) {
243
- inDocComment = true;
244
- currentDoc = { lines: [] };
245
- continue;
246
- }
247
-
248
- // End of JSDoc comment
249
- if (line.startsWith('*/') && inDocComment) {
250
- inDocComment = false;
251
-
252
- // Check next non-empty line for function declaration
253
- let j = i + 1;
254
- while (j < lines.length && lines[j].trim() === '') {
255
- j++;
256
- }
257
-
258
- if (j < lines.length) {
259
- const nextLine = lines[j].trim();
260
- const fnMatch = nextLine.match(/export\s+(async\s+)?function\s+(\w+)/);
261
-
262
- if (fnMatch) {
263
- const fnName = fnMatch[2];
264
- const doc = parseJSDoc(currentDoc.lines);
265
- functions.push({
266
- name: fnName,
267
- description: doc.description,
268
- params: doc.params,
269
- returns: doc.returns,
270
- throws: doc.throws,
271
- examples: doc.examples,
272
- });
273
- }
274
- }
275
-
276
- currentDoc = null;
277
- continue;
278
- }
279
-
280
- // Inside JSDoc comment
281
- if (inDocComment && currentDoc) {
282
- const cleaned = line.replace(/^\*\s?/, '');
283
- currentDoc.lines.push(cleaned);
284
- }
285
- }
286
-
287
- return functions;
288
- }
289
-
290
- /**
291
- * Parse JSDoc comment lines
292
- * @param {Array<string>} lines - JSDoc comment lines
293
- * @returns {Object} Parsed documentation
294
- */
295
- function parseJSDoc(lines) {
296
- const doc = {
297
- description: '',
298
- params: [],
299
- returns: null,
300
- throws: [],
301
- examples: [],
302
- };
303
-
304
- let currentTag = null;
305
- let currentText = [];
306
-
307
- for (const line of lines) {
308
- if (line.startsWith('@')) {
309
- // Save previous tag
310
- if (currentTag) {
311
- saveTag(doc, currentTag, currentText.join(' '));
312
- }
313
-
314
- // Parse new tag
315
- const match = line.match(/@(\w+)\s+(.+)/);
316
- if (match) {
317
- currentTag = match[1];
318
- currentText = [match[2]];
319
- }
320
- } else if (currentTag) {
321
- currentText.push(line);
322
- } else {
323
- doc.description += line + ' ';
324
- }
325
- }
326
-
327
- // Save last tag
328
- if (currentTag) {
329
- saveTag(doc, currentTag, currentText.join(' '));
330
- }
331
-
332
- doc.description = doc.description.trim();
333
-
334
- return doc;
335
- }
336
-
337
- /**
338
- * Save parsed JSDoc tag
339
- * @param {Object} doc - Documentation object
340
- * @param {string} tag - Tag name
341
- * @param {string} text - Tag text
342
- */
343
- function saveTag(doc, tag, text) {
344
- if (tag === 'param') {
345
- const match = text.match(/\{([^}]+)\}\s+(\w+)\s+-\s+(.+)/);
346
- if (match) {
347
- doc.params.push({
348
- type: match[1],
349
- name: match[2],
350
- description: match[3].trim(),
351
- });
352
- }
353
- } else if (tag === 'returns') {
354
- const match = text.match(/\{([^}]+)\}\s+(.+)/);
355
- if (match) {
356
- doc.returns = {
357
- type: match[1],
358
- description: match[2].trim(),
359
- };
360
- }
361
- } else if (tag === 'throws') {
362
- doc.throws.push(text.trim());
363
- } else if (tag === 'example') {
364
- doc.examples.push(text.trim());
365
- }
366
- }
367
-
368
- /**
369
- * Format function documentation as Markdown
370
- * @param {Object} fn - Function documentation
371
- * @returns {string} Markdown formatted documentation
372
- */
373
- function formatFunctionDoc(fn) {
374
- const sections = [];
375
-
376
- sections.push(`### ${fn.name}\n`);
377
- sections.push(`${fn.description}\n`);
378
-
379
- if (fn.params.length > 0) {
380
- sections.push('**Parameters:**\n');
381
- for (const param of fn.params) {
382
- sections.push(`- \`${param.name}\` (\`${param.type}\`): ${param.description}`);
383
- }
384
- sections.push('');
385
- }
386
-
387
- if (fn.returns) {
388
- sections.push(`**Returns:** \`${fn.returns.type}\` - ${fn.returns.description}\n`);
389
- }
390
-
391
- if (fn.throws && fn.throws.length > 0) {
392
- sections.push('**Throws:**\n');
393
- for (const throwsDesc of fn.throws) {
394
- sections.push(`- ${throwsDesc}`);
395
- }
396
- sections.push('');
397
- }
398
-
399
- if (fn.examples && fn.examples.length > 0) {
400
- sections.push('**Example:**\n');
401
- sections.push('```javascript');
402
- sections.push(fn.examples.join('\n'));
403
- sections.push('```\n');
404
- }
405
-
406
- return sections.join('\n');
407
- }
@@ -1,213 +0,0 @@
1
- /**
2
- * @file Infrastructure - Project configuration and templates
3
- * @module @unrdf/project-engine/infrastructure
4
- */
5
-
6
- import { z } from 'zod';
7
-
8
- /**
9
- * Project config schema
10
- */
11
- const ProjectConfigSchema = z.object({
12
- name: z.string(),
13
- type: z.enum(['library', 'application', 'monorepo']),
14
- runtime: z.enum(['node', 'browser', 'both']),
15
- testing: z.object({
16
- framework: z.enum(['vitest', 'jest', 'mocha']),
17
- coverage: z.number().min(0).max(100),
18
- }),
19
- linting: z.object({
20
- enabled: z.boolean(),
21
- rules: z.string(),
22
- }),
23
- formatting: z.object({
24
- enabled: z.boolean(),
25
- tool: z.enum(['prettier', 'eslint']),
26
- }),
27
- });
28
-
29
- /**
30
- * Create project configuration
31
- * @param {string} template - Template name (basic, library, monorepo)
32
- * @returns {Object} Project configuration object
33
- *
34
- * @throws {TypeError} If template is not a string
35
- * @throws {Error} If template is invalid
36
- *
37
- * @example
38
- * const config = createProjectConfig('library');
39
- * console.log('Config:', config);
40
- */
41
- export function createProjectConfig(template) {
42
- if (typeof template !== 'string') {
43
- throw new TypeError('createProjectConfig: template must be a string');
44
- }
45
-
46
- const templates = {
47
- basic: {
48
- name: 'basic-project',
49
- type: 'library',
50
- runtime: 'node',
51
- testing: {
52
- framework: 'vitest',
53
- coverage: 80,
54
- },
55
- linting: {
56
- enabled: true,
57
- rules: 'recommended',
58
- },
59
- formatting: {
60
- enabled: true,
61
- tool: 'prettier',
62
- },
63
- },
64
- library: {
65
- name: 'my-library',
66
- type: 'library',
67
- runtime: 'both',
68
- testing: {
69
- framework: 'vitest',
70
- coverage: 90,
71
- },
72
- linting: {
73
- enabled: true,
74
- rules: 'strict',
75
- },
76
- formatting: {
77
- enabled: true,
78
- tool: 'prettier',
79
- },
80
- },
81
- monorepo: {
82
- name: 'my-monorepo',
83
- type: 'monorepo',
84
- runtime: 'both',
85
- testing: {
86
- framework: 'vitest',
87
- coverage: 80,
88
- },
89
- linting: {
90
- enabled: true,
91
- rules: 'recommended',
92
- },
93
- formatting: {
94
- enabled: true,
95
- tool: 'prettier',
96
- },
97
- },
98
- };
99
-
100
- const config = templates[template];
101
-
102
- if (!config) {
103
- throw new Error(`createProjectConfig: invalid template "${template}"`);
104
- }
105
-
106
- return ProjectConfigSchema.parse(config);
107
- }
108
-
109
- /**
110
- * Setup development environment configuration
111
- * @returns {Object} Development environment config
112
- *
113
- * @example
114
- * const devConfig = setupDevEnvironment();
115
- * console.log('Dev tools:', devConfig.tools);
116
- */
117
- export function setupDevEnvironment() {
118
- return {
119
- tools: {
120
- packageManager: 'pnpm',
121
- nodeVersion: '>=18.0.0',
122
- editor: {
123
- vscode: {
124
- extensions: ['dbaeumer.vscode-eslint', 'esbenp.prettier-vscode', 'vitest.explorer'],
125
- settings: {
126
- 'editor.formatOnSave': true,
127
- 'editor.codeActionsOnSave': {
128
- 'source.fixAll.eslint': true,
129
- },
130
- },
131
- },
132
- },
133
- git: {
134
- hooks: {
135
- 'pre-commit': 'pnpm lint && pnpm test',
136
- 'pre-push': 'pnpm build',
137
- },
138
- },
139
- },
140
- scripts: {
141
- dev: 'vitest --watch',
142
- build: 'node build.config.mjs',
143
- test: 'vitest run --coverage',
144
- lint: 'eslint src/ test/ --max-warnings=0',
145
- format: 'prettier --write src/ test/',
146
- },
147
- };
148
- }
149
-
150
- /**
151
- * Create deployment configuration
152
- * @param {string} environment - Environment name (development, staging, production)
153
- * @returns {Object} Deployment configuration
154
- *
155
- * @throws {TypeError} If environment is not a string
156
- * @throws {Error} If environment is invalid
157
- *
158
- * @example
159
- * const deployConfig = createDeploymentConfig('production');
160
- * console.log('Deploy to:', deployConfig.target);
161
- */
162
- export function createDeploymentConfig(environment) {
163
- if (typeof environment !== 'string') {
164
- throw new TypeError('createDeploymentConfig: environment must be a string');
165
- }
166
-
167
- const configs = {
168
- development: {
169
- environment: 'development',
170
- target: 'local',
171
- build: {
172
- minify: false,
173
- sourceMaps: true,
174
- },
175
- env: {
176
- NODE_ENV: 'development',
177
- DEBUG: 'true',
178
- },
179
- },
180
- staging: {
181
- environment: 'staging',
182
- target: 'staging-server',
183
- build: {
184
- minify: true,
185
- sourceMaps: true,
186
- },
187
- env: {
188
- NODE_ENV: 'staging',
189
- DEBUG: 'false',
190
- },
191
- },
192
- production: {
193
- environment: 'production',
194
- target: 'production-server',
195
- build: {
196
- minify: true,
197
- sourceMaps: false,
198
- },
199
- env: {
200
- NODE_ENV: 'production',
201
- DEBUG: 'false',
202
- },
203
- },
204
- };
205
-
206
- const config = configs[environment];
207
-
208
- if (!config) {
209
- throw new Error(`createDeploymentConfig: invalid environment "${environment}"`);
210
- }
211
-
212
- return config;
213
- }