scai 0.1.108 → 0.1.110

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.
@@ -0,0 +1,37 @@
1
+ import { execSync } from "child_process";
2
+ import path from "path";
3
+ export const runTestsModule = {
4
+ name: "runTestsModule",
5
+ description: "Runs generated Jest tests with safety checks for a single file",
6
+ async run(input) {
7
+ const { filepath } = input;
8
+ if (!filepath) {
9
+ throw new Error("No filepath provided to runTestsModule.");
10
+ }
11
+ const absoluteFilePath = path.resolve(filepath);
12
+ try {
13
+ // Step 1: TypeScript syntax check for this file only using tsconfig.test.json
14
+ // Step 1: TypeScript syntax check for this file only
15
+ execSync(`npx tsc --noEmit --project tsconfig.test.json`, { stdio: "inherit" });
16
+ // Step 2: Dry-run Jest for this file only
17
+ execSync(`npx jest --config ${path.resolve("jest.config.ts")} --dryRun ${absoluteFilePath}`, { stdio: "inherit" });
18
+ // Step 3: Full Jest run for this file only
19
+ execSync(`npx jest --config ${path.resolve("jest.config.ts")} ${absoluteFilePath}`, { stdio: "inherit" });
20
+ return {
21
+ content: "✅ Tests ran successfully",
22
+ filepath,
23
+ mode: "skip",
24
+ summary: "All tests passed successfully."
25
+ };
26
+ }
27
+ catch (error) {
28
+ const errorMessage = error?.message || String(error);
29
+ return {
30
+ content: `❌ Test run failed:\n${errorMessage}`,
31
+ filepath,
32
+ mode: "skip",
33
+ summary: errorMessage // provides failure context for repair
34
+ };
35
+ }
36
+ }
37
+ };
@@ -6,6 +6,8 @@ import { commitSuggesterModule } from '../modules/commitSuggesterModule.js';
6
6
  import { changelogModule } from '../modules/changeLogModule.js';
7
7
  import { cleanGeneratedTestsModule } from '../modules/cleanGeneratedTestsModule.js';
8
8
  import { preserveCodeModule } from '../modules/preserveCodeModule.js';
9
+ import { runTestsModule } from '../modules/runTestsModule.js';
10
+ import { repairTestsModule } from '../modules/repairTestsModule.js';
9
11
  // Built-in modules with metadata
10
12
  export const builtInModules = {
11
13
  comments: {
@@ -38,6 +40,21 @@ export const builtInModules = {
38
40
  ...cleanGeneratedTestsModule,
39
41
  group: 'testing',
40
42
  },
43
+ runTests: {
44
+ ...runTestsModule,
45
+ group: 'testing',
46
+ dependencies: {
47
+ before: ['tests'], // must exist after tests are generated
48
+ after: ['cleanTests'], // run after cleaning
49
+ },
50
+ },
51
+ repairTests: {
52
+ ...repairTestsModule,
53
+ group: 'testing',
54
+ dependencies: {
55
+ after: ['runTests'], // repair runs after tests have been executed
56
+ },
57
+ },
41
58
  suggest: {
42
59
  ...commitSuggesterModule,
43
60
  group: 'git',
@@ -224,3 +224,101 @@ const functionRows = db.prepare(`
224
224
  LIMIT 50
225
225
  `).all();
226
226
  console.table(functionRows);
227
+ // === Class Table Stats ===
228
+ console.log('\n📊 Stats for Table: classes');
229
+ console.log('-------------------------------------------');
230
+ try {
231
+ const classCount = db.prepare(`SELECT COUNT(*) AS count FROM classes`).get().count;
232
+ const distinctClassFiles = db.prepare(`SELECT COUNT(DISTINCT file_id) AS count FROM classes`).get().count;
233
+ console.log(`🏷 Total classes: ${classCount}`);
234
+ console.log(`📂 Distinct files: ${distinctClassFiles}`);
235
+ }
236
+ catch (err) {
237
+ console.error('❌ Error accessing classes table:', err.message);
238
+ }
239
+ // === Example Classes ===
240
+ console.log('\n🧪 Example extracted classes:');
241
+ try {
242
+ const sampleClasses = db.prepare(`
243
+ SELECT id, name, file_id, start_line, end_line, substr(content, 1, 100) || '...' AS short_body
244
+ FROM classes
245
+ ORDER BY id DESC
246
+ LIMIT 5
247
+ `).all();
248
+ sampleClasses.forEach(cls => {
249
+ console.log(`🏷 ID: ${cls.id}`);
250
+ console.log(` Name: ${cls.name}`);
251
+ console.log(` File: ${cls.file_id}`);
252
+ console.log(` Lines: ${cls.start_line}-${cls.end_line}`);
253
+ console.log(` Body: ${cls.short_body}\n`);
254
+ });
255
+ }
256
+ catch (err) {
257
+ console.error('❌ Error printing class examples:', err.message);
258
+ }
259
+ // === Edge Table Stats ===
260
+ console.log('\n📊 Stats for Table: edges');
261
+ console.log('-------------------------------------------');
262
+ try {
263
+ const edgeCount = db.prepare(`SELECT COUNT(*) AS count FROM edges`).get().count;
264
+ const distinctRelations = db.prepare(`SELECT COUNT(DISTINCT relation) AS count FROM edges`).get().count;
265
+ console.log(`🔗 Total edges: ${edgeCount}`);
266
+ console.log(`🧩 Distinct relations: ${distinctRelations}`);
267
+ }
268
+ catch (err) {
269
+ console.error('❌ Error accessing edges table:', err.message);
270
+ }
271
+ // === Example Edges ===
272
+ console.log('\n🧪 Example edges:');
273
+ try {
274
+ const sampleEdges = db.prepare(`
275
+ SELECT id, source_id, target_id, relation
276
+ FROM edges
277
+ ORDER BY id DESC
278
+ LIMIT 10
279
+ `).all();
280
+ sampleEdges.forEach(e => {
281
+ console.log(`🔗 Edge ${e.id}: ${e.source_id} -[${e.relation}]-> ${e.target_id}`);
282
+ });
283
+ }
284
+ catch (err) {
285
+ console.error('❌ Error printing edge examples:', err.message);
286
+ }
287
+ // === Tags Master Stats ===
288
+ console.log('\n📊 Stats for Table: tags_master');
289
+ console.log('-------------------------------------------');
290
+ try {
291
+ const tagCount = db.prepare(`SELECT COUNT(*) AS count FROM tags_master`).get().count;
292
+ console.log(`🏷 Total tags: ${tagCount}`);
293
+ const sampleTags = db.prepare(`
294
+ SELECT id, name
295
+ FROM tags_master
296
+ ORDER BY id DESC
297
+ LIMIT 5
298
+ `).all();
299
+ sampleTags.forEach(tag => {
300
+ console.log(`🏷 Tag ${tag.id}: ${tag.name}`);
301
+ });
302
+ }
303
+ catch (err) {
304
+ console.error('❌ Error accessing tags_master table:', err.message);
305
+ }
306
+ // === Entity Tags Stats ===
307
+ console.log('\n📊 Stats for Table: entity_tags');
308
+ console.log('-------------------------------------------');
309
+ try {
310
+ const entityTagCount = db.prepare(`SELECT COUNT(*) AS count FROM entity_tags`).get().count;
311
+ console.log(`🔗 Total entity-tags: ${entityTagCount}`);
312
+ const sampleEntityTags = db.prepare(`
313
+ SELECT id, entity_type, entity_id, tag_id
314
+ FROM entity_tags
315
+ ORDER BY id DESC
316
+ LIMIT 10
317
+ `).all();
318
+ sampleEntityTags.forEach(et => {
319
+ console.log(`🔗 EntityTag ${et.id}: ${et.entity_type} ${et.entity_id} -> tag ${et.tag_id}`);
320
+ });
321
+ }
322
+ catch (err) {
323
+ console.error('❌ Error accessing entity_tags table:', err.message);
324
+ }
package/dist/utils/log.js CHANGED
@@ -1,5 +1,5 @@
1
+ import { LOG_PATH } from "../constants.js";
1
2
  import fs from 'fs';
2
- import { LOG_PATH } from '../constants.js';
3
3
  export function log(...args) {
4
4
  const timestamp = new Date().toISOString();
5
5
  const message = args.map(arg => typeof arg === 'string' ? arg : JSON.stringify(arg, null, 2)).join(' ');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scai",
3
- "version": "0.1.108",
3
+ "version": "0.1.110",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "scai": "./dist/index.js"
@@ -34,7 +34,7 @@
34
34
  "workflow"
35
35
  ],
36
36
  "scripts": {
37
- "build": "rm -rfd dist && tsc && git add .",
37
+ "build": "rm -rfd dist && tsc && chmod +x dist/index.js && git add .",
38
38
  "start": "node dist/index.js"
39
39
  },
40
40
  "dependencies": {
@@ -1,11 +0,0 @@
1
- const config = {
2
- preset: 'ts-jest',
3
- testEnvironment: 'node',
4
- setupFilesAfterEnv: ['./jest.setup.ts'],
5
- transform: {
6
- '^.+\\.ts$': 'ts-jest',
7
- },
8
- moduleFileExtensions: ['ts', 'js', 'json', 'node'],
9
- testPathIgnorePatterns: ['/node_modules/', '/dist/'],
10
- };
11
- export default config;
@@ -1,14 +0,0 @@
1
- import { jest } from '@jest/globals';
2
- // jest.setup.ts
3
- // Mock the global fetch function in Jest for Node.js 18+
4
- global.fetch = jest.fn(() => Promise.resolve({
5
- json: () => Promise.resolve({ response: 'Mocked Commit Message' }),
6
- ok: true,
7
- status: 200,
8
- statusText: 'OK',
9
- headers: new Headers(),
10
- redirected: false,
11
- type: 'default',
12
- url: 'https://mocked-url.com',
13
- }) // Type assertion for `Response` object
14
- );
@@ -1,11 +0,0 @@
1
- import { execSync } from 'child_process';
2
- export function runJestTest(testFile) {
3
- try {
4
- execSync(`npx jest ${testFile} --silent`, { stdio: 'inherit' });
5
- return true;
6
- }
7
- catch (err) {
8
- console.error(`❌ Tests failed for ${testFile}`);
9
- return false;
10
- }
11
- }