@thymian/plugin-http-analyzer 0.0.0-PLACEHOLDER

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 (35) hide show
  1. package/README.md +59 -0
  2. package/dist/analytics-api-context.d.ts +31 -0
  3. package/dist/analytics-api-context.d.ts.map +1 -0
  4. package/dist/analytics-api-context.js +167 -0
  5. package/dist/analytics-api-context.js.map +1 -0
  6. package/dist/db/http-filter-to-groupby-clause.d.ts +6 -0
  7. package/dist/db/http-filter-to-groupby-clause.d.ts.map +1 -0
  8. package/dist/db/http-filter-to-groupby-clause.js +64 -0
  9. package/dist/db/http-filter-to-groupby-clause.js.map +1 -0
  10. package/dist/db/http-filter-to-where-clause.d.ts +5 -0
  11. package/dist/db/http-filter-to-where-clause.d.ts.map +1 -0
  12. package/dist/db/http-filter-to-where-clause.js +188 -0
  13. package/dist/db/http-filter-to-where-clause.js.map +1 -0
  14. package/dist/db/http-transaction-repository.d.ts +15 -0
  15. package/dist/db/http-transaction-repository.d.ts.map +1 -0
  16. package/dist/db/http-transaction-repository.js +2 -0
  17. package/dist/db/http-transaction-repository.js.map +1 -0
  18. package/dist/db/init.sql +87 -0
  19. package/dist/db/sqlite-http-transaction-repository.d.ts +32 -0
  20. package/dist/db/sqlite-http-transaction-repository.d.ts.map +1 -0
  21. package/dist/db/sqlite-http-transaction-repository.js +472 -0
  22. package/dist/db/sqlite-http-transaction-repository.js.map +1 -0
  23. package/dist/db/types.d.ts +5 -0
  24. package/dist/db/types.d.ts.map +1 -0
  25. package/dist/db/types.js +2 -0
  26. package/dist/db/types.js.map +1 -0
  27. package/dist/db/utils.d.ts +6 -0
  28. package/dist/db/utils.d.ts.map +1 -0
  29. package/dist/db/utils.js +2 -0
  30. package/dist/db/utils.js.map +1 -0
  31. package/dist/index.d.ts +51 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +136 -0
  34. package/dist/index.js.map +1 -0
  35. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,59 @@
1
+ <!-- HEADER:START - Do not remove or modify this section -->
2
+ <div align="center">
3
+ <img src="https://raw.githubusercontent.com/thymianofficial/thymian/main/astro-docs/src/assets/logo.svg" alt="Thymian Logo" width="200"/>
4
+
5
+ # Thymian
6
+
7
+ **Add resilience and HTTP conformance to your API development workflow**
8
+
9
+ [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL%203.0-green.svg)](https://github.com/thymianofficial/thymian/blob/main/LICENSE)
10
+ [![CI](https://github.com/thymianofficial/thymian/actions/workflows/ci.yaml/badge.svg)](https://github.com/thymianofficial/thymian/actions/workflows/ci.yaml)
11
+ [![Documentation](https://img.shields.io/badge/docs-thymian.dev-green.svg)](https://thymian.dev)
12
+ [![Discord](https://img.shields.io/discord/1440702693768429791?logo=discord&label=Discord&color=5865F2)](https://discord.gg/TRSwCxbz9f)
13
+ [![Reddit](https://img.shields.io/badge/Reddit-ThymianOfficial-FF4500?logo=reddit)](https://www.reddit.com/r/ThymianOfficial/)
14
+ [![Twitter](https://img.shields.io/badge/Twitter-@thymiandev-1DA1F2?logo=x)](https://x.com/thymiandev)
15
+
16
+ </div>
17
+ <!-- HEADER:END -->
18
+
19
+ ## @thymian/plugin-http-analyzer
20
+
21
+ Captures and stores HTTP transactions in a SQLite database for post-facto analysis. Powers `thymian analyze` by running validation rules against recorded production traffic, detecting HTTP conformance issues in real deployments where proxies, CDNs, and load balancers affect HTTP semantics.
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install @thymian/plugin-http-analyzer
27
+ ```
28
+
29
+ > **Getting started with Thymian?** See the [main Thymian package](https://www.npmjs.com/package/thymian) for quick installation and first-run instructions.
30
+
31
+ <!-- FOOTER:START - Do not remove or modify this section -->
32
+
33
+ ## 📚 Documentation
34
+
35
+ - **[Getting Started](https://thymian.dev/introduction/getting-started)** - Set up Thymian in minutes
36
+ - **[Documentation](https://thymian.dev)** - Comprehensive guides and API reference
37
+ - **[CLI Reference](https://thymian.dev/references/cli)** - Complete CLI command documentation
38
+ - **[HTTP Rules](https://thymian.dev/guides/http-rules/how-to-use-rules)** - Learn about HTTP conformance validation
39
+
40
+ ## 🏢 Enterprise Support
41
+
42
+ Get professional consulting and dedicated support from the creators of Thymian. We offer:
43
+
44
+ - API design and governance strategies
45
+ - HTTP standards compliance auditing
46
+ - Custom plugin development
47
+ - Custom rule development
48
+ - Team training and workshops
49
+
50
+ **[Learn more about Enterprise Support](https://thymian.dev/enterprise)** | **Email: [support@thymian.dev](mailto:support@thymian.dev)**
51
+
52
+ ---
53
+
54
+ <div align="center">
55
+
56
+ **Shipped with 🌱 by [qupaya](https://qupaya.com)**
57
+
58
+ </div>
59
+ <!-- FOOTER:END -->
@@ -0,0 +1,31 @@
1
+ import { type AnalyzeContext, type CapturedTrace, type CapturedTransaction, type CommonHttpRequest, type CommonHttpResponse, type HttpFilterExpression, type HttpParticipantRole, type HttpRequest, type HttpResponse, type Logger, type ReportFn, type RuleFnResult, type RuleViolation, type RuleViolationLocation, ThymianFormat, type ValidationFn } from '@thymian/core';
2
+ import type { HttpTransactionRepository } from './db/http-transaction-repository.js';
3
+ export declare class AnalyticsApiContext implements AnalyzeContext {
4
+ readonly repository: HttpTransactionRepository;
5
+ private readonly logger;
6
+ readonly format: ThymianFormat;
7
+ readonly report: ReportFn;
8
+ private readonly violations;
9
+ private readonly roles?;
10
+ private readonly skippedOrigins;
11
+ constructor(repository: HttpTransactionRepository, logger: Logger, format: ThymianFormat, reportFn?: ReportFn, roles?: HttpParticipantRole[], skippedOrigins?: string[]);
12
+ reportViolation(violation: RuleViolation): void;
13
+ private addOriginsToFilter;
14
+ validateCommonHttpTransactions(filter: HttpFilterExpression, validate?: ValidationFn<[
15
+ CommonHttpRequest,
16
+ CommonHttpResponse,
17
+ RuleViolationLocation
18
+ ]> | HttpFilterExpression): Promise<RuleFnResult> | RuleFnResult;
19
+ validateGroupedCommonHttpTransactions(filter: HttpFilterExpression, groupBy: HttpFilterExpression, validationFn: ValidationFn<[
20
+ string,
21
+ [
22
+ CommonHttpRequest,
23
+ CommonHttpResponse,
24
+ RuleViolationLocation
25
+ ][]
26
+ ], RuleViolation | undefined>): Promise<RuleFnResult> | RuleFnResult;
27
+ validateHttpTransactions(filter: HttpFilterExpression, validation?: ValidationFn<[HttpRequest, HttpResponse, RuleViolationLocation]> | HttpFilterExpression): Promise<RuleFnResult> | RuleFnResult;
28
+ validateCapturedHttpTransactions(filter: HttpFilterExpression, validate: ValidationFn<[CapturedTransaction, string]>): Promise<RuleFnResult> | RuleFnResult;
29
+ validateCapturedHttpTraces(validate: ValidationFn<[CapturedTrace, string]>): RuleFnResult;
30
+ }
31
+ //# sourceMappingURL=analytics-api-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics-api-context.d.ts","sourceRoot":"","sources":["../src/analytics-api-context.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,aAAa,EAElB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EAEvB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAEhB,KAAK,YAAY,EAGjB,KAAK,MAAM,EAIX,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,aAAa,EAEb,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAErF,qBAAa,mBAAoB,YAAW,cAAc;IAQtD,QAAQ,CAAC,UAAU,EAAE,yBAAyB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM;IARzB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;gBAG/B,UAAU,EAAE,yBAAyB,EAC7B,MAAM,EAAE,MAAM,EAC/B,MAAM,EAAE,aAAa,EACrB,QAAQ,CAAC,EAAE,QAAQ,EACnB,KAAK,CAAC,EAAE,mBAAmB,EAAE,EAC7B,cAAc,CAAC,EAAE,MAAM,EAAE;IA2B3B,eAAe,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI;IAI/C,OAAO,CAAC,kBAAkB;IAa1B,8BAA8B,CAC5B,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,GACJ,YAAY,CACV;QAAC,iBAAiB;QAAE,kBAAkB;QAAE,qBAAqB;KAAC,CAC/D,GACD,oBAA6B,GAChC,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY;IAkDvC,qCAAqC,CACnC,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,oBAAoB,EAC7B,YAAY,EAAE,YAAY,CACxB;QACE,MAAM;QACN;YAAC,iBAAiB;YAAE,kBAAkB;YAAE,qBAAqB;SAAC,EAAE;KACjE,EACD,aAAa,GAAG,SAAS,CAC1B,GACA,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY;IA4BvC,wBAAwB,CACtB,MAAM,EAAE,oBAAoB,EAC5B,UAAU,GACN,YAAY,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,qBAAqB,CAAC,CAAC,GAChE,oBAA6B,GAChC,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY;IAqDvC,gCAAgC,CAC9B,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,EAAE,YAAY,CAAC,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,GACpD,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY;IAiCvC,0BAA0B,CACxB,QAAQ,EAAE,YAAY,CAAC,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,GAC9C,YAAY;CAwBhB"}
@@ -0,0 +1,167 @@
1
+ import { and, capturedTraceToString, createRegExpFromOriginWildcard, httpRequestToCommonHttpRequest, httpResponseToCommonHttpResponse, httpTransactionToLabel, matchesOrigin, not, or, ThymianFormat, thymianRequestToOrigin, } from '@thymian/core';
2
+ export class AnalyticsApiContext {
3
+ repository;
4
+ logger;
5
+ format;
6
+ report;
7
+ violations = [];
8
+ roles;
9
+ skippedOrigins;
10
+ constructor(repository, logger, format, reportFn, roles, skippedOrigins) {
11
+ this.repository = repository;
12
+ this.logger = logger;
13
+ this.report = reportFn ?? (() => undefined);
14
+ this.skippedOrigins = skippedOrigins ?? [];
15
+ if (this.skippedOrigins.length === 0) {
16
+ this.format = format;
17
+ }
18
+ else {
19
+ const regExps = this.skippedOrigins.map(createRegExpFromOriginWildcard);
20
+ this.format = format.filter(({ thymianReq }) => !regExps.some((regExp) => regExp.test(thymianRequestToOrigin(thymianReq))));
21
+ }
22
+ if (roles) {
23
+ this.roles = roles.flatMap((role) => role === 'intermediary'
24
+ ? ['proxy', 'tunnel', 'gateway', 'intermediary']
25
+ : role);
26
+ }
27
+ }
28
+ reportViolation(violation) {
29
+ this.violations.push(violation);
30
+ }
31
+ addOriginsToFilter(filter) {
32
+ return this.skippedOrigins.length === 0
33
+ ? filter
34
+ : and(filter, not(or(...this.skippedOrigins.map((origin) => matchesOrigin(origin)))));
35
+ }
36
+ validateCommonHttpTransactions(filter, validate = filter) {
37
+ let finalFilter;
38
+ let validateFn;
39
+ if (typeof validate === 'function') {
40
+ finalFilter = filter;
41
+ validateFn = validate;
42
+ }
43
+ else {
44
+ finalFilter = and(filter, validate);
45
+ validateFn = () => true;
46
+ }
47
+ finalFilter = this.addOriginsToFilter(finalFilter);
48
+ const results = [];
49
+ for (const { request, response, } of this.repository.readTransactionsByHttpFilter(finalFilter, this.roles)) {
50
+ const violation = validateFn(httpRequestToCommonHttpRequest(request.data), httpResponseToCommonHttpResponse(response.data), httpTransactionToLabel(request.data, response.data));
51
+ if (violation) {
52
+ const location = httpTransactionToLabel(request.data, response.data);
53
+ if (violation === true) {
54
+ results.push({
55
+ location,
56
+ });
57
+ }
58
+ else {
59
+ results.push({
60
+ location,
61
+ ...violation,
62
+ });
63
+ }
64
+ }
65
+ }
66
+ return results.concat(this.violations);
67
+ }
68
+ validateGroupedCommonHttpTransactions(filter, groupBy, validationFn) {
69
+ const results = [];
70
+ const finalFilter = this.addOriginsToFilter(filter);
71
+ const groups = this.repository.readAndGroupTransactionsByHttpFilter(finalFilter, groupBy, this.roles);
72
+ for (const [key, transactions] of groups) {
73
+ const violation = validationFn(key, transactions.map((t) => [
74
+ httpRequestToCommonHttpRequest(t.request.data),
75
+ httpResponseToCommonHttpResponse(t.response.data),
76
+ httpTransactionToLabel(t.request.data, t.response.data),
77
+ ]));
78
+ if (violation) {
79
+ results.push(violation);
80
+ }
81
+ }
82
+ return results;
83
+ }
84
+ validateHttpTransactions(filter, validation = filter) {
85
+ let finalFilter;
86
+ let validateFn;
87
+ if (typeof validation === 'function') {
88
+ finalFilter = filter;
89
+ validateFn = validation;
90
+ }
91
+ else {
92
+ finalFilter = and(filter, validation);
93
+ validateFn = () => true;
94
+ }
95
+ finalFilter = this.addOriginsToFilter(finalFilter);
96
+ const results = [];
97
+ for (const { request, response, } of this.repository.readTransactionsByHttpFilter(finalFilter, this.roles)) {
98
+ const matched = this.format.matchTransaction(request.data, response.data);
99
+ const location = matched
100
+ ? {
101
+ elementType: 'edge',
102
+ elementId: matched[0],
103
+ label: httpTransactionToLabel(request.data, response.data),
104
+ }
105
+ : httpTransactionToLabel(request.data, response.data);
106
+ const violation = validateFn(request.data, response.data, location);
107
+ if (violation) {
108
+ if (violation === true) {
109
+ results.push({
110
+ location,
111
+ });
112
+ }
113
+ else {
114
+ results.push({
115
+ location,
116
+ ...violation,
117
+ });
118
+ }
119
+ }
120
+ }
121
+ return results.concat(this.violations);
122
+ }
123
+ validateCapturedHttpTransactions(filter, validate) {
124
+ const finalFilter = this.addOriginsToFilter(filter);
125
+ const results = [];
126
+ for (const transaction of this.repository.readTransactionsByHttpFilter(finalFilter, this.roles)) {
127
+ const location = httpTransactionToLabel(transaction.request.data, transaction.response.data);
128
+ const violation = validate(transaction, location);
129
+ if (violation) {
130
+ if (violation === true) {
131
+ results.push({
132
+ location,
133
+ });
134
+ }
135
+ else {
136
+ results.push({
137
+ location,
138
+ ...violation,
139
+ });
140
+ }
141
+ }
142
+ }
143
+ return results.concat(this.violations);
144
+ }
145
+ validateCapturedHttpTraces(validate) {
146
+ const results = [];
147
+ for (const trace of this.repository.readAllHttpTraces()) {
148
+ const location = capturedTraceToString(trace);
149
+ const violation = validate(trace, location);
150
+ if (violation) {
151
+ if (violation === true) {
152
+ results.push({
153
+ location,
154
+ });
155
+ }
156
+ else {
157
+ results.push({
158
+ location,
159
+ ...violation,
160
+ });
161
+ }
162
+ }
163
+ }
164
+ return results.concat(this.violations);
165
+ }
166
+ }
167
+ //# sourceMappingURL=analytics-api-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics-api-context.js","sourceRoot":"","sources":["../src/analytics-api-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type HttpFilterExpression } from '@thymian/core';
2
+ import type { TableNames } from './types.js';
3
+ import type { SqlFragment } from './utils.js';
4
+ export declare function httpFilterToGroupByClause(expression: HttpFilterExpression, tables: TableNames): SqlFragment;
5
+ export declare function httpFilterToGroupingKey(expression: HttpFilterExpression, tables: TableNames): string;
6
+ //# sourceMappingURL=http-filter-to-groupby-clause.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-filter-to-groupby-clause.d.ts","sourceRoot":"","sources":["../../src/db/http-filter-to-groupby-clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,oBAAoB,EAK1B,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,UAAU,GACjB,WAAW,CAyCb;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,UAAU,GACjB,MAAM,CAyBR"}
@@ -0,0 +1,64 @@
1
+ import { and, origin, path, visitHttpFilter, } from '@thymian/core';
2
+ export function httpFilterToGroupByClause(expression, tables) {
3
+ const params = [];
4
+ switch (expression.type) {
5
+ case 'url':
6
+ // port is embedded in origin (e.g. "https://example.com:8080"), so
7
+ // grouping by origin + path is sufficient to identify a URL.
8
+ return httpFilterToGroupByClause(and(origin(), path()), tables);
9
+ case 'origin':
10
+ return {
11
+ sql: `${tables.requests}.origin`,
12
+ params,
13
+ };
14
+ case 'method':
15
+ return {
16
+ sql: `${tables.requests}.method`,
17
+ params,
18
+ };
19
+ case 'path':
20
+ return {
21
+ sql: `${tables.requests}.path`,
22
+ params,
23
+ };
24
+ case 'statusCode':
25
+ return {
26
+ sql: `${tables.responses}.status_code`,
27
+ params,
28
+ };
29
+ case 'and': {
30
+ const parts = expression.filters.map((expr) => httpFilterToGroupByClause(expr, tables));
31
+ return {
32
+ sql: parts.map((p) => p.sql).join(', '),
33
+ params,
34
+ };
35
+ }
36
+ default:
37
+ throw new Error(`Unsupported group by expression: ${expression.type}`);
38
+ }
39
+ }
40
+ export function httpFilterToGroupingKey(expression, tables) {
41
+ // Pre-expand url() to and(origin(), path()) so the visitor does not need a
42
+ // visitUrl handler (port is already embedded in origin).
43
+ const resolved = expression.type === 'url' ? and(origin(), path()) : expression;
44
+ return visitHttpFilter(resolved, {
45
+ visitAnd(expr) {
46
+ return expr.filters
47
+ .map((filter) => httpFilterToGroupingKey(filter, tables))
48
+ .join(' || ');
49
+ },
50
+ visitOrigin() {
51
+ return `COALESCE(${tables.requests}.origin, '')`;
52
+ },
53
+ visitMethod() {
54
+ return `COALESCE(${tables.requests}.method, '')`;
55
+ },
56
+ visitStatusCode() {
57
+ return `COALESCE(${tables.responses}.status_code, '')`;
58
+ },
59
+ visitPath() {
60
+ return `COALESCE(${tables.requests}.path, '')`;
61
+ },
62
+ });
63
+ }
64
+ //# sourceMappingURL=http-filter-to-groupby-clause.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-filter-to-groupby-clause.js","sourceRoot":"","sources":["../../src/db/http-filter-to-groupby-clause.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EAGH,MAAM,EACN,IAAI,EACJ,eAAe,GAChB,MAAM,eAAe,CAAC;AAKvB,MAAM,UAAU,yBAAyB,CACvC,UAAgC,EAChC,MAAkB;IAElB,MAAM,MAAM,GAAc,EAAE,CAAC;IAE7B,QAAQ,UAAU,CAAC,IAAI,EAAE,CAAC;QACxB,KAAK,KAAK;YACR,mEAAmE;YACnE,6DAA6D;YAC7D,OAAO,yBAAyB,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QAClE,KAAK,QAAQ;YACX,OAAO;gBACL,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,SAAS;gBAChC,MAAM;aACP,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO;gBACL,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,SAAS;gBAChC,MAAM;aACP,CAAC;QACJ,KAAK,MAAM;YACT,OAAO;gBACL,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,OAAO;gBAC9B,MAAM;aACP,CAAC;QACJ,KAAK,YAAY;YACf,OAAO;gBACL,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,cAAc;gBACtC,MAAM;aACP,CAAC;QACJ,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC5C,yBAAyB,CAAC,IAAI,EAAE,MAAM,CAAC,CACxC,CAAC;YAEF,OAAO;gBACL,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBACvC,MAAM;aACP,CAAC;QACJ,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,oCAAoC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,UAAgC,EAChC,MAAkB;IAElB,2EAA2E;IAC3E,yDAAyD;IACzD,MAAM,QAAQ,GACZ,UAAU,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IAEjE,OAAO,eAAe,CAAC,QAAQ,EAAE;QAC/B,QAAQ,CAAC,IAAiD;YACxD,OAAO,IAAI,CAAC,OAAO;iBAChB,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;iBACxD,IAAI,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC;QACD,WAAW;YACT,OAAO,YAAY,MAAM,CAAC,QAAQ,cAAc,CAAC;QACnD,CAAC;QACD,WAAW;YACT,OAAO,YAAY,MAAM,CAAC,QAAQ,cAAc,CAAC;QACnD,CAAC;QACD,eAAe;YACb,OAAO,YAAY,MAAM,CAAC,SAAS,mBAAmB,CAAC;QACzD,CAAC;QACD,SAAS;YACP,OAAO,YAAY,MAAM,CAAC,QAAQ,YAAY,CAAC;QACjD,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type HttpFilterExpression } from '@thymian/core';
2
+ import type { TableNames } from './types.js';
3
+ import { type SqlFragment } from './utils.js';
4
+ export declare function compileHttpFilterToWhereClause(filter: HttpFilterExpression, names?: Partial<TableNames>): SqlFragment;
5
+ //# sourceMappingURL=http-filter-to-where-clause.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-filter-to-where-clause.d.ts","sourceRoot":"","sources":["../../src/db/http-filter-to-where-clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,oBAAoB,EAAgB,MAAM,eAAe,CAAC;AAE7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,oBAAoB,EAC5B,KAAK,GAAE,OAAO,CAAC,UAAU,CAAM,GAC9B,WAAW,CAwNb"}
@@ -0,0 +1,188 @@
1
+ import { and, origin, path } from '@thymian/core';
2
+ import { parenthesize } from './utils.js';
3
+ export function compileHttpFilterToWhereClause(filter, names = {}) {
4
+ const tableNames = {
5
+ requests: 'req',
6
+ responses: 'res',
7
+ ...names,
8
+ };
9
+ switch (filter.type) {
10
+ case 'origin':
11
+ return {
12
+ sql: `${tableNames.requests}.origin = ?`,
13
+ params: [filter.origin],
14
+ };
15
+ case 'method':
16
+ return {
17
+ sql: `${tableNames.requests}.method = ? COLLATE NOCASE`,
18
+ params: [filter.method],
19
+ };
20
+ case 'path':
21
+ return { sql: `${tableNames.requests}.path = ?`, params: [filter.path] };
22
+ case 'requestHeader': {
23
+ const base = `
24
+ EXISTS (
25
+ SELECT 1
26
+ FROM http_request_header reqHeader
27
+ WHERE reqHeader.request_id = ${tableNames.requests}.id
28
+ AND reqHeader.name = ? COLLATE NOCASE`;
29
+ if (typeof filter.value === 'undefined') {
30
+ return { sql: `${base})`, params: [filter.header] };
31
+ }
32
+ return {
33
+ sql: `${base} AND reqHeader.value = ?)`,
34
+ params: [filter.header, String(filter.value)],
35
+ };
36
+ }
37
+ case 'responseHeader': {
38
+ const base = `
39
+ EXISTS (
40
+ SELECT 1
41
+ FROM http_response_header resHeader
42
+ WHERE resHeader.response_id = res.id
43
+ AND resHeader.name = ? COLLATE NOCASE`;
44
+ if (typeof filter.value === 'undefined') {
45
+ return { sql: `${base})`, params: [filter.header] };
46
+ }
47
+ return {
48
+ sql: `${base} AND resHeader.value = ?)`,
49
+ params: [filter.header, String(filter.value)],
50
+ };
51
+ }
52
+ case 'responseTrailer': {
53
+ const base = `
54
+ EXISTS (
55
+ SELECT 1
56
+ FROM http_response_trailer resTrailer
57
+ WHERE resTrailer.response_id = res.id
58
+ AND resTrailer.name = ? COLLATE NOCASE`;
59
+ if (typeof filter.value === 'undefined') {
60
+ return { sql: `${base})`, params: [filter.trailer] };
61
+ }
62
+ return {
63
+ sql: `${base} AND resTrailer.value = ?)`,
64
+ params: [filter.trailer, String(filter.value)],
65
+ };
66
+ }
67
+ case 'statusCode':
68
+ return {
69
+ sql: `${tableNames.responses}.status_code = ?`,
70
+ params: [filter.code],
71
+ };
72
+ case 'statusCodeRange':
73
+ return {
74
+ sql: `(${tableNames.responses}.status_code BETWEEN ? AND ?)`,
75
+ params: [filter.start, filter.end],
76
+ };
77
+ case 'hasBody':
78
+ return { sql: `${tableNames.requests}.body IS NOT NULL`, params: [] };
79
+ case 'hasResponseBody':
80
+ return { sql: `${tableNames.responses}.body IS NOT NULL`, params: [] };
81
+ case 'requestMediaType': {
82
+ const where = `
83
+ EXISTS (
84
+ SELECT 1
85
+ FROM http_request_header reqHeader
86
+ WHERE reqHeader.request_id = req.id
87
+ AND reqHeader.name = 'content-type' COLLATE NOCASE
88
+ AND LOWER(reqHeader.value) LIKE LOWER(?)
89
+ )`;
90
+ return { sql: where, params: [filter.mediaType] };
91
+ }
92
+ case 'responseMediaType': {
93
+ const where = `
94
+ EXISTS (
95
+ SELECT 1
96
+ FROM http_response_header resHeader
97
+ WHERE resHeader.response_id = res.id
98
+ AND resHeader.name = 'content-type' COLLATE NOCASE
99
+ AND LOWER(resHeader.value) LIKE LOWER(?)
100
+ )`;
101
+ return { sql: where, params: [filter.mediaType] };
102
+ }
103
+ case 'constant':
104
+ return { sql: filter.value ? '1=1' : '0=1', params: [] };
105
+ case 'and': {
106
+ const parts = filter.filters.map((expr) => compileHttpFilterToWhereClause(expr, tableNames));
107
+ return {
108
+ sql: parts.map((p) => parenthesize(p.sql)).join(' AND '),
109
+ params: parts.flatMap((p) => p.params),
110
+ };
111
+ }
112
+ case 'or': {
113
+ const parts = filter.filters.map((expr) => compileHttpFilterToWhereClause(expr, tableNames));
114
+ return {
115
+ sql: parts.map((p) => parenthesize(p.sql)).join(' OR '),
116
+ params: parts.flatMap((p) => p.params),
117
+ };
118
+ }
119
+ case 'not': {
120
+ const inner = compileHttpFilterToWhereClause(filter.filter);
121
+ return {
122
+ sql: `NOT ${parenthesize(inner.sql)}`,
123
+ params: inner.params,
124
+ };
125
+ }
126
+ case 'xor': {
127
+ const [a, b] = filter.filters;
128
+ const sa = compileHttpFilterToWhereClause(a);
129
+ const sb = compileHttpFilterToWhereClause(b);
130
+ const where = `
131
+ (${parenthesize(sa.sql)} AND NOT ${parenthesize(sb.sql)})
132
+ OR
133
+ (${parenthesize(sb.sql)} AND NOT ${parenthesize(sa.sql)})
134
+ `;
135
+ return {
136
+ sql: where,
137
+ params: [...sa.params, ...sb.params, ...sb.params, ...sa.params],
138
+ };
139
+ }
140
+ case 'queryParam': {
141
+ if (typeof filter.param === 'undefined') {
142
+ return { sql: '1=1', params: [] };
143
+ }
144
+ return {
145
+ sql: `
146
+ EXISTS (
147
+ SELECT 1
148
+ FROM http_request_query_parameter reqParam
149
+ WHERE
150
+ reqParam.request_id = reqId AND
151
+ reqParam.name = ? COLLATE NOCASE AND
152
+ reqParam.value = ?
153
+ )`,
154
+ params: [filter.param, filter.value],
155
+ };
156
+ }
157
+ case 'url': {
158
+ if (typeof filter.url === 'undefined') {
159
+ return { sql: '1=1', params: [] };
160
+ }
161
+ const url = new URL(filter.url);
162
+ return compileHttpFilterToWhereClause(and(origin(url.origin), path(url.pathname)), tableNames);
163
+ }
164
+ case 'protocol': {
165
+ if (typeof filter.protocol === 'undefined') {
166
+ return { sql: '1=1', params: [] };
167
+ }
168
+ return {
169
+ sql: `${tableNames.requests}.origin LIKE ? || '://%'`,
170
+ params: [filter.protocol],
171
+ };
172
+ }
173
+ case 'matches-origin': {
174
+ if (typeof filter.origin === 'undefined') {
175
+ return { sql: '1=1', params: [] };
176
+ }
177
+ return {
178
+ sql: `${tableNames.requests}.origin LIKE ?`,
179
+ params: [`%${filter.origin.replaceAll('*', '%')}%`],
180
+ };
181
+ }
182
+ case 'hasResponse':
183
+ case 'isAuthorized':
184
+ case 'port':
185
+ throw new Error(`HTTP filter expression "${filter.type}" is not supported for SQL translation.`);
186
+ }
187
+ }
188
+ //# sourceMappingURL=http-filter-to-where-clause.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-filter-to-where-clause.js","sourceRoot":"","sources":["../../src/db/http-filter-to-where-clause.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { HttpFilterExpression } from '@thymian/core';
2
+ import type { CapturedTrace, CapturedTransaction, HttpParticipantRole } from '@thymian/core';
3
+ export type Awaitable<T> = T | Promise<T>;
4
+ export interface HttpTransactionRepository {
5
+ init(): Awaitable<void>;
6
+ close(): Awaitable<void>;
7
+ insertHttpTrace(trace: CapturedTrace): Awaitable<number>;
8
+ readTraceById(id: number): Awaitable<CapturedTrace | undefined>;
9
+ insertHttpTransaction(transaction: CapturedTransaction): Awaitable<number>;
10
+ readTransactionById(id: number): Awaitable<CapturedTransaction | undefined>;
11
+ readTransactionsByHttpFilter(filter: HttpFilterExpression, role?: HttpParticipantRole[]): IterableIterator<CapturedTransaction, void, unknown>;
12
+ readAndGroupTransactionsByHttpFilter(filter: HttpFilterExpression, groupBy: HttpFilterExpression, role?: HttpParticipantRole[]): IterableIterator<[string, CapturedTransaction[]], void, unknown>;
13
+ readAllHttpTraces(): IterableIterator<CapturedTrace, void, unknown>;
14
+ }
15
+ //# sourceMappingURL=http-transaction-repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-transaction-repository.d.ts","sourceRoot":"","sources":["../../src/db/http-transaction-repository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,KAAK,EACV,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAE1C,MAAM,WAAW,yBAAyB;IACxC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC;IAExB,KAAK,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC;IAEzB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAEzD,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;IAEhE,qBAAqB,CAAC,WAAW,EAAE,mBAAmB,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAE3E,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAAC;IAE5E,4BAA4B,CAC1B,MAAM,EAAE,oBAAoB,EAC5B,IAAI,CAAC,EAAE,mBAAmB,EAAE,GAC3B,gBAAgB,CAAC,mBAAmB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAExD,oCAAoC,CAClC,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,oBAAoB,EAC7B,IAAI,CAAC,EAAE,mBAAmB,EAAE,GAC3B,gBAAgB,CAAC,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAEpE,iBAAiB,IAAI,gBAAgB,CAAC,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;CACrE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=http-transaction-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-transaction-repository.js","sourceRoot":"","sources":["../../src/db/http-transaction-repository.ts"],"names":[],"mappings":""}