@topogram/cli 0.3.77 → 0.3.79

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 (129) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/package.json +2 -2
  3. package/src/agent-brief.js +29 -23
  4. package/src/agent-ops/query-builders/change-risk/{import-plan.js → extract-plan.js} +1 -1
  5. package/src/agent-ops/query-builders/change-risk/review-packets.js +5 -5
  6. package/src/agent-ops/query-builders/change-risk.js +1 -1
  7. package/src/agent-ops/query-builders/common.js +2 -2
  8. package/src/agent-ops/query-builders/multi-agent.js +1 -1
  9. package/src/agent-ops/query-builders/workflow-context-shared.js +4 -4
  10. package/src/catalog/provenance.js +1 -1
  11. package/src/cli/catalog-alias.d.ts +2 -0
  12. package/src/cli/catalog-alias.js +2 -2
  13. package/src/cli/command-parsers/core.js +9 -5
  14. package/src/cli/command-parsers/import.js +11 -17
  15. package/src/cli/command-parsers/project.js +0 -3
  16. package/src/cli/commands/catalog/copy.js +3 -3
  17. package/src/cli/commands/catalog/help.js +1 -2
  18. package/src/cli/commands/catalog/list.js +7 -4
  19. package/src/cli/commands/catalog/show.js +4 -4
  20. package/src/cli/commands/copy.js +356 -0
  21. package/src/cli/commands/doctor.js +1 -1
  22. package/src/cli/commands/import/adopt.js +9 -9
  23. package/src/cli/commands/import/check.js +15 -15
  24. package/src/cli/commands/import/diff.js +6 -6
  25. package/src/cli/commands/import/help.js +43 -34
  26. package/src/cli/commands/import/paths.js +3 -3
  27. package/src/cli/commands/import/plan.js +8 -8
  28. package/src/cli/commands/import/refresh.js +25 -24
  29. package/src/cli/commands/import/status-history.js +4 -4
  30. package/src/cli/commands/import/workspace.js +16 -16
  31. package/src/cli/commands/import-runner.js +6 -5
  32. package/src/cli/commands/import.js +4 -1
  33. package/src/cli/commands/init.js +67 -0
  34. package/src/cli/commands/query/{import-adopt.js → extract-adopt.js} +2 -2
  35. package/src/cli/commands/query/runner/change.js +2 -2
  36. package/src/cli/commands/query/runner/{import-adopt.js → extract-adopt.js} +9 -9
  37. package/src/cli/commands/query/runner/index.js +1 -1
  38. package/src/cli/commands/query/runner/workflow.js +7 -7
  39. package/src/cli/commands/query/workspace.js +4 -4
  40. package/src/cli/commands/release-status.js +2 -2
  41. package/src/cli/commands/source.js +2 -2
  42. package/src/cli/commands/template/check.js +2 -2
  43. package/src/cli/commands/template/list-show.js +4 -4
  44. package/src/cli/dispatcher.js +18 -3
  45. package/src/cli/help-dispatch.js +22 -8
  46. package/src/cli/help.js +68 -52
  47. package/src/cli/migration-guidance.js +9 -0
  48. package/src/generator/context/bundle.js +14 -7
  49. package/src/generator/context/diff.js +8 -1
  50. package/src/generator/context/digest.js +10 -1
  51. package/src/generator/context/shared/domain-sdlc.js +5 -1
  52. package/src/generator/context/shared/relationships.js +20 -5
  53. package/src/generator/context/shared/summaries.js +26 -0
  54. package/src/generator/context/shared.d.ts +1 -0
  55. package/src/generator/context/shared.js +1 -0
  56. package/src/generator/context/slice/core.js +9 -5
  57. package/src/generator/context/slice/sdlc.js +31 -2
  58. package/src/generator/context/task-mode.js +3 -3
  59. package/src/import/core/runner/reports.js +4 -4
  60. package/src/import/core/shared/files.js +21 -2
  61. package/src/import/core/shared.js +2 -1
  62. package/src/import/enrichers/django-rest.js +4 -4
  63. package/src/import/enrichers/rails-controllers.js +3 -3
  64. package/src/import/enrichers/rails-models.js +3 -3
  65. package/src/import/extractors/api/aspnet-core.js +5 -5
  66. package/src/import/extractors/api/django-routes.js +5 -5
  67. package/src/import/extractors/api/express.js +4 -4
  68. package/src/import/extractors/api/fastify.js +7 -7
  69. package/src/import/extractors/api/flutter-dio.js +4 -4
  70. package/src/import/extractors/api/generic-route-fallback.js +2 -2
  71. package/src/import/extractors/api/graphql-code-first.js +3 -3
  72. package/src/import/extractors/api/graphql-sdl.js +5 -5
  73. package/src/import/extractors/api/jaxrs.js +3 -3
  74. package/src/import/extractors/api/micronaut.js +3 -3
  75. package/src/import/extractors/api/openapi-code.js +4 -4
  76. package/src/import/extractors/api/openapi.js +3 -3
  77. package/src/import/extractors/api/rails-routes.js +3 -3
  78. package/src/import/extractors/api/react-native-repository.js +3 -3
  79. package/src/import/extractors/api/retrofit.js +3 -3
  80. package/src/import/extractors/api/spring-web.js +3 -3
  81. package/src/import/extractors/api/swift-webapi.js +3 -3
  82. package/src/import/extractors/api/trpc.js +4 -4
  83. package/src/import/extractors/cli/generic.js +3 -3
  84. package/src/import/extractors/db/django-models.js +4 -4
  85. package/src/import/extractors/db/dotnet-models.js +4 -4
  86. package/src/import/extractors/db/drizzle.js +9 -7
  87. package/src/import/extractors/db/ef-core.js +5 -5
  88. package/src/import/extractors/db/flutter-entities.js +3 -3
  89. package/src/import/extractors/db/jpa.js +3 -3
  90. package/src/import/extractors/db/liquibase.js +3 -3
  91. package/src/import/extractors/db/maintained-seams.js +4 -4
  92. package/src/import/extractors/db/mybatis-xml.js +4 -4
  93. package/src/import/extractors/db/prisma.js +3 -3
  94. package/src/import/extractors/db/rails-schema.js +3 -3
  95. package/src/import/extractors/db/react-native-entities.js +3 -3
  96. package/src/import/extractors/db/room.js +5 -5
  97. package/src/import/extractors/db/snapshot.js +3 -3
  98. package/src/import/extractors/db/sql.js +3 -3
  99. package/src/import/extractors/db/swiftdata.js +3 -3
  100. package/src/import/extractors/ui/android-compose.js +4 -4
  101. package/src/import/extractors/ui/backend-only.js +3 -3
  102. package/src/import/extractors/ui/blazor.js +3 -3
  103. package/src/import/extractors/ui/flutter-screens.js +3 -3
  104. package/src/import/extractors/ui/maui-xaml.js +4 -4
  105. package/src/import/extractors/ui/next-pages-router.js +3 -3
  106. package/src/import/extractors/ui/razor-pages.js +3 -3
  107. package/src/import/extractors/ui/react-native-screens.js +4 -4
  108. package/src/import/extractors/ui/swiftui.js +3 -3
  109. package/src/import/extractors/ui/uikit.js +3 -3
  110. package/src/import/provenance.js +16 -16
  111. package/src/init-project.js +215 -0
  112. package/src/new-project/constants.js +1 -1
  113. package/src/new-project/create.js +2 -2
  114. package/src/new-project/project-files.js +7 -7
  115. package/src/reconcile/journeys.js +8 -3
  116. package/src/record-blocks.js +125 -0
  117. package/src/resolver/index.js +3 -0
  118. package/src/resolver/journeys.js +74 -0
  119. package/src/resolver/normalize.js +25 -0
  120. package/src/sdlc/adopt.js +1 -1
  121. package/src/validator/common.js +34 -1
  122. package/src/validator/index.js +4 -0
  123. package/src/validator/kinds.d.ts +2 -0
  124. package/src/validator/kinds.js +34 -1
  125. package/src/validator/per-kind/journey.js +233 -0
  126. package/src/workflows/docs-generate.js +4 -1
  127. package/src/workflows/reconcile/bundle-core/index.js +4 -2
  128. package/src/workflows/reconcile/canonical-surface.js +4 -1
  129. package/src/cli/commands/new.js +0 -94
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  dedupeCandidateRecords,
3
- findImportFiles,
3
+ findPrimaryImportFiles,
4
4
  inferApiEntityIdFromPath,
5
5
  inferRouteCapabilityId,
6
6
  makeCandidateRecord,
@@ -11,7 +11,7 @@ import {
11
11
  } from "../../core/shared.js";
12
12
 
13
13
  function buildJavaFileIndex(paths) {
14
- const files = findImportFiles(paths, (filePath) => /\.java$/i.test(filePath));
14
+ const files = findPrimaryImportFiles(paths, (filePath) => /\.java$/i.test(filePath));
15
15
  return files.map((filePath) => ({
16
16
  filePath,
17
17
  relativePath: relativeTo(paths.repoRoot, filePath),
@@ -253,7 +253,7 @@ export const jaxRsExtractor = {
253
253
  id: "api.jaxrs",
254
254
  track: "api",
255
255
  detect(context) {
256
- const javaFiles = findImportFiles(context.paths, (filePath) => /\.java$/i.test(filePath));
256
+ const javaFiles = findPrimaryImportFiles(context.paths, (filePath) => /\.java$/i.test(filePath));
257
257
  const jaxrsCount = javaFiles.filter((filePath) => /@Path\(|@(GET|POST|PUT|PATCH|DELETE)\b/.test(readTextIfExists(filePath) || "")).length;
258
258
  return {
259
259
  score: jaxrsCount > 0 ? 92 : 0,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  dedupeCandidateRecords,
3
- findImportFiles,
3
+ findPrimaryImportFiles,
4
4
  inferApiEntityIdFromPath,
5
5
  inferRouteCapabilityId,
6
6
  makeCandidateRecord,
@@ -11,7 +11,7 @@ import {
11
11
  } from "../../core/shared.js";
12
12
 
13
13
  function buildJavaFileIndex(paths) {
14
- const files = findImportFiles(paths, (filePath) => /\.java$/i.test(filePath));
14
+ const files = findPrimaryImportFiles(paths, (filePath) => /\.java$/i.test(filePath));
15
15
  return files.map((filePath) => ({
16
16
  filePath,
17
17
  relativePath: relativeTo(paths.repoRoot, filePath),
@@ -163,7 +163,7 @@ export const micronautExtractor = {
163
163
  id: "api.micronaut",
164
164
  track: "api",
165
165
  detect(context) {
166
- const javaFiles = findImportFiles(context.paths, (filePath) => /\.java$/i.test(filePath));
166
+ const javaFiles = findPrimaryImportFiles(context.paths, (filePath) => /\.java$/i.test(filePath));
167
167
  const count = javaFiles.filter((filePath) => /io\.micronaut\.http\.annotation|@Controller\(|@Get\(|@Post\(|@Put\(|@Delete\(/.test(readTextIfExists(filePath) || "")).length;
168
168
  return {
169
169
  score: count > 0 ? 95 : 0,
@@ -2,7 +2,7 @@ import path from "node:path";
2
2
 
3
3
  import {
4
4
  dedupeCandidateRecords,
5
- findImportFiles,
5
+ findPrimaryImportFiles,
6
6
  inferApiCapabilityIdFromOperation,
7
7
  inferApiEntityIdFromPath,
8
8
  makeCandidateRecord,
@@ -183,15 +183,15 @@ export const openApiCodeExtractor = {
183
183
  id: "api.openapi-code",
184
184
  track: "api",
185
185
  detect(context) {
186
- const openApiFiles = findImportFiles(context.paths, (filePath) => /src\/docs\/openapi\.(ts|js|mjs|cjs)$/i.test(filePath));
186
+ const openApiFiles = findPrimaryImportFiles(context.paths, (filePath) => /src\/docs\/openapi\.(ts|js|mjs|cjs)$/i.test(filePath));
187
187
  return {
188
188
  score: openApiFiles.length > 0 ? 92 : 0,
189
189
  reasons: openApiFiles.length > 0 ? ["Found code-generated OpenAPI source"] : []
190
190
  };
191
191
  },
192
192
  extract(context) {
193
- const openApiFiles = findImportFiles(context.paths, (filePath) => /src\/docs\/openapi\.(ts|js|mjs|cjs)$/i.test(filePath));
194
- const schemaFile = findImportFiles(context.paths, (filePath) => /src\/docs\/openapi-schemas\.(ts|js|mjs|cjs)$/i.test(filePath))[0];
193
+ const openApiFiles = findPrimaryImportFiles(context.paths, (filePath) => /src\/docs\/openapi\.(ts|js|mjs|cjs)$/i.test(filePath));
194
+ const schemaFile = findPrimaryImportFiles(context.paths, (filePath) => /src\/docs\/openapi-schemas\.(ts|js|mjs|cjs)$/i.test(filePath))[0];
195
195
  const schemaFields = schemaFile ? parseZodObjectSchemaFields(context.helpers.readTextIfExists(schemaFile) || "") : new Map();
196
196
  const findings = [];
197
197
  const candidates = { capabilities: [], routes: [], stacks: [] };
@@ -1,4 +1,4 @@
1
- import { findImportFiles, isPrimaryImportSource, makeCandidateRecord, normalizeOpenApiPath, relativeTo, selectPreferredImportFiles, slugify, titleCase } from "../../core/shared.js";
1
+ import { findPrimaryImportFiles, isPrimaryImportSource, makeCandidateRecord, normalizeOpenApiPath, relativeTo, selectPreferredImportFiles, slugify, titleCase } from "../../core/shared.js";
2
2
 
3
3
  function openApiRefName(ref) {
4
4
  return typeof ref === "string" ? ref.split("/").pop() || null : null;
@@ -196,7 +196,7 @@ export const openApiExtractor = {
196
196
  detect(context) {
197
197
  const files = selectPreferredImportFiles(
198
198
  context.paths,
199
- findImportFiles(context.paths, (filePath) => /(openapi|swagger)\.(json|ya?ml)$/i.test(filePath) && isPrimaryImportSource(context.paths, filePath)),
199
+ findPrimaryImportFiles(context.paths, (filePath) => /(openapi|swagger)\.(json|ya?ml)$/i.test(filePath) && isPrimaryImportSource(context.paths, filePath)),
200
200
  "openapi"
201
201
  );
202
202
  return {
@@ -207,7 +207,7 @@ export const openApiExtractor = {
207
207
  extract(context) {
208
208
  const openApiFiles = selectPreferredImportFiles(
209
209
  context.paths,
210
- findImportFiles(context.paths, (filePath) => /(openapi|swagger)\.(json|ya?ml)$/i.test(filePath) && isPrimaryImportSource(context.paths, filePath)),
210
+ findPrimaryImportFiles(context.paths, (filePath) => /(openapi|swagger)\.(json|ya?ml)$/i.test(filePath) && isPrimaryImportSource(context.paths, filePath)),
211
211
  "openapi"
212
212
  );
213
213
  const findings = [];
@@ -2,7 +2,7 @@ import path from "node:path";
2
2
 
3
3
  import {
4
4
  dedupeCandidateRecords,
5
- findImportFiles,
5
+ findPrimaryImportFiles,
6
6
  inferApiEntityIdFromPath,
7
7
  inferRouteCapabilityId,
8
8
  makeCandidateRecord,
@@ -167,14 +167,14 @@ export const railsRoutesExtractor = {
167
167
  id: "api.rails-routes",
168
168
  track: "api",
169
169
  detect(context) {
170
- const routeFiles = findImportFiles(context.paths, (filePath) => /config\/routes\.rb$/i.test(filePath));
170
+ const routeFiles = findPrimaryImportFiles(context.paths, (filePath) => /config\/routes\.rb$/i.test(filePath));
171
171
  return {
172
172
  score: routeFiles.length > 0 ? 90 : 0,
173
173
  reasons: routeFiles.length > 0 ? ["Found Rails routes.rb"] : []
174
174
  };
175
175
  },
176
176
  extract(context) {
177
- const routeFiles = findImportFiles(context.paths, (filePath) => /config\/routes\.rb$/i.test(filePath));
177
+ const routeFiles = findPrimaryImportFiles(context.paths, (filePath) => /config\/routes\.rb$/i.test(filePath));
178
178
  const findings = [];
179
179
  const candidates = { capabilities: [], routes: [], stacks: [] };
180
180
 
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  canonicalCandidateTerm,
3
3
  dedupeCandidateRecords,
4
- findImportFiles,
4
+ findPrimaryImportFiles,
5
5
  makeCandidateRecord,
6
6
  pluralizeCandidateTerm,
7
7
  relativeTo,
@@ -82,7 +82,7 @@ export const reactNativeRepositoryExtractor = {
82
82
  id: "api.react-native-repository",
83
83
  track: "api",
84
84
  detect(context) {
85
- const files = findImportFiles(
85
+ const files = findPrimaryImportFiles(
86
86
  context.paths,
87
87
  (filePath) => /\/src\/.+\/infrastructure\/implementations\/.+Repository\.ts$/i.test(filePath)
88
88
  );
@@ -93,7 +93,7 @@ export const reactNativeRepositoryExtractor = {
93
93
  };
94
94
  },
95
95
  extract(context) {
96
- const files = findImportFiles(
96
+ const files = findPrimaryImportFiles(
97
97
  context.paths,
98
98
  (filePath) => /\/src\/.+\/infrastructure\/implementations\/.+Repository\.ts$/i.test(filePath)
99
99
  );
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  canonicalCandidateTerm,
3
3
  dedupeCandidateRecords,
4
- findImportFiles,
4
+ findPrimaryImportFiles,
5
5
  makeCandidateRecord,
6
6
  relativeTo,
7
7
  titleCase
@@ -66,7 +66,7 @@ export const retrofitExtractor = {
66
66
  id: "api.retrofit",
67
67
  track: "api",
68
68
  detect(context) {
69
- const serviceFiles = findImportFiles(context.paths, (filePath) => /Service\.kt$/i.test(filePath) || /retrofit\/.+\.kt$/i.test(filePath));
69
+ const serviceFiles = findPrimaryImportFiles(context.paths, (filePath) => /Service\.kt$/i.test(filePath) || /retrofit\/.+\.kt$/i.test(filePath));
70
70
  const score = serviceFiles.some((filePath) => /@GET|@POST|@PUT|@PATCH|@DELETE/.test(context.helpers.readTextIfExists(filePath) || "")) ? 87 : 0;
71
71
  return {
72
72
  score,
@@ -74,7 +74,7 @@ export const retrofitExtractor = {
74
74
  };
75
75
  },
76
76
  extract(context) {
77
- const serviceFiles = findImportFiles(context.paths, (filePath) => /Service\.kt$/i.test(filePath) || /retrofit\/.+\.kt$/i.test(filePath));
77
+ const serviceFiles = findPrimaryImportFiles(context.paths, (filePath) => /Service\.kt$/i.test(filePath) || /retrofit\/.+\.kt$/i.test(filePath));
78
78
  const capabilities = [];
79
79
  for (const filePath of serviceFiles) {
80
80
  const provenance = relativeTo(context.paths.repoRoot, filePath);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  dedupeCandidateRecords,
3
- findImportFiles,
3
+ findPrimaryImportFiles,
4
4
  inferApiEntityIdFromPath,
5
5
  inferRouteCapabilityId,
6
6
  makeCandidateRecord,
@@ -13,7 +13,7 @@ import {
13
13
  const JAVA_ANNOTATION_PATTERN = String.raw`@[\w.]+(?:\((?:[^()]|\([^)]*\))*\))?`;
14
14
 
15
15
  function buildJavaFileIndex(paths) {
16
- const files = findImportFiles(paths, (filePath) => /\.java$/i.test(filePath));
16
+ const files = findPrimaryImportFiles(paths, (filePath) => /\.java$/i.test(filePath));
17
17
  return files.map((filePath) => ({
18
18
  filePath,
19
19
  relativePath: relativeTo(paths.repoRoot, filePath),
@@ -318,7 +318,7 @@ export const springWebExtractor = {
318
318
  id: "api.spring-web",
319
319
  track: "api",
320
320
  detect(context) {
321
- const javaFiles = findImportFiles(context.paths, (filePath) => /\.java$/i.test(filePath));
321
+ const javaFiles = findPrimaryImportFiles(context.paths, (filePath) => /\.java$/i.test(filePath));
322
322
  const springCount = javaFiles.filter((filePath) => /@(RestController|Controller)|@(?:Get|Post|Put|Patch|Delete)Exchange|@(GetMapping|PostMapping|PutMapping|PatchMapping|DeleteMapping)|@RequestMapping/.test(readTextIfExists(filePath) || "")).length;
323
323
  return {
324
324
  score: springCount > 0 ? 90 : 0,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  canonicalCandidateTerm,
3
3
  dedupeCandidateRecords,
4
- findImportFiles,
4
+ findPrimaryImportFiles,
5
5
  idHintify,
6
6
  makeCandidateRecord,
7
7
  relativeTo,
@@ -78,7 +78,7 @@ export const swiftWebApiExtractor = {
78
78
  id: "api.swift-webapi",
79
79
  track: "api",
80
80
  detect(context) {
81
- const files = findImportFiles(context.paths, (filePath) => /WebRepository\.swift$/i.test(filePath) || /WebAPI\/.+\.swift$/i.test(filePath));
81
+ const files = findPrimaryImportFiles(context.paths, (filePath) => /WebRepository\.swift$/i.test(filePath) || /WebAPI\/.+\.swift$/i.test(filePath));
82
82
  const score = files.some((filePath) => /APICall|URLSession/.test(context.helpers.readTextIfExists(filePath) || "")) ? 85 : 0;
83
83
  return {
84
84
  score,
@@ -86,7 +86,7 @@ export const swiftWebApiExtractor = {
86
86
  };
87
87
  },
88
88
  extract(context) {
89
- const files = findImportFiles(context.paths, (filePath) => /WebAPI\/.+\.swift$/i.test(filePath))
89
+ const files = findPrimaryImportFiles(context.paths, (filePath) => /WebAPI\/.+\.swift$/i.test(filePath))
90
90
  .filter((filePath) => /struct\s+Real/.test(context.helpers.readTextIfExists(filePath) || ""));
91
91
  const capabilities = [];
92
92
  for (const filePath of files) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  dedupeCandidateRecords,
3
- findImportFiles,
3
+ findPrimaryImportFiles,
4
4
  inferApiEntityIdFromPath,
5
5
  makeCandidateRecord,
6
6
  pluralizeCandidateTerm,
@@ -156,15 +156,15 @@ export const trpcExtractor = {
156
156
  id: "api.trpc",
157
157
  track: "api",
158
158
  detect(context) {
159
- const routerFiles = findImportFiles(context.paths, (filePath) => /src\/server\/routers\/.+\.(ts|tsx|js|jsx)$/i.test(filePath));
160
- const trpcHandler = findImportFiles(context.paths, (filePath) => /src\/pages\/api\/trpc\/\[trpc\]\.(ts|tsx|js|jsx)$/i.test(filePath));
159
+ const routerFiles = findPrimaryImportFiles(context.paths, (filePath) => /src\/server\/routers\/.+\.(ts|tsx|js|jsx)$/i.test(filePath));
160
+ const trpcHandler = findPrimaryImportFiles(context.paths, (filePath) => /src\/pages\/api\/trpc\/\[trpc\]\.(ts|tsx|js|jsx)$/i.test(filePath));
161
161
  return {
162
162
  score: routerFiles.length > 0 && trpcHandler.length > 0 ? 88 : 0,
163
163
  reasons: routerFiles.length > 0 && trpcHandler.length > 0 ? ["Found tRPC router modules and Next.js tRPC handler"] : []
164
164
  };
165
165
  },
166
166
  extract(context) {
167
- const routerFiles = findImportFiles(context.paths, (filePath) => /src\/server\/routers\/.+\.(ts|tsx|js|jsx)$/i.test(filePath))
167
+ const routerFiles = findPrimaryImportFiles(context.paths, (filePath) => /src\/server\/routers\/.+\.(ts|tsx|js|jsx)$/i.test(filePath))
168
168
  .filter((filePath) => !/\/_app\.(ts|tsx|js|jsx)$/i.test(filePath) && !/\.test\./i.test(filePath));
169
169
  const procedures = routerFiles.flatMap((filePath) => parseRouterProcedures(filePath, context.helpers.readTextIfExists(filePath) || ""));
170
170
  const findings = [];
@@ -3,7 +3,7 @@
3
3
  import path from "node:path";
4
4
 
5
5
  import {
6
- findImportFiles,
6
+ findPrimaryImportFiles,
7
7
  idHintify,
8
8
  isPrimaryImportSource,
9
9
  makeCandidateRecord,
@@ -251,9 +251,9 @@ function inspectPackageCliMetadata(context, packageFiles) {
251
251
  * @returns {{ packageFiles: string[], sourceFiles: string[], binNames: Set<string>, findings: any[], provenance: string[] }}
252
252
  */
253
253
  function discoverCliSources(context) {
254
- const packageFiles = findImportFiles(context.paths, (/** @type {string} */ filePath) => /package\.json$/i.test(filePath));
254
+ const packageFiles = findPrimaryImportFiles(context.paths, (/** @type {string} */ filePath) => /package\.json$/i.test(filePath));
255
255
  const packageMetadata = inspectPackageCliMetadata(context, packageFiles);
256
- const sourceFiles = findImportFiles(context.paths, (/** @type {string} */ filePath) => {
256
+ const sourceFiles = findPrimaryImportFiles(context.paths, (/** @type {string} */ filePath) => {
257
257
  const normalized = normalizePath(filePath);
258
258
  if (!isAuthoritativeCliSource(context.paths, filePath)) {
259
259
  return false;
@@ -3,7 +3,7 @@ import path from "node:path";
3
3
  import {
4
4
  canonicalCandidateTerm,
5
5
  dedupeCandidateRecords,
6
- findImportFiles,
6
+ findPrimaryImportFiles,
7
7
  idHintify,
8
8
  makeCandidateRecord,
9
9
  relativeTo,
@@ -169,8 +169,8 @@ export const djangoModelsExtractor = {
169
169
  id: "db.django-models",
170
170
  track: "db",
171
171
  detect(context) {
172
- const modelFiles = findImportFiles(context.paths, (filePath) => /\/models\.py$/i.test(filePath));
173
- const manageFiles = findImportFiles(context.paths, (filePath) => /\/manage\.py$/i.test(filePath));
172
+ const modelFiles = findPrimaryImportFiles(context.paths, (filePath) => /\/models\.py$/i.test(filePath));
173
+ const manageFiles = findPrimaryImportFiles(context.paths, (filePath) => /\/manage\.py$/i.test(filePath));
174
174
  const score = modelFiles.length > 0 && manageFiles.length > 0 ? 91 : 0;
175
175
  return {
176
176
  score,
@@ -178,7 +178,7 @@ export const djangoModelsExtractor = {
178
178
  };
179
179
  },
180
180
  extract(context) {
181
- const modelFiles = findImportFiles(context.paths, (filePath) => /\/models\.py$/i.test(filePath));
181
+ const modelFiles = findPrimaryImportFiles(context.paths, (filePath) => /\/models\.py$/i.test(filePath));
182
182
  const findings = [];
183
183
  const candidates = { entities: [], enums: [], relations: [], indexes: [] };
184
184
 
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  canonicalCandidateTerm,
3
3
  dedupeCandidateRecords,
4
- findImportFiles,
4
+ findPrimaryImportFiles,
5
5
  idHintify,
6
6
  makeCandidateRecord,
7
7
  relativeTo,
@@ -61,8 +61,8 @@ export const dotnetModelsExtractor = {
61
61
  id: "db.dotnet-models",
62
62
  track: "db",
63
63
  detect(context) {
64
- const modelFiles = findImportFiles(context.paths, (filePath) => /\/Models\/.+\.cs$/i.test(filePath));
65
- const csprojFiles = findImportFiles(context.paths, (filePath) => /\.csproj$/i.test(filePath));
64
+ const modelFiles = findPrimaryImportFiles(context.paths, (filePath) => /\/Models\/.+\.cs$/i.test(filePath));
65
+ const csprojFiles = findPrimaryImportFiles(context.paths, (filePath) => /\.csproj$/i.test(filePath));
66
66
  const score = modelFiles.length > 0 && csprojFiles.length > 0 ? 78 : 0;
67
67
  return {
68
68
  score,
@@ -70,7 +70,7 @@ export const dotnetModelsExtractor = {
70
70
  };
71
71
  },
72
72
  extract(context) {
73
- const modelFiles = findImportFiles(context.paths, (filePath) => /\/Models\/.+\.cs$/i.test(filePath));
73
+ const modelFiles = findPrimaryImportFiles(context.paths, (filePath) => /\/Models\/.+\.cs$/i.test(filePath));
74
74
  const findings = [];
75
75
  const entities = [];
76
76
  for (const filePath of modelFiles) {
@@ -3,7 +3,7 @@ import path from "node:path";
3
3
  import {
4
4
  canonicalCandidateTerm,
5
5
  dedupeCandidateRecords,
6
- findImportFiles,
6
+ findPrimaryImportFiles,
7
7
  idHintify,
8
8
  isPrimaryImportSource,
9
9
  makeCandidateRecord,
@@ -168,7 +168,7 @@ function parseDrizzleTables(schemaText) {
168
168
  }
169
169
 
170
170
  function drizzleConfigFiles(context) {
171
- return findImportFiles(context.paths, (filePath) =>
171
+ return findPrimaryImportFiles(context.paths, (filePath) =>
172
172
  /drizzle\.config\.(ts|js|mjs|cjs)$/i.test(path.basename(filePath)) &&
173
173
  isPrimaryImportSource(context.paths, filePath)
174
174
  );
@@ -180,7 +180,10 @@ function configuredSchemaFiles(context, configFiles) {
180
180
  const configText = context.helpers.readTextIfExists(configFile) || "";
181
181
  for (const match of configText.matchAll(/\bschema\s*:\s*["'`]([^"'`*]+)["'`]/g)) {
182
182
  const absoluteSchemaPath = path.resolve(path.dirname(configFile), match[1]);
183
- if (context.helpers.readTextIfExists(absoluteSchemaPath) !== null) {
183
+ if (
184
+ context.helpers.readTextIfExists(absoluteSchemaPath) !== null &&
185
+ isPrimaryImportSource(context.paths, absoluteSchemaPath)
186
+ ) {
184
187
  files.push(absoluteSchemaPath);
185
188
  }
186
189
  }
@@ -195,7 +198,7 @@ function isDrizzleSchemaSource(context, filePath) {
195
198
 
196
199
  function findDrizzleSchemaFiles(context) {
197
200
  const configFiles = drizzleConfigFiles(context);
198
- const conventionalSchemaFiles = findImportFiles(context.paths, (filePath) =>
201
+ const conventionalSchemaFiles = findPrimaryImportFiles(context.paths, (filePath) =>
199
202
  /(?:^|\/)(?:src\/db\/schema|src\/schema|db\/schema|schema)\.(ts|js|mjs|cjs)$/i.test(relativeTo(context.paths.workspaceRoot, filePath).replaceAll(path.sep, "/")) &&
200
203
  isPrimaryImportSource(context.paths, filePath)
201
204
  );
@@ -209,11 +212,10 @@ export const drizzleExtractor = {
209
212
  id: "db.drizzle",
210
213
  track: "db",
211
214
  detect(context) {
212
- const hasConfig = drizzleConfigFiles(context).length > 0;
213
215
  const hasSchema = findDrizzleSchemaFiles(context).length > 0;
214
216
  return {
215
- score: hasConfig || hasSchema ? 95 : 0,
216
- reasons: hasConfig || hasSchema ? ["Found Drizzle config/schema source"] : []
217
+ score: hasSchema ? 95 : 0,
218
+ reasons: hasSchema ? ["Found Drizzle schema source"] : []
217
219
  };
218
220
  },
219
221
  extract(context) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  canonicalCandidateTerm,
3
3
  dedupeCandidateRecords,
4
- findImportFiles,
4
+ findPrimaryImportFiles,
5
5
  makeCandidateRecord,
6
6
  readTextIfExists,
7
7
  relativeTo,
@@ -155,8 +155,8 @@ export const efCoreExtractor = {
155
155
  id: "db.ef-core",
156
156
  track: "db",
157
157
  detect(context) {
158
- const csprojFiles = findImportFiles(context.paths, (filePath) => /\.csproj$/i.test(filePath));
159
- const dbContextFiles = findImportFiles(context.paths, (filePath) => /DbContext|Context\.cs$/i.test(filePath));
158
+ const csprojFiles = findPrimaryImportFiles(context.paths, (filePath) => /\.csproj$/i.test(filePath));
159
+ const dbContextFiles = findPrimaryImportFiles(context.paths, (filePath) => /DbContext|Context\.cs$/i.test(filePath));
160
160
  const score = csprojFiles.length > 0 && dbContextFiles.some((filePath) => /DbContext/.test(readTextIfExists(filePath) || "")) ? 89 : 0;
161
161
  return {
162
162
  score,
@@ -164,8 +164,8 @@ export const efCoreExtractor = {
164
164
  };
165
165
  },
166
166
  extract(context) {
167
- const dbContextFiles = findImportFiles(context.paths, (filePath) => /DbContext|Context\.cs$/i.test(filePath));
168
- const domainFiles = findImportFiles(context.paths, (filePath) => /\/Domain\/.+\.cs$/i.test(filePath));
167
+ const dbContextFiles = findPrimaryImportFiles(context.paths, (filePath) => /DbContext|Context\.cs$/i.test(filePath));
168
+ const domainFiles = findPrimaryImportFiles(context.paths, (filePath) => /\/Domain\/.+\.cs$/i.test(filePath));
169
169
  const findings = [];
170
170
  const candidates = { entities: [], enums: [], relations: [], indexes: [] };
171
171
 
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  canonicalCandidateTerm,
3
3
  dedupeCandidateRecords,
4
- findImportFiles,
4
+ findPrimaryImportFiles,
5
5
  idHintify,
6
6
  makeCandidateRecord,
7
7
  relativeTo,
@@ -82,7 +82,7 @@ export const flutterEntitiesExtractor = {
82
82
  id: "db.flutter-entities",
83
83
  track: "db",
84
84
  detect(context) {
85
- const entityFiles = findImportFiles(
85
+ const entityFiles = findPrimaryImportFiles(
86
86
  context.paths,
87
87
  (filePath) => /\/lib\/features\/.+\/domain\/entities\/.+_entity\.dart$/i.test(filePath)
88
88
  );
@@ -93,7 +93,7 @@ export const flutterEntitiesExtractor = {
93
93
  };
94
94
  },
95
95
  extract(context) {
96
- const entityFiles = findImportFiles(
96
+ const entityFiles = findPrimaryImportFiles(
97
97
  context.paths,
98
98
  (filePath) => /\/lib\/features\/.+\/domain\/entities\/.+_entity\.dart$/i.test(filePath)
99
99
  );
@@ -1,4 +1,4 @@
1
- import { canonicalCandidateTerm, dedupeCandidateRecords, findImportFiles, makeCandidateRecord, relativeTo, slugify, titleCase } from "../../core/shared.js";
1
+ import { canonicalCandidateTerm, dedupeCandidateRecords, findPrimaryImportFiles, makeCandidateRecord, relativeTo, slugify, titleCase } from "../../core/shared.js";
2
2
 
3
3
  function extractAnnotatedFields(text) {
4
4
  const fields = [];
@@ -44,7 +44,7 @@ export const jpaExtractor = {
44
44
  id: "db.jpa",
45
45
  track: "db",
46
46
  detect(context) {
47
- const entityFiles = findImportFiles(context.paths, (filePath) => /\.java$/i.test(filePath));
47
+ const entityFiles = findPrimaryImportFiles(context.paths, (filePath) => /\.java$/i.test(filePath));
48
48
  const count = entityFiles.filter((filePath) => /@Entity\b/.test(context.helpers.readTextIfExists(filePath) || "")).length;
49
49
  return {
50
50
  score: count > 0 ? 87 : 0,
@@ -52,7 +52,7 @@ export const jpaExtractor = {
52
52
  };
53
53
  },
54
54
  extract(context) {
55
- const files = findImportFiles(context.paths, (filePath) => /\.java$/i.test(filePath));
55
+ const files = findPrimaryImportFiles(context.paths, (filePath) => /\.java$/i.test(filePath));
56
56
  const findings = [];
57
57
  const candidates = { entities: [], enums: [], relations: [], indexes: [] };
58
58
 
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  canonicalCandidateTerm,
3
3
  dedupeCandidateRecords,
4
- findImportFiles,
4
+ findPrimaryImportFiles,
5
5
  idHintify,
6
6
  makeCandidateRecord,
7
7
  relativeTo,
@@ -109,14 +109,14 @@ export const liquibaseExtractor = {
109
109
  id: "db.liquibase",
110
110
  track: "db",
111
111
  detect(context) {
112
- const files = findImportFiles(context.paths, (filePath) => /db\/changelog\/.+\.(xml|ya?ml)$/i.test(filePath));
112
+ const files = findPrimaryImportFiles(context.paths, (filePath) => /db\/changelog\/.+\.(xml|ya?ml)$/i.test(filePath));
113
113
  return {
114
114
  score: files.length > 0 ? 88 : 0,
115
115
  reasons: files.length > 0 ? ["Found Liquibase changelog files"] : []
116
116
  };
117
117
  },
118
118
  extract(context) {
119
- const changelogFiles = findImportFiles(context.paths, (filePath) => /db\/changelog\/.+\.xml$/i.test(filePath));
119
+ const changelogFiles = findPrimaryImportFiles(context.paths, (filePath) => /db\/changelog\/.+\.xml$/i.test(filePath));
120
120
  const findings = [];
121
121
  const candidates = { entities: [], enums: [], relations: [], indexes: [] };
122
122
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  import path from "node:path";
4
4
 
5
- import { findImportFiles, isPrimaryImportSource, makeCandidateRecord, relativeTo } from "../../core/shared.js";
5
+ import { findPrimaryImportFiles, isPrimaryImportSource, makeCandidateRecord, relativeTo } from "../../core/shared.js";
6
6
 
7
7
  /** @param {string} value @returns {string} */
8
8
  function toPosix(value) {
@@ -139,7 +139,7 @@ export function inferPrismaMaintainedDbSeams(context, prismaFiles) {
139
139
  return [];
140
140
  }
141
141
  const schemaPath = appRelativePath(context, prismaFiles[0]);
142
- const migrationFiles = /** @type {string[]} */ (findImportFiles(context.paths, /** @param {string} filePath */ (filePath) =>
142
+ const migrationFiles = /** @type {string[]} */ (findPrimaryImportFiles(context.paths, /** @param {string} filePath */ (filePath) =>
143
143
  toPosix(filePath).includes("/prisma/migrations/") &&
144
144
  isPrimaryImportSource(context.paths, filePath)
145
145
  ));
@@ -167,11 +167,11 @@ export function inferDrizzleMaintainedDbSeams(context, schemaFiles) {
167
167
  if (!schemaFiles.length) {
168
168
  return [];
169
169
  }
170
- const configFiles = /** @type {string[]} */ (findImportFiles(context.paths, /** @param {string} filePath */ (filePath) =>
170
+ const configFiles = /** @type {string[]} */ (findPrimaryImportFiles(context.paths, /** @param {string} filePath */ (filePath) =>
171
171
  /drizzle\.config\.(ts|js|mjs|cjs)$/i.test(path.basename(filePath)) &&
172
172
  isPrimaryImportSource(context.paths, filePath)
173
173
  ));
174
- const drizzleFiles = /** @type {string[]} */ (findImportFiles(context.paths, /** @param {string} filePath */ (filePath) =>
174
+ const drizzleFiles = /** @type {string[]} */ (findPrimaryImportFiles(context.paths, /** @param {string} filePath */ (filePath) =>
175
175
  appRelativePath(context, filePath).startsWith("drizzle/") &&
176
176
  isPrimaryImportSource(context.paths, filePath)
177
177
  ));
@@ -1,4 +1,4 @@
1
- import { dedupeCandidateRecords, findImportFiles, makeCandidateRecord, relativeTo, selectPreferredImportFiles, slugify, titleCase, idHintify, canonicalCandidateTerm } from "../../core/shared.js";
1
+ import { dedupeCandidateRecords, findPrimaryImportFiles, makeCandidateRecord, relativeTo, selectPreferredImportFiles, slugify, titleCase, idHintify, canonicalCandidateTerm } from "../../core/shared.js";
2
2
  import { parseSqlSchema } from "./sql.js";
3
3
 
4
4
  function classifyNoiseEntity(tableName, fields) {
@@ -36,15 +36,15 @@ export const myBatisXmlExtractor = {
36
36
  id: "db.mybatis-xml",
37
37
  track: "db",
38
38
  detect(context) {
39
- const mapperFiles = findImportFiles(context.paths, (filePath) => /\/mapper\/.+\.xml$/i.test(filePath));
39
+ const mapperFiles = findPrimaryImportFiles(context.paths, (filePath) => /\/mapper\/.+\.xml$/i.test(filePath));
40
40
  return {
41
41
  score: mapperFiles.length > 0 ? 86 : 0,
42
42
  reasons: mapperFiles.length > 0 ? ["Found MyBatis mapper XML files"] : []
43
43
  };
44
44
  },
45
45
  extract(context) {
46
- const mapperFiles = findImportFiles(context.paths, (filePath) => /\/mapper\/.+\.xml$/i.test(filePath));
47
- const allSqlFiles = findImportFiles(context.paths, (filePath) => filePath.endsWith(".sql"));
46
+ const mapperFiles = findPrimaryImportFiles(context.paths, (filePath) => /\/mapper\/.+\.xml$/i.test(filePath));
47
+ const allSqlFiles = findPrimaryImportFiles(context.paths, (filePath) => filePath.endsWith(".sql"));
48
48
  const schemaSqlFiles = allSqlFiles.filter((filePath) => !/\/src\/test\//i.test(filePath));
49
49
  const sqlFiles = selectPreferredImportFiles(context.paths, schemaSqlFiles, "sql");
50
50
  const findings = [];
@@ -1,5 +1,5 @@
1
1
  import {
2
- findImportFiles,
2
+ findPrimaryImportFiles,
3
3
  isPrimaryImportSource,
4
4
  makeCandidateRecord,
5
5
  normalizePrismaType,
@@ -114,7 +114,7 @@ export const prismaExtractor = {
114
114
  id: "db.prisma",
115
115
  track: "db",
116
116
  detect(context) {
117
- const files = findImportFiles(context.paths, (filePath) =>
117
+ const files = findPrimaryImportFiles(context.paths, (filePath) =>
118
118
  (filePath.endsWith("/prisma/schema.prisma") || filePath.endsWith("prisma/schema.prisma")) &&
119
119
  isPrimaryImportSource(context.paths, filePath)
120
120
  );
@@ -126,7 +126,7 @@ export const prismaExtractor = {
126
126
  extract(context) {
127
127
  const prismaFiles = selectPreferredImportFiles(
128
128
  context.paths,
129
- findImportFiles(context.paths, (filePath) =>
129
+ findPrimaryImportFiles(context.paths, (filePath) =>
130
130
  (filePath.endsWith("/prisma/schema.prisma") || filePath.endsWith("prisma/schema.prisma")) &&
131
131
  isPrimaryImportSource(context.paths, filePath)
132
132
  ),
@@ -3,7 +3,7 @@ import path from "node:path";
3
3
  import {
4
4
  canonicalCandidateTerm,
5
5
  dedupeCandidateRecords,
6
- findImportFiles,
6
+ findPrimaryImportFiles,
7
7
  idHintify,
8
8
  makeCandidateRecord,
9
9
  relativeTo,
@@ -107,14 +107,14 @@ export const railsSchemaExtractor = {
107
107
  id: "db.rails-schema",
108
108
  track: "db",
109
109
  detect(context) {
110
- const schemaFiles = findImportFiles(context.paths, (filePath) => /db\/schema\.rb$/i.test(filePath));
110
+ const schemaFiles = findPrimaryImportFiles(context.paths, (filePath) => /db\/schema\.rb$/i.test(filePath));
111
111
  return {
112
112
  score: schemaFiles.length > 0 ? 92 : 0,
113
113
  reasons: schemaFiles.length > 0 ? ["Found Rails schema.rb"] : []
114
114
  };
115
115
  },
116
116
  extract(context) {
117
- const schemaFiles = findImportFiles(context.paths, (filePath) => /db\/schema\.rb$/i.test(filePath));
117
+ const schemaFiles = findPrimaryImportFiles(context.paths, (filePath) => /db\/schema\.rb$/i.test(filePath));
118
118
  const findings = [];
119
119
  const candidates = { entities: [], enums: [], relations: [], indexes: [] };
120
120
 
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  canonicalCandidateTerm,
3
3
  dedupeCandidateRecords,
4
- findImportFiles,
4
+ findPrimaryImportFiles,
5
5
  idHintify,
6
6
  makeCandidateRecord,
7
7
  relativeTo,
@@ -60,7 +60,7 @@ export const reactNativeEntitiesExtractor = {
60
60
  id: "db.react-native-entities",
61
61
  track: "db",
62
62
  detect(context) {
63
- const entityFiles = findImportFiles(
63
+ const entityFiles = findPrimaryImportFiles(
64
64
  context.paths,
65
65
  (filePath) => /\/src\/.+\/domain\/entities\/.+Entity\.ts$/i.test(filePath)
66
66
  );
@@ -71,7 +71,7 @@ export const reactNativeEntitiesExtractor = {
71
71
  };
72
72
  },
73
73
  extract(context) {
74
- const entityFiles = findImportFiles(
74
+ const entityFiles = findPrimaryImportFiles(
75
75
  context.paths,
76
76
  (filePath) => /\/src\/.+\/domain\/entities\/.+Entity\.ts$/i.test(filePath)
77
77
  );