flowlint 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/packages/config/flowlint-config.d.ts +64 -0
  2. package/dist/packages/config/flowlint-config.js +103 -0
  3. package/dist/packages/config/flowlint-config.js.map +1 -0
  4. package/dist/packages/config/index.d.ts +4 -0
  5. package/dist/packages/config/index.js +21 -0
  6. package/dist/packages/config/index.js.map +1 -0
  7. package/dist/packages/github/client.d.ts +2 -0
  8. package/dist/packages/github/client.js +94 -0
  9. package/dist/packages/github/client.js.map +1 -0
  10. package/dist/packages/logger/index.d.ts +11 -0
  11. package/dist/packages/logger/index.js +40 -0
  12. package/dist/packages/logger/index.js.map +1 -0
  13. package/dist/packages/observability/collectors.d.ts +40 -0
  14. package/dist/packages/observability/collectors.js +75 -0
  15. package/dist/packages/observability/collectors.js.map +1 -0
  16. package/dist/packages/observability/index.d.ts +10 -0
  17. package/dist/packages/observability/index.js +35 -0
  18. package/dist/packages/observability/index.js.map +1 -0
  19. package/dist/packages/observability/metrics.d.ts +119 -0
  20. package/dist/packages/observability/metrics.js +194 -0
  21. package/dist/packages/observability/metrics.js.map +1 -0
  22. package/dist/packages/observability/middleware.d.ts +32 -0
  23. package/dist/packages/observability/middleware.js +58 -0
  24. package/dist/packages/observability/middleware.js.map +1 -0
  25. package/dist/packages/review/analysis-engine.d.ts +19 -0
  26. package/dist/packages/review/analysis-engine.js +111 -0
  27. package/dist/packages/review/analysis-engine.js.map +1 -0
  28. package/dist/packages/review/index.d.ts +12 -0
  29. package/dist/packages/review/index.js +29 -0
  30. package/dist/packages/review/index.js.map +1 -0
  31. package/dist/packages/review/parser-n8n.d.ts +2 -0
  32. package/dist/packages/review/parser-n8n.js +118 -0
  33. package/dist/packages/review/parser-n8n.js.map +1 -0
  34. package/dist/packages/review/providers/github.d.ts +62 -0
  35. package/dist/packages/review/providers/github.js +275 -0
  36. package/dist/packages/review/providers/github.js.map +1 -0
  37. package/dist/packages/review/providers.d.ts +106 -0
  38. package/dist/packages/review/providers.js +12 -0
  39. package/dist/packages/review/providers.js.map +1 -0
  40. package/dist/packages/review/reporter.d.ts +17 -0
  41. package/dist/packages/review/reporter.js +62 -0
  42. package/dist/packages/review/reporter.js.map +1 -0
  43. package/dist/packages/review/rules/index.d.ts +9 -0
  44. package/dist/packages/review/rules/index.js +313 -0
  45. package/dist/packages/review/rules/index.js.map +1 -0
  46. package/dist/packages/review/rules/rule-utils.d.ts +36 -0
  47. package/dist/packages/review/rules/rule-utils.js +75 -0
  48. package/dist/packages/review/rules/rule-utils.js.map +1 -0
  49. package/dist/packages/review/schemas/index.d.ts +17 -0
  50. package/dist/packages/review/schemas/index.js +139 -0
  51. package/dist/packages/review/schemas/index.js.map +1 -0
  52. package/dist/packages/review/schemas/n8n-workflow.schema.json +177 -0
  53. package/dist/packages/review/sniffer.d.ts +15 -0
  54. package/dist/packages/review/sniffer.js +47 -0
  55. package/dist/packages/review/sniffer.js.map +1 -0
  56. package/dist/packages/review/types.d.ts +38 -0
  57. package/dist/packages/review/types.js +3 -0
  58. package/dist/packages/review/types.js.map +1 -0
  59. package/dist/packages/review/utils/findings.d.ts +23 -0
  60. package/dist/packages/review/utils/findings.js +34 -0
  61. package/dist/packages/review/utils/findings.js.map +1 -0
  62. package/dist/packages/review/utils/merge.d.ts +12 -0
  63. package/dist/packages/review/utils/merge.js +40 -0
  64. package/dist/packages/review/utils/merge.js.map +1 -0
  65. package/dist/packages/review/utils.d.ts +60 -0
  66. package/dist/packages/review/utils.js +214 -0
  67. package/dist/packages/review/utils.js.map +1 -0
  68. package/dist/packages/tracing/github-tracer.d.ts +38 -0
  69. package/dist/packages/tracing/github-tracer.js +79 -0
  70. package/dist/packages/tracing/github-tracer.js.map +1 -0
  71. package/dist/packages/tracing/index.d.ts +81 -0
  72. package/dist/packages/tracing/index.js +240 -0
  73. package/dist/packages/tracing/index.js.map +1 -0
  74. package/dist/packages/tracing/tracer.d.ts +30 -0
  75. package/dist/packages/tracing/tracer.js +141 -0
  76. package/dist/packages/tracing/tracer.js.map +1 -0
  77. package/package.json +10 -1
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EXAMPLES_BASE_URL = void 0;
4
+ exports.flattenConnections = flattenConnections;
5
+ exports.buildValidationErrors = buildValidationErrors;
6
+ exports.collectStrings = collectStrings;
7
+ exports.toRegex = toRegex;
8
+ exports.isApiNode = isApiNode;
9
+ exports.isMutationNode = isMutationNode;
10
+ exports.isErrorProneNode = isErrorProneNode;
11
+ exports.isNotificationNode = isNotificationNode;
12
+ exports.isErrorHandlerNode = isErrorHandlerNode;
13
+ exports.isRejoinNode = isRejoinNode;
14
+ exports.isMeaningfulConsumer = isMeaningfulConsumer;
15
+ exports.containsCandidate = containsCandidate;
16
+ exports.isTerminalNode = isTerminalNode;
17
+ exports.readNumber = readNumber;
18
+ exports.findAllDownstreamNodes = findAllDownstreamNodes;
19
+ exports.findAllUpstreamNodes = findAllUpstreamNodes;
20
+ exports.getExampleLink = getExampleLink;
21
+ /**
22
+ * Shared utility functions for workflow parsing and validation
23
+ */
24
+ /**
25
+ * Helper to flatten nested connection arrays from n8n workflow connections.
26
+ * Connections can be nested in various ways (arrays of arrays, objects with node properties).
27
+ * This recursively flattens them to a simple array of connection objects.
28
+ *
29
+ * @param value - The connection value to flatten (can be array, object, or primitive)
30
+ * @returns Array of connection objects with 'node' property
31
+ */
32
+ function flattenConnections(value) {
33
+ if (!value)
34
+ return [];
35
+ if (Array.isArray(value)) {
36
+ return value.flatMap((entry) => flattenConnections(entry));
37
+ }
38
+ if (typeof value === 'object' && 'node' in value) {
39
+ return [value];
40
+ }
41
+ return [];
42
+ }
43
+ /**
44
+ * Build validation error objects from a collection of items using provided templates.
45
+ * This utility eliminates code duplication in validation error construction.
46
+ *
47
+ * @template T - Type of items to process
48
+ * @param items - Set or array of items to convert to validation errors
49
+ * @param errorConfig - Configuration object containing:
50
+ * - path: The JSON path where the error occurred
51
+ * - messageTemplate: Function to generate error message for each item
52
+ * - suggestionTemplate: Function to generate actionable suggestion for each item
53
+ * @returns Array of validation error objects with path, message, and suggestion fields
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * const duplicates = new Set(['node1', 'node2']);
58
+ * const errors = buildValidationErrors(duplicates, {
59
+ * path: 'nodes[].id',
60
+ * messageTemplate: (id) => `Duplicate node ID: "${id}"`,
61
+ * suggestionTemplate: (id) => `Remove or rename the duplicate node with ID "${id}".`
62
+ * });
63
+ * ```
64
+ */
65
+ function buildValidationErrors(items, errorConfig) {
66
+ const itemArray = Array.isArray(items) ? items : Array.from(items);
67
+ return itemArray.map((item) => ({
68
+ path: errorConfig.path,
69
+ message: errorConfig.messageTemplate(item),
70
+ suggestion: errorConfig.suggestionTemplate(item),
71
+ }));
72
+ }
73
+ function collectStrings(value, out = []) {
74
+ if (typeof value === 'string')
75
+ out.push(value);
76
+ else if (Array.isArray(value))
77
+ value.forEach((entry) => collectStrings(entry, out));
78
+ else if (value && typeof value === 'object')
79
+ Object.values(value).forEach((entry) => collectStrings(entry, out));
80
+ return out;
81
+ }
82
+ function toRegex(pattern) {
83
+ let source = pattern;
84
+ let flags = '';
85
+ if (source.startsWith('(?i)')) {
86
+ source = source.slice(4);
87
+ flags += 'i';
88
+ }
89
+ return new RegExp(source, flags);
90
+ }
91
+ function isApiNode(type) {
92
+ return /http|request|google|facebook|ads/i.test(type);
93
+ }
94
+ function isMutationNode(type) {
95
+ return /write|insert|update|delete|post|put|patch|database|mongo|supabase|sheet/i.test(type);
96
+ }
97
+ function isErrorProneNode(type) {
98
+ return isApiNode(type) || isMutationNode(type) || /execute|workflow|function/i.test(type);
99
+ }
100
+ function isNotificationNode(type) {
101
+ return /slack|discord|email|gotify|mattermost|microsoftTeams|pushbullet|pushover|rocketchat|zulip|telegram/i.test(type);
102
+ }
103
+ function isErrorHandlerNode(type, name) {
104
+ const normalizedType = type.toLowerCase();
105
+ if (normalizedType.includes('stopanderror'))
106
+ return true;
107
+ if (normalizedType.includes('errorhandler'))
108
+ return true;
109
+ if (normalizedType.includes('raiseerror'))
110
+ return true;
111
+ const normalizedName = name?.toLowerCase() ?? '';
112
+ if (normalizedName.includes('stop and error'))
113
+ return true;
114
+ if (normalizedName.includes('error handler'))
115
+ return true;
116
+ return false;
117
+ }
118
+ function isRejoinNode(graph, nodeId) {
119
+ const incoming = graph.edges.filter((e) => e.to === nodeId);
120
+ if (incoming.length <= 1)
121
+ return false;
122
+ const hasErrorEdge = incoming.some((e) => e.on === 'error');
123
+ const hasSuccessEdge = incoming.some((e) => e.on !== 'error');
124
+ return hasErrorEdge && hasSuccessEdge;
125
+ }
126
+ function isMeaningfulConsumer(node) {
127
+ // A meaningful consumer is a node that has an external side-effect.
128
+ return (isMutationNode(node.type) || // Writes to a DB, sheet, etc.
129
+ isNotificationNode(node.type) || // Sends a message to Slack, email, etc.
130
+ isApiNode(node.type) || // Calls an external API
131
+ /respondToWebhook/i.test(node.type) // Specifically nodes that send a response back.
132
+ );
133
+ }
134
+ function containsCandidate(value, candidates) {
135
+ if (!value || !candidates.length)
136
+ return false;
137
+ const queue = [value];
138
+ const candidateRegex = new RegExp(`(${candidates.join('|')})`, 'i');
139
+ while (queue.length > 0) {
140
+ const current = queue.shift();
141
+ if (typeof current === 'string') {
142
+ if (candidateRegex.test(current))
143
+ return true;
144
+ }
145
+ else if (Array.isArray(current)) {
146
+ queue.push(...current);
147
+ }
148
+ else if (current && typeof current === 'object') {
149
+ for (const [key, val] of Object.entries(current)) {
150
+ if (candidateRegex.test(key))
151
+ return true;
152
+ queue.push(val);
153
+ }
154
+ }
155
+ }
156
+ return false;
157
+ }
158
+ const TERMINAL_NODE_PATTERNS = [
159
+ 'respond', 'reply', 'end', 'stop', 'terminate', 'return', 'sticky', 'note', 'noop', 'no operation',
160
+ 'slack', 'email', 'discord', 'teams', 'webhook', 'telegram', 'pushbullet', 'mattermost', 'notifier', 'notification', 'alert', 'sms', 'call',
161
+ ];
162
+ function isTerminalNode(type, name) {
163
+ const label = `${type} ${name ?? ''}`.toLowerCase();
164
+ return TERMINAL_NODE_PATTERNS.some((pattern) => label.includes(pattern));
165
+ }
166
+ function readNumber(source, paths) {
167
+ for (const path of paths) {
168
+ const value = path.split('.').reduce((acc, key) => (acc ? acc[key] : undefined), source);
169
+ if (typeof value === 'number')
170
+ return value;
171
+ if (typeof value === 'string' && !Number.isNaN(Number(value)))
172
+ return Number(value);
173
+ }
174
+ return undefined;
175
+ }
176
+ function findAllDownstreamNodes(graph, startNodeId) {
177
+ const visited = new Set();
178
+ const queue = [startNodeId];
179
+ visited.add(startNodeId);
180
+ let head = 0;
181
+ while (head < queue.length) {
182
+ const currentId = queue[head++];
183
+ const outgoing = graph.edges.filter((e) => e.from === currentId);
184
+ for (const edge of outgoing) {
185
+ if (!visited.has(edge.to)) {
186
+ visited.add(edge.to);
187
+ queue.push(edge.to);
188
+ }
189
+ }
190
+ }
191
+ return visited;
192
+ }
193
+ function findAllUpstreamNodes(graph, startNodeId) {
194
+ const visited = new Set();
195
+ const queue = [startNodeId];
196
+ visited.add(startNodeId);
197
+ let head = 0;
198
+ while (head < queue.length) {
199
+ const currentId = queue[head++];
200
+ const incoming = graph.edges.filter((e) => e.to === currentId);
201
+ for (const edge of incoming) {
202
+ if (!visited.has(edge.from)) {
203
+ visited.add(edge.from);
204
+ queue.push(edge.from);
205
+ }
206
+ }
207
+ }
208
+ return visited;
209
+ }
210
+ exports.EXAMPLES_BASE_URL = "https://github.com/Replikanti/flowlint/tree/main/flowlint-examples";
211
+ function getExampleLink(ruleId) {
212
+ return `${exports.EXAMPLES_BASE_URL}/${ruleId}`;
213
+ }
214
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../packages/review/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * GitHub API tracing wrapper
3
+ * Instruments GitHub API calls with OpenTelemetry spans
4
+ */
5
+ /**
6
+ * Wrap a GitHub API call with tracing
7
+ */
8
+ export declare function traceGitHubApiCall<T>(method: string, endpoint: string, fn: () => Promise<T>, additionalAttributes?: Record<string, string | number | boolean>): Promise<T>;
9
+ /**
10
+ * GitHub API call attributes for common operations
11
+ */
12
+ export declare const GitHubApiAttributes: {
13
+ listFiles: (owner: string, repo: string, prNumber: number) => {
14
+ 'github.repo.owner': string;
15
+ 'github.repo.name': string;
16
+ 'github.pr.number': number;
17
+ 'github.api.operation': string;
18
+ };
19
+ getContent: (owner: string, repo: string, path: string, ref: string) => {
20
+ 'github.repo.owner': string;
21
+ 'github.repo.name': string;
22
+ 'github.file.path': string;
23
+ 'github.ref': string;
24
+ 'github.api.operation': string;
25
+ };
26
+ createCheckRun: (owner: string, repo: string, sha: string) => {
27
+ 'github.repo.owner': string;
28
+ 'github.repo.name': string;
29
+ 'github.commit.sha': string;
30
+ 'github.api.operation': string;
31
+ };
32
+ updateCheckRun: (owner: string, repo: string, checkRunId: number) => {
33
+ 'github.repo.owner': string;
34
+ 'github.repo.name': string;
35
+ 'github.check_run.id': number;
36
+ 'github.api.operation': string;
37
+ };
38
+ };
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ /**
3
+ * GitHub API tracing wrapper
4
+ * Instruments GitHub API calls with OpenTelemetry spans
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.GitHubApiAttributes = void 0;
8
+ exports.traceGitHubApiCall = traceGitHubApiCall;
9
+ const index_1 = require("./index");
10
+ /**
11
+ * Wrap a GitHub API call with tracing
12
+ */
13
+ async function traceGitHubApiCall(method, endpoint, fn, additionalAttributes) {
14
+ return (0, index_1.withClientSpan)(index_1.SpanNames.GITHUB_API_CALL, async (span) => {
15
+ span.setAttributes({
16
+ 'github.api.method': method,
17
+ 'github.api.endpoint': endpoint,
18
+ 'http.method': method,
19
+ 'http.url': endpoint,
20
+ ...additionalAttributes,
21
+ });
22
+ const startTime = Date.now();
23
+ try {
24
+ const result = await fn();
25
+ const duration = Date.now() - startTime;
26
+ span.setAttributes({
27
+ 'github.api.duration_ms': duration,
28
+ 'http.status_code': 200, // Assuming success
29
+ });
30
+ span.addEvent('github.api.call.success', {
31
+ duration_ms: duration,
32
+ });
33
+ return result;
34
+ }
35
+ catch (error) {
36
+ const duration = Date.now() - startTime;
37
+ span.setAttributes({
38
+ 'github.api.duration_ms': duration,
39
+ 'github.api.error': true,
40
+ 'error.type': error instanceof Error ? error.constructor.name : 'UnknownError',
41
+ });
42
+ if (error instanceof Error) {
43
+ span.recordException(error);
44
+ }
45
+ throw error;
46
+ }
47
+ });
48
+ }
49
+ /**
50
+ * GitHub API call attributes for common operations
51
+ */
52
+ exports.GitHubApiAttributes = {
53
+ listFiles: (owner, repo, prNumber) => ({
54
+ 'github.repo.owner': owner,
55
+ 'github.repo.name': repo,
56
+ 'github.pr.number': prNumber,
57
+ 'github.api.operation': 'list_pr_files',
58
+ }),
59
+ getContent: (owner, repo, path, ref) => ({
60
+ 'github.repo.owner': owner,
61
+ 'github.repo.name': repo,
62
+ 'github.file.path': path,
63
+ 'github.ref': ref,
64
+ 'github.api.operation': 'get_content',
65
+ }),
66
+ createCheckRun: (owner, repo, sha) => ({
67
+ 'github.repo.owner': owner,
68
+ 'github.repo.name': repo,
69
+ 'github.commit.sha': sha,
70
+ 'github.api.operation': 'create_check_run',
71
+ }),
72
+ updateCheckRun: (owner, repo, checkRunId) => ({
73
+ 'github.repo.owner': owner,
74
+ 'github.repo.name': repo,
75
+ 'github.check_run.id': checkRunId,
76
+ 'github.api.operation': 'update_check_run',
77
+ }),
78
+ };
79
+ //# sourceMappingURL=github-tracer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-tracer.js","sourceRoot":"","sources":["../../../packages/tracing/github-tracer.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAQH,gDAkDC;AAxDD,mCAAoD;AAGpD;;GAEG;AACI,KAAK,UAAU,kBAAkB,CACtC,MAAc,EACd,QAAgB,EAChB,EAAoB,EACpB,oBAAgE;IAEhE,OAAO,IAAA,sBAAc,EACnB,iBAAS,CAAC,eAAe,EACzB,KAAK,EAAE,IAAU,EAAE,EAAE;QACnB,IAAI,CAAC,aAAa,CAAC;YACjB,mBAAmB,EAAE,MAAM;YAC3B,qBAAqB,EAAE,QAAQ;YAC/B,aAAa,EAAE,MAAM;YACrB,UAAU,EAAE,QAAQ;YACpB,GAAG,oBAAoB;SACxB,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAExC,IAAI,CAAC,aAAa,CAAC;gBACjB,wBAAwB,EAAE,QAAQ;gBAClC,kBAAkB,EAAE,GAAG,EAAE,mBAAmB;aAC7C,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,yBAAyB,EAAE;gBACvC,WAAW,EAAE,QAAQ;aACtB,CAAC,CAAC;YAEH,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAExC,IAAI,CAAC,aAAa,CAAC;gBACjB,wBAAwB,EAAE,QAAQ;gBAClC,kBAAkB,EAAE,IAAI;gBACxB,YAAY,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc;aAC/E,CAAC,CAAC;YAEH,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;YAED,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACU,QAAA,mBAAmB,GAAG;IACjC,SAAS,EAAE,CAAC,KAAa,EAAE,IAAY,EAAE,QAAgB,EAAE,EAAE,CAAC,CAAC;QAC7D,mBAAmB,EAAE,KAAK;QAC1B,kBAAkB,EAAE,IAAI;QACxB,kBAAkB,EAAE,QAAQ;QAC5B,sBAAsB,EAAE,eAAe;KACxC,CAAC;IAEF,UAAU,EAAE,CAAC,KAAa,EAAE,IAAY,EAAE,IAAY,EAAE,GAAW,EAAE,EAAE,CAAC,CAAC;QACvE,mBAAmB,EAAE,KAAK;QAC1B,kBAAkB,EAAE,IAAI;QACxB,kBAAkB,EAAE,IAAI;QACxB,YAAY,EAAE,GAAG;QACjB,sBAAsB,EAAE,aAAa;KACtC,CAAC;IAEF,cAAc,EAAE,CAAC,KAAa,EAAE,IAAY,EAAE,GAAW,EAAE,EAAE,CAAC,CAAC;QAC7D,mBAAmB,EAAE,KAAK;QAC1B,kBAAkB,EAAE,IAAI;QACxB,mBAAmB,EAAE,GAAG;QACxB,sBAAsB,EAAE,kBAAkB;KAC3C,CAAC;IAEF,cAAc,EAAE,CAAC,KAAa,EAAE,IAAY,EAAE,UAAkB,EAAE,EAAE,CAAC,CAAC;QACpE,mBAAmB,EAAE,KAAK;QAC1B,kBAAkB,EAAE,IAAI;QACxB,qBAAqB,EAAE,UAAU;QACjC,sBAAsB,EAAE,kBAAkB;KAC3C,CAAC;CACH,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * FlowLint Distributed Tracing Package
3
+ *
4
+ * Provides OpenTelemetry-based distributed tracing for FlowLint.
5
+ * Tracks request flow from webhook reception through job processing to Check Run creation.
6
+ *
7
+ * @module packages/tracing
8
+ */
9
+ import { Tracer, Span, SpanStatusCode, Context, context, trace, propagation } from '@opentelemetry/api';
10
+ /**
11
+ * Trace span names following OpenTelemetry semantic conventions
12
+ */
13
+ export declare const SpanNames: {
14
+ readonly WEBHOOK_RECEIVED: "webhook.received";
15
+ readonly WEBHOOK_VERIFY_SIGNATURE: "webhook.verify_signature";
16
+ readonly JOB_ENQUEUED: "job.enqueued";
17
+ readonly JOB_PROCESSED: "job.processed";
18
+ readonly JOB_FETCH_FILES: "job.fetch_files";
19
+ readonly JOB_LOAD_CONFIG: "job.load_config";
20
+ readonly JOB_PARSE_WORKFLOW: "job.parse_workflow";
21
+ readonly JOB_RUN_RULES: "job.run_rules";
22
+ readonly JOB_CREATE_CHECK_RUN: "job.create_check_run";
23
+ readonly GITHUB_API_CALL: "github.api_call";
24
+ readonly LINT_RULE_EXECUTE: "lint.rule.execute";
25
+ readonly REDIS_OPERATION: "redis.operation";
26
+ };
27
+ /**
28
+ * Get the configured tracer instance
29
+ */
30
+ export declare function getTracerInstance(): Tracer;
31
+ /**
32
+ * Start a new span with the given name and attributes
33
+ */
34
+ export declare function startSpan(name: string, attributes?: Record<string, string | number | boolean>, parentContext?: Context): Span;
35
+ /**
36
+ * Start a server span (for incoming requests)
37
+ */
38
+ export declare function startServerSpan(name: string, attributes?: Record<string, string | number | boolean>, parentContext?: Context): Span;
39
+ /**
40
+ * Start a client span (for outgoing requests)
41
+ */
42
+ export declare function startClientSpan(name: string, attributes?: Record<string, string | number | boolean>, parentContext?: Context): Span;
43
+ /**
44
+ * Execute a function within a span context
45
+ */
46
+ export declare function withSpan<T>(name: string, fn: (span: Span) => Promise<T>, attributes?: Record<string, string | number | boolean>, parentContext?: Context): Promise<T>;
47
+ /**
48
+ * Execute a synchronous function within a span context
49
+ */
50
+ export declare function withSpanSync<T>(name: string, fn: (span: Span) => T, attributes?: Record<string, string | number | boolean>, parentContext?: Context): T;
51
+ /**
52
+ * Execute a function within a server span context (for incoming requests)
53
+ */
54
+ export declare function withServerSpan<T>(name: string, fn: (span: Span) => Promise<T>, attributes?: Record<string, string | number | boolean>, parentContext?: Context): Promise<T>;
55
+ /**
56
+ * Execute a function within a client span context (for outgoing requests)
57
+ */
58
+ export declare function withClientSpan<T>(name: string, fn: (span: Span) => Promise<T>, attributes?: Record<string, string | number | boolean>, parentContext?: Context): Promise<T>;
59
+ /**
60
+ * Add an event to the current active span
61
+ */
62
+ export declare function addSpanEvent(name: string, attributes?: Record<string, string | number | boolean>): void;
63
+ /**
64
+ * Set attributes on the current active span
65
+ */
66
+ export declare function setSpanAttributes(attributes: Record<string, string | number | boolean>): void;
67
+ /**
68
+ * Record an exception on the current active span
69
+ */
70
+ export declare function recordSpanException(error: Error): void;
71
+ /**
72
+ * Get the current active span
73
+ */
74
+ export declare function getActiveSpan(): Span | undefined;
75
+ /**
76
+ * Get the current trace context
77
+ */
78
+ export declare function getActiveContext(): Context;
79
+ export { Span, SpanStatusCode, Context, trace, context, propagation };
80
+ export { initTracing, shutdownTracing } from './tracer';
81
+ export { traceGitHubApiCall, GitHubApiAttributes } from './github-tracer';
@@ -0,0 +1,240 @@
1
+ "use strict";
2
+ /**
3
+ * FlowLint Distributed Tracing Package
4
+ *
5
+ * Provides OpenTelemetry-based distributed tracing for FlowLint.
6
+ * Tracks request flow from webhook reception through job processing to Check Run creation.
7
+ *
8
+ * @module packages/tracing
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.GitHubApiAttributes = exports.traceGitHubApiCall = exports.shutdownTracing = exports.initTracing = exports.propagation = exports.context = exports.trace = exports.SpanStatusCode = exports.SpanNames = void 0;
12
+ exports.getTracerInstance = getTracerInstance;
13
+ exports.startSpan = startSpan;
14
+ exports.startServerSpan = startServerSpan;
15
+ exports.startClientSpan = startClientSpan;
16
+ exports.withSpan = withSpan;
17
+ exports.withSpanSync = withSpanSync;
18
+ exports.withServerSpan = withServerSpan;
19
+ exports.withClientSpan = withClientSpan;
20
+ exports.addSpanEvent = addSpanEvent;
21
+ exports.setSpanAttributes = setSpanAttributes;
22
+ exports.recordSpanException = recordSpanException;
23
+ exports.getActiveSpan = getActiveSpan;
24
+ exports.getActiveContext = getActiveContext;
25
+ const api_1 = require("@opentelemetry/api");
26
+ Object.defineProperty(exports, "SpanStatusCode", { enumerable: true, get: function () { return api_1.SpanStatusCode; } });
27
+ Object.defineProperty(exports, "context", { enumerable: true, get: function () { return api_1.context; } });
28
+ Object.defineProperty(exports, "trace", { enumerable: true, get: function () { return api_1.trace; } });
29
+ Object.defineProperty(exports, "propagation", { enumerable: true, get: function () { return api_1.propagation; } });
30
+ const tracer_1 = require("./tracer");
31
+ /**
32
+ * Trace span names following OpenTelemetry semantic conventions
33
+ */
34
+ exports.SpanNames = {
35
+ WEBHOOK_RECEIVED: 'webhook.received',
36
+ WEBHOOK_VERIFY_SIGNATURE: 'webhook.verify_signature',
37
+ JOB_ENQUEUED: 'job.enqueued',
38
+ JOB_PROCESSED: 'job.processed',
39
+ JOB_FETCH_FILES: 'job.fetch_files',
40
+ JOB_LOAD_CONFIG: 'job.load_config',
41
+ JOB_PARSE_WORKFLOW: 'job.parse_workflow',
42
+ JOB_RUN_RULES: 'job.run_rules',
43
+ JOB_CREATE_CHECK_RUN: 'job.create_check_run',
44
+ GITHUB_API_CALL: 'github.api_call',
45
+ LINT_RULE_EXECUTE: 'lint.rule.execute',
46
+ REDIS_OPERATION: 'redis.operation',
47
+ };
48
+ /**
49
+ * Get the configured tracer instance
50
+ */
51
+ function getTracerInstance() {
52
+ return (0, tracer_1.getTracer)();
53
+ }
54
+ /**
55
+ * Start a new span with the given name and attributes
56
+ */
57
+ function startSpan(name, attributes, parentContext) {
58
+ const tracer = (0, tracer_1.getTracer)();
59
+ const ctx = parentContext || api_1.context.active();
60
+ return tracer.startSpan(name, {
61
+ kind: api_1.SpanKind.INTERNAL,
62
+ attributes,
63
+ }, ctx);
64
+ }
65
+ /**
66
+ * Start a server span (for incoming requests)
67
+ */
68
+ function startServerSpan(name, attributes, parentContext) {
69
+ const tracer = (0, tracer_1.getTracer)();
70
+ const ctx = parentContext || api_1.context.active();
71
+ return tracer.startSpan(name, {
72
+ kind: api_1.SpanKind.SERVER,
73
+ attributes,
74
+ }, ctx);
75
+ }
76
+ /**
77
+ * Start a client span (for outgoing requests)
78
+ */
79
+ function startClientSpan(name, attributes, parentContext) {
80
+ const tracer = (0, tracer_1.getTracer)();
81
+ const ctx = parentContext || api_1.context.active();
82
+ return tracer.startSpan(name, {
83
+ kind: api_1.SpanKind.CLIENT,
84
+ attributes,
85
+ }, ctx);
86
+ }
87
+ /**
88
+ * Execute a function within a span context
89
+ */
90
+ async function withSpan(name, fn, attributes, parentContext) {
91
+ const baseContext = parentContext || api_1.context.active();
92
+ const span = startSpan(name, attributes, parentContext);
93
+ const ctxWithSpan = api_1.trace.setSpan(baseContext, span);
94
+ try {
95
+ const result = await api_1.context.with(ctxWithSpan, () => fn(span));
96
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
97
+ return result;
98
+ }
99
+ catch (error) {
100
+ span.setStatus({
101
+ code: api_1.SpanStatusCode.ERROR,
102
+ message: error instanceof Error ? error.message : 'Unknown error',
103
+ });
104
+ if (error instanceof Error) {
105
+ span.recordException(error);
106
+ }
107
+ throw error;
108
+ }
109
+ finally {
110
+ span.end();
111
+ }
112
+ }
113
+ /**
114
+ * Execute a synchronous function within a span context
115
+ */
116
+ function withSpanSync(name, fn, attributes, parentContext) {
117
+ const baseContext = parentContext || api_1.context.active();
118
+ const span = startSpan(name, attributes, parentContext);
119
+ const ctxWithSpan = api_1.trace.setSpan(baseContext, span);
120
+ try {
121
+ const result = api_1.context.with(ctxWithSpan, () => fn(span));
122
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
123
+ return result;
124
+ }
125
+ catch (error) {
126
+ span.setStatus({
127
+ code: api_1.SpanStatusCode.ERROR,
128
+ message: error instanceof Error ? error.message : 'Unknown error',
129
+ });
130
+ if (error instanceof Error) {
131
+ span.recordException(error);
132
+ }
133
+ throw error;
134
+ }
135
+ finally {
136
+ span.end();
137
+ }
138
+ }
139
+ /**
140
+ * Execute a function within a server span context (for incoming requests)
141
+ */
142
+ async function withServerSpan(name, fn, attributes, parentContext) {
143
+ const baseContext = parentContext || api_1.context.active();
144
+ const span = startServerSpan(name, attributes, parentContext);
145
+ const ctxWithSpan = api_1.trace.setSpan(baseContext, span);
146
+ try {
147
+ const result = await api_1.context.with(ctxWithSpan, () => fn(span));
148
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
149
+ return result;
150
+ }
151
+ catch (error) {
152
+ span.setStatus({
153
+ code: api_1.SpanStatusCode.ERROR,
154
+ message: error instanceof Error ? error.message : 'Unknown error',
155
+ });
156
+ if (error instanceof Error) {
157
+ span.recordException(error);
158
+ }
159
+ throw error;
160
+ }
161
+ finally {
162
+ span.end();
163
+ }
164
+ }
165
+ /**
166
+ * Execute a function within a client span context (for outgoing requests)
167
+ */
168
+ async function withClientSpan(name, fn, attributes, parentContext) {
169
+ const baseContext = parentContext || api_1.context.active();
170
+ const span = startClientSpan(name, attributes, parentContext);
171
+ const ctxWithSpan = api_1.trace.setSpan(baseContext, span);
172
+ try {
173
+ const result = await api_1.context.with(ctxWithSpan, () => fn(span));
174
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
175
+ return result;
176
+ }
177
+ catch (error) {
178
+ span.setStatus({
179
+ code: api_1.SpanStatusCode.ERROR,
180
+ message: error instanceof Error ? error.message : 'Unknown error',
181
+ });
182
+ if (error instanceof Error) {
183
+ span.recordException(error);
184
+ }
185
+ throw error;
186
+ }
187
+ finally {
188
+ span.end();
189
+ }
190
+ }
191
+ /**
192
+ * Add an event to the current active span
193
+ */
194
+ function addSpanEvent(name, attributes) {
195
+ const span = api_1.trace.getActiveSpan();
196
+ if (span) {
197
+ span.addEvent(name, attributes);
198
+ }
199
+ }
200
+ /**
201
+ * Set attributes on the current active span
202
+ */
203
+ function setSpanAttributes(attributes) {
204
+ const span = api_1.trace.getActiveSpan();
205
+ if (span) {
206
+ span.setAttributes(attributes);
207
+ }
208
+ }
209
+ /**
210
+ * Record an exception on the current active span
211
+ */
212
+ function recordSpanException(error) {
213
+ const span = api_1.trace.getActiveSpan();
214
+ if (span) {
215
+ span.recordException(error);
216
+ span.setStatus({
217
+ code: api_1.SpanStatusCode.ERROR,
218
+ message: error.message,
219
+ });
220
+ }
221
+ }
222
+ /**
223
+ * Get the current active span
224
+ */
225
+ function getActiveSpan() {
226
+ return api_1.trace.getActiveSpan();
227
+ }
228
+ /**
229
+ * Get the current trace context
230
+ */
231
+ function getActiveContext() {
232
+ return api_1.context.active();
233
+ }
234
+ var tracer_2 = require("./tracer");
235
+ Object.defineProperty(exports, "initTracing", { enumerable: true, get: function () { return tracer_2.initTracing; } });
236
+ Object.defineProperty(exports, "shutdownTracing", { enumerable: true, get: function () { return tracer_2.shutdownTracing; } });
237
+ var github_tracer_1 = require("./github-tracer");
238
+ Object.defineProperty(exports, "traceGitHubApiCall", { enumerable: true, get: function () { return github_tracer_1.traceGitHubApiCall; } });
239
+ Object.defineProperty(exports, "GitHubApiAttributes", { enumerable: true, get: function () { return github_tracer_1.GitHubApiAttributes; } });
240
+ //# sourceMappingURL=index.js.map