@query-doctor/core 0.10.7 → 0.10.8

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/dist/index.cjs CHANGED
@@ -4,6 +4,7 @@ const require_pg_identifier = require("./sql/pg-identifier.cjs");
4
4
  const require_schema = require("./schema.cjs");
5
5
  const require_nudges = require("./sql/nudges.cjs");
6
6
  const require_analyzer = require("./sql/analyzer.cjs");
7
+ const require_test_origin = require("./sql/test-origin.cjs");
7
8
  const require_database = require("./sql/database.cjs");
8
9
  const require_display_query = require("./sql/display-query.cjs");
9
10
  const require_normalized_fingerprint = require("./sql/normalized-fingerprint.cjs");
@@ -73,5 +74,7 @@ exports.ignoredIdentifier = require_analyzer.ignoredIdentifier;
73
74
  exports.indexCovers = require_index_coverage.indexCovers;
74
75
  exports.isIndexProbablyDroppable = require_indexes.isIndexProbablyDroppable;
75
76
  exports.isIndexSupported = require_indexes.isIndexSupported;
77
+ exports.isTestFilePath = require_test_origin.isTestFilePath;
78
+ exports.isTestOriginQuery = require_test_origin.isTestOriginQuery;
76
79
  exports.normalizedFingerprint = require_normalized_fingerprint.normalizedFingerprint;
77
80
  exports.parseNudges = require_nudges.parseNudges;
package/dist/index.d.cts CHANGED
@@ -8,6 +8,7 @@ import { ColumnMetadata, ComputedColumnStats, ComputedReltuples, ComputedStats,
8
8
  import { IndexIdentifier, IndexOptimizer, IndexToCreate, OptimizeResult, PROCEED, PermutedIndexCandidate, RootIndexCandidate, SKIP } from "./optimizer/genalgo.cjs";
9
9
  import { Nudge, parseNudges } from "./sql/nudges.cjs";
10
10
  import { AnalysisResult, Analyzer, DatabaseDriver, DiscoveredColumnReference, JsonbOperator, Parser, SQLCommenterExtraction, SQLCommenterTag, SortContext, StatementType, TableReference, ignoredIdentifier } from "./sql/analyzer.cjs";
11
+ import { isTestFilePath, isTestOriginQuery } from "./sql/test-origin.cjs";
11
12
  import { CompactSelectListOptions, compactSelectList } from "./sql/display-query.cjs";
12
13
  import { FingerprintFn, normalizedFingerprint } from "./sql/normalized-fingerprint.cjs";
13
14
  import { DuplicateIndexGroup, groupDuplicateIndexes, isIndexProbablyDroppable, isIndexSupported } from "./sql/indexes.cjs";
@@ -20,4 +21,4 @@ import { ActionPlanNudgeQuery, ActionableStep, AffectedQueryCost, CostReduction,
20
21
  import { deriveSentryEnvironment } from "./sentry.cjs";
21
22
  import { ClientApi, ConnectionMode, ExtensionPresence, IndexDefinition, RepoConfig, ServerApi, UnauthenticatedServerApi } from "./websocket-server.cjs";
22
23
  import { QueryFinding, QueryFindingCode, QueryFindingSeverity, analyzeQueryFindings } from "./findings/query-findings.cjs";
23
- export { ActionPlanNudgeQuery, ActionPlanQuery, ActionableStep, AffectedQueryCost, AggregatedIndexRecommendation, AnalysisResult, Analyzer, ClientApi, ColumnMetadata, CombinedExport, CompactSelectListOptions, ComputedColumnStats, ComputedReltuples, ComputedStats, ConnectionMode, CostReduction, DUMP_STATS_SQL, DatabaseDriver, DiscoveredColumnReference, DomainLabel, DuplicateIndexGroup, ExportedQuery, ExportedStats, ExportedStatsColumns, ExportedStatsIndex, ExportedStatsStatistics, ExportedStatsV1, ExtensionPresence, FingerprintFn, FullSchema, FullSchemaColumn, FullSchemaCompositeAttribute, FullSchemaConstraint, FullSchemaExtension, FullSchemaFunction, FullSchemaIncludedColumn, FullSchemaIndex, FullSchemaKeyColumn, FullSchemaTable, FullSchemaTrigger, FullSchemaType, FullSchemaTypeConstraint, FullSchemaView, IndexAction, IndexDefinition, IndexGroup, IndexIdentifier, IndexOptimizer, IndexRecommendation, IndexToCreate, JsonbOperator, LiveQueryOptimization, Nudge, NudgeFinding, OptimizationResult, OptimizeResult, OptimizedQuery, PROCEED, Parameter, Parser, Path, PermutedIndexCandidate, PgIdentifier, Postgres, PostgresConnectionInput, PostgresExplainResult, PostgresExplainStage, PostgresExplainStageCommon, PostgresExplainStageSchema, PostgresFactory, PostgresQueryBuilder, PostgresQueryBuilderCommand, PostgresStage, PostgresStageId, PostgresTransaction, PostgresVersion, PssRewriter, QueryFinding, QueryFindingCode, QueryFindingSeverity, QueryHash, QuerySource, RecentQuery, RegressionBreach, RepoConfig, RootIndexCandidate, SKIP, SQLCommenterExtraction, SQLCommenterTag, SerializeResult, ServerApi, SortContext, StatementType, Statistics, StatisticsMode, StatisticsSource, TableMetadata, TableReference, TableStats, UnauthenticatedServerApi, aggregateIndexRecommendations, analyzeQueryFindings, buildActionPlan, combinedDumpSql, compactSelectList, deriveSentryEnvironment, dropIndex, dumpQueriesSql, dumpSchema, groupDuplicateIndexes, groupIndexesByCoverage, ignoredIdentifier, indexCovers, isIndexProbablyDroppable, isIndexSupported, normalizedFingerprint, parseNudges };
24
+ export { ActionPlanNudgeQuery, ActionPlanQuery, ActionableStep, AffectedQueryCost, AggregatedIndexRecommendation, AnalysisResult, Analyzer, ClientApi, ColumnMetadata, CombinedExport, CompactSelectListOptions, ComputedColumnStats, ComputedReltuples, ComputedStats, ConnectionMode, CostReduction, DUMP_STATS_SQL, DatabaseDriver, DiscoveredColumnReference, DomainLabel, DuplicateIndexGroup, ExportedQuery, ExportedStats, ExportedStatsColumns, ExportedStatsIndex, ExportedStatsStatistics, ExportedStatsV1, ExtensionPresence, FingerprintFn, FullSchema, FullSchemaColumn, FullSchemaCompositeAttribute, FullSchemaConstraint, FullSchemaExtension, FullSchemaFunction, FullSchemaIncludedColumn, FullSchemaIndex, FullSchemaKeyColumn, FullSchemaTable, FullSchemaTrigger, FullSchemaType, FullSchemaTypeConstraint, FullSchemaView, IndexAction, IndexDefinition, IndexGroup, IndexIdentifier, IndexOptimizer, IndexRecommendation, IndexToCreate, JsonbOperator, LiveQueryOptimization, Nudge, NudgeFinding, OptimizationResult, OptimizeResult, OptimizedQuery, PROCEED, Parameter, Parser, Path, PermutedIndexCandidate, PgIdentifier, Postgres, PostgresConnectionInput, PostgresExplainResult, PostgresExplainStage, PostgresExplainStageCommon, PostgresExplainStageSchema, PostgresFactory, PostgresQueryBuilder, PostgresQueryBuilderCommand, PostgresStage, PostgresStageId, PostgresTransaction, PostgresVersion, PssRewriter, QueryFinding, QueryFindingCode, QueryFindingSeverity, QueryHash, QuerySource, RecentQuery, RegressionBreach, RepoConfig, RootIndexCandidate, SKIP, SQLCommenterExtraction, SQLCommenterTag, SerializeResult, ServerApi, SortContext, StatementType, Statistics, StatisticsMode, StatisticsSource, TableMetadata, TableReference, TableStats, UnauthenticatedServerApi, aggregateIndexRecommendations, analyzeQueryFindings, buildActionPlan, combinedDumpSql, compactSelectList, deriveSentryEnvironment, dropIndex, dumpQueriesSql, dumpSchema, groupDuplicateIndexes, groupIndexesByCoverage, ignoredIdentifier, indexCovers, isIndexProbablyDroppable, isIndexSupported, isTestFilePath, isTestOriginQuery, normalizedFingerprint, parseNudges };
package/dist/index.d.mts CHANGED
@@ -8,6 +8,7 @@ import { ColumnMetadata, ComputedColumnStats, ComputedReltuples, ComputedStats,
8
8
  import { IndexIdentifier, IndexOptimizer, IndexToCreate, OptimizeResult, PROCEED, PermutedIndexCandidate, RootIndexCandidate, SKIP } from "./optimizer/genalgo.mjs";
9
9
  import { Nudge, parseNudges } from "./sql/nudges.mjs";
10
10
  import { AnalysisResult, Analyzer, DatabaseDriver, DiscoveredColumnReference, JsonbOperator, Parser, SQLCommenterExtraction, SQLCommenterTag, SortContext, StatementType, TableReference, ignoredIdentifier } from "./sql/analyzer.mjs";
11
+ import { isTestFilePath, isTestOriginQuery } from "./sql/test-origin.mjs";
11
12
  import { CompactSelectListOptions, compactSelectList } from "./sql/display-query.mjs";
12
13
  import { FingerprintFn, normalizedFingerprint } from "./sql/normalized-fingerprint.mjs";
13
14
  import { DuplicateIndexGroup, groupDuplicateIndexes, isIndexProbablyDroppable, isIndexSupported } from "./sql/indexes.mjs";
@@ -20,4 +21,4 @@ import { ActionPlanNudgeQuery, ActionableStep, AffectedQueryCost, CostReduction,
20
21
  import { deriveSentryEnvironment } from "./sentry.mjs";
21
22
  import { ClientApi, ConnectionMode, ExtensionPresence, IndexDefinition, RepoConfig, ServerApi, UnauthenticatedServerApi } from "./websocket-server.mjs";
22
23
  import { QueryFinding, QueryFindingCode, QueryFindingSeverity, analyzeQueryFindings } from "./findings/query-findings.mjs";
23
- export { ActionPlanNudgeQuery, ActionPlanQuery, ActionableStep, AffectedQueryCost, AggregatedIndexRecommendation, AnalysisResult, Analyzer, ClientApi, ColumnMetadata, CombinedExport, CompactSelectListOptions, ComputedColumnStats, ComputedReltuples, ComputedStats, ConnectionMode, CostReduction, DUMP_STATS_SQL, DatabaseDriver, DiscoveredColumnReference, DomainLabel, DuplicateIndexGroup, ExportedQuery, ExportedStats, ExportedStatsColumns, ExportedStatsIndex, ExportedStatsStatistics, ExportedStatsV1, ExtensionPresence, FingerprintFn, FullSchema, FullSchemaColumn, FullSchemaCompositeAttribute, FullSchemaConstraint, FullSchemaExtension, FullSchemaFunction, FullSchemaIncludedColumn, FullSchemaIndex, FullSchemaKeyColumn, FullSchemaTable, FullSchemaTrigger, FullSchemaType, FullSchemaTypeConstraint, FullSchemaView, IndexAction, IndexDefinition, IndexGroup, IndexIdentifier, IndexOptimizer, IndexRecommendation, IndexToCreate, JsonbOperator, LiveQueryOptimization, Nudge, NudgeFinding, OptimizationResult, OptimizeResult, OptimizedQuery, PROCEED, Parameter, Parser, Path, PermutedIndexCandidate, PgIdentifier, Postgres, PostgresConnectionInput, PostgresExplainResult, PostgresExplainStage, PostgresExplainStageCommon, PostgresExplainStageSchema, PostgresFactory, PostgresQueryBuilder, PostgresQueryBuilderCommand, PostgresStage, PostgresStageId, PostgresTransaction, PostgresVersion, PssRewriter, QueryFinding, QueryFindingCode, QueryFindingSeverity, QueryHash, QuerySource, RecentQuery, RegressionBreach, RepoConfig, RootIndexCandidate, SKIP, SQLCommenterExtraction, SQLCommenterTag, SerializeResult, ServerApi, SortContext, StatementType, Statistics, StatisticsMode, StatisticsSource, TableMetadata, TableReference, TableStats, UnauthenticatedServerApi, aggregateIndexRecommendations, analyzeQueryFindings, buildActionPlan, combinedDumpSql, compactSelectList, deriveSentryEnvironment, dropIndex, dumpQueriesSql, dumpSchema, groupDuplicateIndexes, groupIndexesByCoverage, ignoredIdentifier, indexCovers, isIndexProbablyDroppable, isIndexSupported, normalizedFingerprint, parseNudges };
24
+ export { ActionPlanNudgeQuery, ActionPlanQuery, ActionableStep, AffectedQueryCost, AggregatedIndexRecommendation, AnalysisResult, Analyzer, ClientApi, ColumnMetadata, CombinedExport, CompactSelectListOptions, ComputedColumnStats, ComputedReltuples, ComputedStats, ConnectionMode, CostReduction, DUMP_STATS_SQL, DatabaseDriver, DiscoveredColumnReference, DomainLabel, DuplicateIndexGroup, ExportedQuery, ExportedStats, ExportedStatsColumns, ExportedStatsIndex, ExportedStatsStatistics, ExportedStatsV1, ExtensionPresence, FingerprintFn, FullSchema, FullSchemaColumn, FullSchemaCompositeAttribute, FullSchemaConstraint, FullSchemaExtension, FullSchemaFunction, FullSchemaIncludedColumn, FullSchemaIndex, FullSchemaKeyColumn, FullSchemaTable, FullSchemaTrigger, FullSchemaType, FullSchemaTypeConstraint, FullSchemaView, IndexAction, IndexDefinition, IndexGroup, IndexIdentifier, IndexOptimizer, IndexRecommendation, IndexToCreate, JsonbOperator, LiveQueryOptimization, Nudge, NudgeFinding, OptimizationResult, OptimizeResult, OptimizedQuery, PROCEED, Parameter, Parser, Path, PermutedIndexCandidate, PgIdentifier, Postgres, PostgresConnectionInput, PostgresExplainResult, PostgresExplainStage, PostgresExplainStageCommon, PostgresExplainStageSchema, PostgresFactory, PostgresQueryBuilder, PostgresQueryBuilderCommand, PostgresStage, PostgresStageId, PostgresTransaction, PostgresVersion, PssRewriter, QueryFinding, QueryFindingCode, QueryFindingSeverity, QueryHash, QuerySource, RecentQuery, RegressionBreach, RepoConfig, RootIndexCandidate, SKIP, SQLCommenterExtraction, SQLCommenterTag, SerializeResult, ServerApi, SortContext, StatementType, Statistics, StatisticsMode, StatisticsSource, TableMetadata, TableReference, TableStats, UnauthenticatedServerApi, aggregateIndexRecommendations, analyzeQueryFindings, buildActionPlan, combinedDumpSql, compactSelectList, deriveSentryEnvironment, dropIndex, dumpQueriesSql, dumpSchema, groupDuplicateIndexes, groupIndexesByCoverage, ignoredIdentifier, indexCovers, isIndexProbablyDroppable, isIndexSupported, isTestFilePath, isTestOriginQuery, normalizedFingerprint, parseNudges };
package/dist/index.mjs CHANGED
@@ -3,6 +3,7 @@ import { PgIdentifier } from "./sql/pg-identifier.mjs";
3
3
  import { FullSchema, FullSchemaColumn, FullSchemaCompositeAttribute, FullSchemaConstraint, FullSchemaExtension, FullSchemaFunction, FullSchemaIncludedColumn, FullSchemaIndex, FullSchemaKeyColumn, FullSchemaTable, FullSchemaTrigger, FullSchemaType, FullSchemaTypeConstraint, FullSchemaView, dumpSchema } from "./schema.mjs";
4
4
  import { parseNudges } from "./sql/nudges.mjs";
5
5
  import { Analyzer, ignoredIdentifier } from "./sql/analyzer.mjs";
6
+ import { isTestFilePath, isTestOriginQuery } from "./sql/test-origin.mjs";
6
7
  import { PostgresExplainStageSchema, PostgresVersion, dropIndex } from "./sql/database.mjs";
7
8
  import { compactSelectList } from "./sql/display-query.mjs";
8
9
  import { normalizedFingerprint } from "./sql/normalized-fingerprint.mjs";
@@ -18,4 +19,4 @@ import { buildActionPlan } from "./action-plan/build-action-plan.mjs";
18
19
  import { deriveSentryEnvironment } from "./sentry.mjs";
19
20
  import { OptimizedQuery, RecentQuery } from "./query.mjs";
20
21
  import { analyzeQueryFindings } from "./findings/query-findings.mjs";
21
- export { Analyzer, CombinedExport, ComputedColumnStats, ComputedReltuples, ComputedStats, DUMP_STATS_SQL, ExportedQuery, ExportedStats, ExportedStatsColumns, ExportedStatsIndex, ExportedStatsStatistics, ExportedStatsV1, FullSchema, FullSchemaColumn, FullSchemaCompositeAttribute, FullSchemaConstraint, FullSchemaExtension, FullSchemaFunction, FullSchemaIncludedColumn, FullSchemaIndex, FullSchemaKeyColumn, FullSchemaTable, FullSchemaTrigger, FullSchemaType, FullSchemaTypeConstraint, FullSchemaView, IndexOptimizer, OptimizedQuery, PROCEED, PgIdentifier, PostgresExplainStageSchema, PostgresQueryBuilder, PostgresVersion, PssRewriter, RecentQuery, SKIP, Statistics, StatisticsMode, StatisticsSource, aggregateIndexRecommendations, analyzeQueryFindings, buildActionPlan, combinedDumpSql, compactSelectList, deriveSentryEnvironment, dropIndex, dumpQueriesSql, dumpSchema, groupDuplicateIndexes, groupIndexesByCoverage, ignoredIdentifier, indexCovers, isIndexProbablyDroppable, isIndexSupported, normalizedFingerprint, parseNudges };
22
+ export { Analyzer, CombinedExport, ComputedColumnStats, ComputedReltuples, ComputedStats, DUMP_STATS_SQL, ExportedQuery, ExportedStats, ExportedStatsColumns, ExportedStatsIndex, ExportedStatsStatistics, ExportedStatsV1, FullSchema, FullSchemaColumn, FullSchemaCompositeAttribute, FullSchemaConstraint, FullSchemaExtension, FullSchemaFunction, FullSchemaIncludedColumn, FullSchemaIndex, FullSchemaKeyColumn, FullSchemaTable, FullSchemaTrigger, FullSchemaType, FullSchemaTypeConstraint, FullSchemaView, IndexOptimizer, OptimizedQuery, PROCEED, PgIdentifier, PostgresExplainStageSchema, PostgresQueryBuilder, PostgresVersion, PssRewriter, RecentQuery, SKIP, Statistics, StatisticsMode, StatisticsSource, aggregateIndexRecommendations, analyzeQueryFindings, buildActionPlan, combinedDumpSql, compactSelectList, deriveSentryEnvironment, dropIndex, dumpQueriesSql, dumpSchema, groupDuplicateIndexes, groupIndexesByCoverage, ignoredIdentifier, indexCovers, isIndexProbablyDroppable, isIndexSupported, isTestFilePath, isTestOriginQuery, normalizedFingerprint, parseNudges };
@@ -0,0 +1,52 @@
1
+ "use client";
2
+ //#region src/sql/test-origin.ts
3
+ /**
4
+ * Whether a query originated from a test file, decided from its SQLCommenter
5
+ * `file` tag.
6
+ *
7
+ * The CI gate should never flag a query that no production route runs — e.g. a
8
+ * read-back assertion in `tests/pg/postgres.test.ts` — yet before this such
9
+ * queries had to be ignored one hash at a time (#3199). SQLCommenter already
10
+ * carries the caller's file (surfaced in query detail per #2585); this reads it
11
+ * so both the analyzer's gate and the server's alert engine can bucket
12
+ * test-origin queries out with a single shared rule instead of drifting apart.
13
+ *
14
+ * Conservative by construction: the decision keys only off the `file` tag's
15
+ * origin path. A query with no `file` tag is never test-origin, so untagged
16
+ * codebases behave exactly as before.
17
+ */
18
+ function isTestOriginQuery(tags) {
19
+ if (!tags) return false;
20
+ for (const tag of tags) {
21
+ if (tag.key !== "file") continue;
22
+ const originFile = tag.value.split(";")[0]?.trim();
23
+ if (originFile && isTestFilePath(originFile)) return true;
24
+ }
25
+ return false;
26
+ }
27
+ /**
28
+ * Whether a source path looks like a test file. Query Doctor analyzes clients in
29
+ * any language, so this spans the common cross-language conventions rather than
30
+ * assuming JS/TS — directory-scoped (`tests/`, `__tests__/`, `spec/`, `e2e/`,
31
+ * Maven's `src/test/`) and filename-scoped (`*.test.*` / `*.spec.*`, Python
32
+ * `test_*.py` / `*_test.py`, Go `*_test.go`, Ruby `*_test.rb` / `*_spec.rb`,
33
+ * Java `*Test.java`). Anchored on path separators so `testimonials/user.ts` or
34
+ * `latest/report.py` don't get mistaken for tests.
35
+ */
36
+ function isTestFilePath(path) {
37
+ return TEST_PATH_PATTERNS.some((pattern) => pattern.test(path));
38
+ }
39
+ const TEST_PATH_PATTERNS = [
40
+ /(?:^|\/)(?:tests?|__tests__|specs?|e2e)\//i,
41
+ /(?:^|\/)src\/test\//i,
42
+ /\.(?:test|spec|e2e)\.[cm]?[jt]sx?$/i,
43
+ /(?:^|\/)(?:test_[^/]+|[^/]+_test|conftest)\.py$/i,
44
+ /_test\.go$/i,
45
+ /_(?:test|spec)\.rb$/i,
46
+ /Tests?\.(?:java|kt)$/
47
+ ];
48
+ //#endregion
49
+ exports.isTestFilePath = isTestFilePath;
50
+ exports.isTestOriginQuery = isTestOriginQuery;
51
+
52
+ //# sourceMappingURL=test-origin.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-origin.cjs","names":[],"sources":["../../src/sql/test-origin.ts"],"sourcesContent":["import type { SQLCommenterTag } from \"./analyzer.js\";\n\n/**\n * Whether a query originated from a test file, decided from its SQLCommenter\n * `file` tag.\n *\n * The CI gate should never flag a query that no production route runs — e.g. a\n * read-back assertion in `tests/pg/postgres.test.ts` — yet before this such\n * queries had to be ignored one hash at a time (#3199). SQLCommenter already\n * carries the caller's file (surfaced in query detail per #2585); this reads it\n * so both the analyzer's gate and the server's alert engine can bucket\n * test-origin queries out with a single shared rule instead of drifting apart.\n *\n * Conservative by construction: the decision keys only off the `file` tag's\n * origin path. A query with no `file` tag is never test-origin, so untagged\n * codebases behave exactly as before.\n */\nexport function isTestOriginQuery(\n tags: readonly SQLCommenterTag[] | undefined | null,\n): boolean {\n if (!tags) return false;\n for (const tag of tags) {\n if (tag.key !== \"file\") continue;\n // SQLCommenter can pack a caller stack into one `file` value, `;`-separated\n // and most-specific-first (the frontend renders `files[0]` as the origin).\n // The first entry is the query's own call site, so it decides origin — a\n // production query that merely threads through a test helper deeper in the\n // stack stays gated.\n const originFile = tag.value.split(\";\")[0]?.trim();\n if (originFile && isTestFilePath(originFile)) return true;\n }\n return false;\n}\n\n/**\n * Whether a source path looks like a test file. Query Doctor analyzes clients in\n * any language, so this spans the common cross-language conventions rather than\n * assuming JS/TS — directory-scoped (`tests/`, `__tests__/`, `spec/`, `e2e/`,\n * Maven's `src/test/`) and filename-scoped (`*.test.*` / `*.spec.*`, Python\n * `test_*.py` / `*_test.py`, Go `*_test.go`, Ruby `*_test.rb` / `*_spec.rb`,\n * Java `*Test.java`). Anchored on path separators so `testimonials/user.ts` or\n * `latest/report.py` don't get mistaken for tests.\n */\nexport function isTestFilePath(path: string): boolean {\n return TEST_PATH_PATTERNS.some((pattern) => pattern.test(path));\n}\n\nconst TEST_PATH_PATTERNS: readonly RegExp[] = [\n // A directory segment dedicated to tests, anywhere in the path.\n /(?:^|\\/)(?:tests?|__tests__|specs?|e2e)\\//i,\n // Maven/Gradle layout: src/test/java/...\n /(?:^|\\/)src\\/test\\//i,\n // JS/TS: foo.test.ts, foo.spec.tsx, foo.e2e.mts\n /\\.(?:test|spec|e2e)\\.[cm]?[jt]sx?$/i,\n // Python: test_foo.py, foo_test.py, conftest.py\n /(?:^|\\/)(?:test_[^/]+|[^/]+_test|conftest)\\.py$/i,\n // Go: foo_test.go\n /_test\\.go$/i,\n // Ruby: foo_test.rb, foo_spec.rb\n /_(?:test|spec)\\.rb$/i,\n // Java/Kotlin: FooTest.java, FooTests.kt\n /Tests?\\.(?:java|kt)$/,\n];\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,SAAgB,kBACd,MACS;AACT,KAAI,CAAC,KAAM,QAAO;AAClB,MAAK,MAAM,OAAO,MAAM;AACtB,MAAI,IAAI,QAAQ,OAAQ;EAMxB,MAAM,aAAa,IAAI,MAAM,MAAM,IAAI,CAAC,IAAI,MAAM;AAClD,MAAI,cAAc,eAAe,WAAW,CAAE,QAAO;;AAEvD,QAAO;;;;;;;;;;;AAYT,SAAgB,eAAe,MAAuB;AACpD,QAAO,mBAAmB,MAAM,YAAY,QAAQ,KAAK,KAAK,CAAC;;AAGjE,MAAM,qBAAwC;CAE5C;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CACD"}
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+
3
+ import { SQLCommenterTag } from "./analyzer.cjs";
4
+
5
+ //#region src/sql/test-origin.d.ts
6
+ /**
7
+ * Whether a query originated from a test file, decided from its SQLCommenter
8
+ * `file` tag.
9
+ *
10
+ * The CI gate should never flag a query that no production route runs — e.g. a
11
+ * read-back assertion in `tests/pg/postgres.test.ts` — yet before this such
12
+ * queries had to be ignored one hash at a time (#3199). SQLCommenter already
13
+ * carries the caller's file (surfaced in query detail per #2585); this reads it
14
+ * so both the analyzer's gate and the server's alert engine can bucket
15
+ * test-origin queries out with a single shared rule instead of drifting apart.
16
+ *
17
+ * Conservative by construction: the decision keys only off the `file` tag's
18
+ * origin path. A query with no `file` tag is never test-origin, so untagged
19
+ * codebases behave exactly as before.
20
+ */
21
+ declare function isTestOriginQuery(tags: readonly SQLCommenterTag[] | undefined | null): boolean;
22
+ /**
23
+ * Whether a source path looks like a test file. Query Doctor analyzes clients in
24
+ * any language, so this spans the common cross-language conventions rather than
25
+ * assuming JS/TS — directory-scoped (`tests/`, `__tests__/`, `spec/`, `e2e/`,
26
+ * Maven's `src/test/`) and filename-scoped (`*.test.*` / `*.spec.*`, Python
27
+ * `test_*.py` / `*_test.py`, Go `*_test.go`, Ruby `*_test.rb` / `*_spec.rb`,
28
+ * Java `*Test.java`). Anchored on path separators so `testimonials/user.ts` or
29
+ * `latest/report.py` don't get mistaken for tests.
30
+ */
31
+ declare function isTestFilePath(path: string): boolean;
32
+ //#endregion
33
+ export { isTestFilePath, isTestOriginQuery };
34
+ //# sourceMappingURL=test-origin.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-origin.d.cts","names":[],"sources":["../../src/sql/test-origin.ts"],"mappings":";;;;;;;;AAiBA;;;;;AA0BA;;;;;;;iBA1BgB,iBAAA,CACd,IAAA,WAAe,eAAA;;;;;;;;;;iBAyBD,cAAA,CAAe,IAAA"}
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+
3
+ import { SQLCommenterTag } from "./analyzer.mjs";
4
+
5
+ //#region src/sql/test-origin.d.ts
6
+ /**
7
+ * Whether a query originated from a test file, decided from its SQLCommenter
8
+ * `file` tag.
9
+ *
10
+ * The CI gate should never flag a query that no production route runs — e.g. a
11
+ * read-back assertion in `tests/pg/postgres.test.ts` — yet before this such
12
+ * queries had to be ignored one hash at a time (#3199). SQLCommenter already
13
+ * carries the caller's file (surfaced in query detail per #2585); this reads it
14
+ * so both the analyzer's gate and the server's alert engine can bucket
15
+ * test-origin queries out with a single shared rule instead of drifting apart.
16
+ *
17
+ * Conservative by construction: the decision keys only off the `file` tag's
18
+ * origin path. A query with no `file` tag is never test-origin, so untagged
19
+ * codebases behave exactly as before.
20
+ */
21
+ declare function isTestOriginQuery(tags: readonly SQLCommenterTag[] | undefined | null): boolean;
22
+ /**
23
+ * Whether a source path looks like a test file. Query Doctor analyzes clients in
24
+ * any language, so this spans the common cross-language conventions rather than
25
+ * assuming JS/TS — directory-scoped (`tests/`, `__tests__/`, `spec/`, `e2e/`,
26
+ * Maven's `src/test/`) and filename-scoped (`*.test.*` / `*.spec.*`, Python
27
+ * `test_*.py` / `*_test.py`, Go `*_test.go`, Ruby `*_test.rb` / `*_spec.rb`,
28
+ * Java `*Test.java`). Anchored on path separators so `testimonials/user.ts` or
29
+ * `latest/report.py` don't get mistaken for tests.
30
+ */
31
+ declare function isTestFilePath(path: string): boolean;
32
+ //#endregion
33
+ export { isTestFilePath, isTestOriginQuery };
34
+ //# sourceMappingURL=test-origin.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-origin.d.mts","names":[],"sources":["../../src/sql/test-origin.ts"],"mappings":";;;;;;;;AAiBA;;;;;AA0BA;;;;;;;iBA1BgB,iBAAA,CACd,IAAA,WAAe,eAAA;;;;;;;;;;iBAyBD,cAAA,CAAe,IAAA"}
@@ -0,0 +1,51 @@
1
+ "use client";
2
+ //#region src/sql/test-origin.ts
3
+ /**
4
+ * Whether a query originated from a test file, decided from its SQLCommenter
5
+ * `file` tag.
6
+ *
7
+ * The CI gate should never flag a query that no production route runs — e.g. a
8
+ * read-back assertion in `tests/pg/postgres.test.ts` — yet before this such
9
+ * queries had to be ignored one hash at a time (#3199). SQLCommenter already
10
+ * carries the caller's file (surfaced in query detail per #2585); this reads it
11
+ * so both the analyzer's gate and the server's alert engine can bucket
12
+ * test-origin queries out with a single shared rule instead of drifting apart.
13
+ *
14
+ * Conservative by construction: the decision keys only off the `file` tag's
15
+ * origin path. A query with no `file` tag is never test-origin, so untagged
16
+ * codebases behave exactly as before.
17
+ */
18
+ function isTestOriginQuery(tags) {
19
+ if (!tags) return false;
20
+ for (const tag of tags) {
21
+ if (tag.key !== "file") continue;
22
+ const originFile = tag.value.split(";")[0]?.trim();
23
+ if (originFile && isTestFilePath(originFile)) return true;
24
+ }
25
+ return false;
26
+ }
27
+ /**
28
+ * Whether a source path looks like a test file. Query Doctor analyzes clients in
29
+ * any language, so this spans the common cross-language conventions rather than
30
+ * assuming JS/TS — directory-scoped (`tests/`, `__tests__/`, `spec/`, `e2e/`,
31
+ * Maven's `src/test/`) and filename-scoped (`*.test.*` / `*.spec.*`, Python
32
+ * `test_*.py` / `*_test.py`, Go `*_test.go`, Ruby `*_test.rb` / `*_spec.rb`,
33
+ * Java `*Test.java`). Anchored on path separators so `testimonials/user.ts` or
34
+ * `latest/report.py` don't get mistaken for tests.
35
+ */
36
+ function isTestFilePath(path) {
37
+ return TEST_PATH_PATTERNS.some((pattern) => pattern.test(path));
38
+ }
39
+ const TEST_PATH_PATTERNS = [
40
+ /(?:^|\/)(?:tests?|__tests__|specs?|e2e)\//i,
41
+ /(?:^|\/)src\/test\//i,
42
+ /\.(?:test|spec|e2e)\.[cm]?[jt]sx?$/i,
43
+ /(?:^|\/)(?:test_[^/]+|[^/]+_test|conftest)\.py$/i,
44
+ /_test\.go$/i,
45
+ /_(?:test|spec)\.rb$/i,
46
+ /Tests?\.(?:java|kt)$/
47
+ ];
48
+ //#endregion
49
+ export { isTestFilePath, isTestOriginQuery };
50
+
51
+ //# sourceMappingURL=test-origin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-origin.mjs","names":[],"sources":["../../src/sql/test-origin.ts"],"sourcesContent":["import type { SQLCommenterTag } from \"./analyzer.js\";\n\n/**\n * Whether a query originated from a test file, decided from its SQLCommenter\n * `file` tag.\n *\n * The CI gate should never flag a query that no production route runs — e.g. a\n * read-back assertion in `tests/pg/postgres.test.ts` — yet before this such\n * queries had to be ignored one hash at a time (#3199). SQLCommenter already\n * carries the caller's file (surfaced in query detail per #2585); this reads it\n * so both the analyzer's gate and the server's alert engine can bucket\n * test-origin queries out with a single shared rule instead of drifting apart.\n *\n * Conservative by construction: the decision keys only off the `file` tag's\n * origin path. A query with no `file` tag is never test-origin, so untagged\n * codebases behave exactly as before.\n */\nexport function isTestOriginQuery(\n tags: readonly SQLCommenterTag[] | undefined | null,\n): boolean {\n if (!tags) return false;\n for (const tag of tags) {\n if (tag.key !== \"file\") continue;\n // SQLCommenter can pack a caller stack into one `file` value, `;`-separated\n // and most-specific-first (the frontend renders `files[0]` as the origin).\n // The first entry is the query's own call site, so it decides origin — a\n // production query that merely threads through a test helper deeper in the\n // stack stays gated.\n const originFile = tag.value.split(\";\")[0]?.trim();\n if (originFile && isTestFilePath(originFile)) return true;\n }\n return false;\n}\n\n/**\n * Whether a source path looks like a test file. Query Doctor analyzes clients in\n * any language, so this spans the common cross-language conventions rather than\n * assuming JS/TS — directory-scoped (`tests/`, `__tests__/`, `spec/`, `e2e/`,\n * Maven's `src/test/`) and filename-scoped (`*.test.*` / `*.spec.*`, Python\n * `test_*.py` / `*_test.py`, Go `*_test.go`, Ruby `*_test.rb` / `*_spec.rb`,\n * Java `*Test.java`). Anchored on path separators so `testimonials/user.ts` or\n * `latest/report.py` don't get mistaken for tests.\n */\nexport function isTestFilePath(path: string): boolean {\n return TEST_PATH_PATTERNS.some((pattern) => pattern.test(path));\n}\n\nconst TEST_PATH_PATTERNS: readonly RegExp[] = [\n // A directory segment dedicated to tests, anywhere in the path.\n /(?:^|\\/)(?:tests?|__tests__|specs?|e2e)\\//i,\n // Maven/Gradle layout: src/test/java/...\n /(?:^|\\/)src\\/test\\//i,\n // JS/TS: foo.test.ts, foo.spec.tsx, foo.e2e.mts\n /\\.(?:test|spec|e2e)\\.[cm]?[jt]sx?$/i,\n // Python: test_foo.py, foo_test.py, conftest.py\n /(?:^|\\/)(?:test_[^/]+|[^/]+_test|conftest)\\.py$/i,\n // Go: foo_test.go\n /_test\\.go$/i,\n // Ruby: foo_test.rb, foo_spec.rb\n /_(?:test|spec)\\.rb$/i,\n // Java/Kotlin: FooTest.java, FooTests.kt\n /Tests?\\.(?:java|kt)$/,\n];\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,SAAgB,kBACd,MACS;AACT,KAAI,CAAC,KAAM,QAAO;AAClB,MAAK,MAAM,OAAO,MAAM;AACtB,MAAI,IAAI,QAAQ,OAAQ;EAMxB,MAAM,aAAa,IAAI,MAAM,MAAM,IAAI,CAAC,IAAI,MAAM;AAClD,MAAI,cAAc,eAAe,WAAW,CAAE,QAAO;;AAEvD,QAAO;;;;;;;;;;;AAYT,SAAgB,eAAe,MAAuB;AACpD,QAAO,mBAAmB,MAAM,YAAY,QAAQ,KAAK,KAAK,CAAC;;AAGjE,MAAM,qBAAwC;CAE5C;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CACD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@query-doctor/core",
3
- "version": "0.10.7",
3
+ "version": "0.10.8",
4
4
  "private": false,
5
5
  "description": "Core logic for Query Doctor",
6
6
  "license": "",