@descryy/runtime-adapter-ruby 0.0.0
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.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/rails-frame-parsing.d.ts +105 -0
- package/dist/rails-frame-parsing.d.ts.map +1 -0
- package/dist/rails-frame-parsing.js +183 -0
- package/dist/rails-frame-parsing.js.map +1 -0
- package/dist/rails-stack-trace-parser.d.ts +31 -0
- package/dist/rails-stack-trace-parser.d.ts.map +1 -0
- package/dist/rails-stack-trace-parser.js +63 -0
- package/dist/rails-stack-trace-parser.js.map +1 -0
- package/dist/ruby-frame-parsing.d.ts +78 -0
- package/dist/ruby-frame-parsing.d.ts.map +1 -0
- package/dist/ruby-frame-parsing.js +108 -0
- package/dist/ruby-frame-parsing.js.map +1 -0
- package/dist/ruby-log-envelopes.d.ts +101 -0
- package/dist/ruby-log-envelopes.d.ts.map +1 -0
- package/dist/ruby-log-envelopes.js +214 -0
- package/dist/ruby-log-envelopes.js.map +1 -0
- package/dist/ruby-runtime-adapter.d.ts +51 -0
- package/dist/ruby-runtime-adapter.d.ts.map +1 -0
- package/dist/ruby-runtime-adapter.js +56 -0
- package/dist/ruby-runtime-adapter.js.map +1 -0
- package/dist/ruby-source-location-resolver.d.ts +34 -0
- package/dist/ruby-source-location-resolver.d.ts.map +1 -0
- package/dist/ruby-source-location-resolver.js +61 -0
- package/dist/ruby-source-location-resolver.js.map +1 -0
- package/dist/ruby-stack-trace-parser.d.ts +24 -0
- package/dist/ruby-stack-trace-parser.d.ts.map +1 -0
- package/dist/ruby-stack-trace-parser.js +71 -0
- package/dist/ruby-stack-trace-parser.js.map +1 -0
- package/dist/sinatra-frame-parsing.d.ts +92 -0
- package/dist/sinatra-frame-parsing.d.ts.map +1 -0
- package/dist/sinatra-frame-parsing.js +142 -0
- package/dist/sinatra-frame-parsing.js.map +1 -0
- package/dist/sinatra-stack-trace-parser.d.ts +18 -0
- package/dist/sinatra-stack-trace-parser.d.ts.map +1 -0
- package/dist/sinatra-stack-trace-parser.js +50 -0
- package/dist/sinatra-stack-trace-parser.js.map +1 -0
- package/package.json +30 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ruby-stack-trace-parser.js","sourceRoot":"","sources":["../src/ruby-stack-trace-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAEnF,MAAM,UAAU,0BAA0B,CAAC,QAAgC;IACzE,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,OAAe;YACzB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAE1C,MAAM,MAAM,GAAiB,EAAE,CAAC;YAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,mEAAmE;gBACnE,kEAAkE;gBAClE,6DAA6D;gBAC7D,4DAA4D;gBAC5D,MAAM,GAAG,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC;gBACnE,IAAI,GAAG,KAAK,IAAI;oBAAE,SAAS;gBAE3B,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;oBACtC,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,MAAM,EAAE,IAAI;oBACZ,YAAY,EAAE,GAAG,CAAC,YAAY;iBAC/B,CAAC,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;YACvC,CAAC;YAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,2DAA2D;gBAC3D,2DAA2D;gBAC3D,oEAAoE;gBACpE,OAAO,IAAI,CAAC;YACd,CAAC;YAED,kEAAkE;YAClE,mEAAmE;YACnE,oEAAoE;YACpE,qEAAqE;YACrE,sEAAsE;YACtE,mEAAmE;YACnE,oCAAoC;YACpC,EAAE;YACF,gEAAgE;YAChE,kEAAkE;YAClE,oBAAoB;YACpB,oEAAoE;YACpE,sEAAsE;YACtE,mEAAmE;YACnE,iEAAiE;YACjE,mEAAmE;YACnE,mEAAmE;YACnE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC;QACnE,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sinatra's production-mode backtrace grammar, which is **not Ruby's** —
|
|
3
|
+
* the plan's 1C measurement, and Sinatra's own answer to the question
|
|
4
|
+
* `rails-frame-parsing.ts` asked of Rails.
|
|
5
|
+
*
|
|
6
|
+
* ## The measurement
|
|
7
|
+
*
|
|
8
|
+
* A real Sinatra 4.1.1 app, `set :environment, :production`, spawned
|
|
9
|
+
* through the managed lifecycle, failing through its own request pipeline:
|
|
10
|
+
*
|
|
11
|
+
* ```
|
|
12
|
+
* 2026-08-21 00:27:09 - RuntimeError - invoice 3 is corrupt (RuntimeError):
|
|
13
|
+
* sinatra_service.rb:44:in 'Object#charge_invoice'
|
|
14
|
+
* sinatra_service.rb:51:in 'Object#delete_invoice'
|
|
15
|
+
* ...
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* against Ruby's own printer, which the plain `ruby-frame-parsing.ts`
|
|
19
|
+
* classifier expects:
|
|
20
|
+
*
|
|
21
|
+
* ```
|
|
22
|
+
* sinatra_service.rb:44:in 'Object#charge_invoice': invoice 3 is corrupt (RuntimeError)
|
|
23
|
+
* from sinatra_service.rb:51:in 'Object#delete_invoice'
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Read off `Sinatra::Base#dump_errors!` (`sinatra/base.rb`) before this was
|
|
27
|
+
* run, then confirmed against the live process, matching exactly:
|
|
28
|
+
*
|
|
29
|
+
* ```ruby
|
|
30
|
+
* msg = ["#{Time.now...} - #{boom.class} - #{msg}:", *additional_msg, *boom.backtrace].join("\n\t")
|
|
31
|
+
* @env['rack.errors'].puts(msg)
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* - **The header carries no location.** It is
|
|
35
|
+
* `TIMESTAMP - ClassName - message:`, never `file:line:in 'name': message`,
|
|
36
|
+
* so `HEADER_PATTERN` never matches it.
|
|
37
|
+
* - **The frames have no `from` prefix.** `boom.backtrace` is the raw
|
|
38
|
+
* `Exception#backtrace` array — Ruby's own top-level printer is what adds
|
|
39
|
+
* `from `, not `Exception#backtrace` itself — so `FROM_FRAME_PATTERN`
|
|
40
|
+
* never matches them either.
|
|
41
|
+
*
|
|
42
|
+
* Result, measured against the live process rather than assumed:
|
|
43
|
+
* **0 headers, 0 frames** — RT-111's exact signature, on the framework
|
|
44
|
+
* built directly on Rack rather than on Rack itself. (Bare Rack — no
|
|
45
|
+
* framework at all — was also measured, in `rack-framework-lifecycle.test.ts`,
|
|
46
|
+
* and needed no new grammar: its dispatch frames print in Ruby's own
|
|
47
|
+
* `file:line:in 'name'` / `from ...` shape and the existing classifier
|
|
48
|
+
* reads them unchanged.)
|
|
49
|
+
*
|
|
50
|
+
* ## Why this is a third classifier, not a widened Rails one
|
|
51
|
+
*
|
|
52
|
+
* Sinatra's header shape (`TIMESTAMP - Class - message:`) and Rails'
|
|
53
|
+
* (`Class (message):`) are different enough that one pattern covering both
|
|
54
|
+
* would have to be loose enough to risk matching an application's own log
|
|
55
|
+
* line — the same rule that ruled out widening Ruby's `isFrame` for Rails
|
|
56
|
+
* (see `rails-frame-parsing.ts`). The bare `file:line:in 'name'` frame shape
|
|
57
|
+
* *is* identical to Rails' — both are literally `Exception#backtrace`
|
|
58
|
+
* entries with no `from` — but is kept as its own pattern here rather than
|
|
59
|
+
* imported from `rails-frame-parsing.ts`, so a change scoped to one
|
|
60
|
+
* framework's grammar can never silently reach the other's.
|
|
61
|
+
*
|
|
62
|
+
* `isFrame` is stateful for the same reason Rails' is: a bare
|
|
63
|
+
* `file:line:in 'name'` is confined to "after a header has been seen" so it
|
|
64
|
+
* can never open a block from idle on its own.
|
|
65
|
+
*/
|
|
66
|
+
export interface RawSinatraFrame {
|
|
67
|
+
/** `Object#charge_invoice`, `block in Sinatra::Base#dispatch!` — kept verbatim, never rewritten. */
|
|
68
|
+
readonly functionName: string | null;
|
|
69
|
+
readonly file: string;
|
|
70
|
+
readonly line: number;
|
|
71
|
+
}
|
|
72
|
+
export declare function isSinatraHeaderLine(line: string): boolean;
|
|
73
|
+
export declare function isSinatraFrameLine(line: string): boolean;
|
|
74
|
+
/** `null` when the line is not `TIMESTAMP - Class - message:` shaped — never fabricated. */
|
|
75
|
+
export declare function parseSinatraHeader(line: string): {
|
|
76
|
+
readonly exceptionClass: string;
|
|
77
|
+
readonly message: string;
|
|
78
|
+
} | null;
|
|
79
|
+
/** `null` for anything not shaped like a bare `file:line:in 'name'` frame — never fabricated. */
|
|
80
|
+
export declare function parseSinatraFrame(line: string): RawSinatraFrame | null;
|
|
81
|
+
/**
|
|
82
|
+
* A stateful `LineClassifier` — see this file's header for why the loose
|
|
83
|
+
* frame pattern is safe only inside that state.
|
|
84
|
+
*
|
|
85
|
+
* A fresh classifier per collector keeps two processes' output from priming
|
|
86
|
+
* each other, the same construction rule every other adapter here follows.
|
|
87
|
+
*/
|
|
88
|
+
export declare function createSinatraLineClassifier(): {
|
|
89
|
+
isHeader(line: string): boolean;
|
|
90
|
+
isFrame(line: string): boolean;
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=sinatra-frame-parsing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sinatra-frame-parsing.d.ts","sourceRoot":"","sources":["../src/sinatra-frame-parsing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AAEH,MAAM,WAAW,eAAe;IAC9B,oGAAoG;IACpG,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAwBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAMrH;AAED,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAOtE;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,IAAI;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC,CAqBA"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sinatra's production-mode backtrace grammar, which is **not Ruby's** —
|
|
3
|
+
* the plan's 1C measurement, and Sinatra's own answer to the question
|
|
4
|
+
* `rails-frame-parsing.ts` asked of Rails.
|
|
5
|
+
*
|
|
6
|
+
* ## The measurement
|
|
7
|
+
*
|
|
8
|
+
* A real Sinatra 4.1.1 app, `set :environment, :production`, spawned
|
|
9
|
+
* through the managed lifecycle, failing through its own request pipeline:
|
|
10
|
+
*
|
|
11
|
+
* ```
|
|
12
|
+
* 2026-08-21 00:27:09 - RuntimeError - invoice 3 is corrupt (RuntimeError):
|
|
13
|
+
* sinatra_service.rb:44:in 'Object#charge_invoice'
|
|
14
|
+
* sinatra_service.rb:51:in 'Object#delete_invoice'
|
|
15
|
+
* ...
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* against Ruby's own printer, which the plain `ruby-frame-parsing.ts`
|
|
19
|
+
* classifier expects:
|
|
20
|
+
*
|
|
21
|
+
* ```
|
|
22
|
+
* sinatra_service.rb:44:in 'Object#charge_invoice': invoice 3 is corrupt (RuntimeError)
|
|
23
|
+
* from sinatra_service.rb:51:in 'Object#delete_invoice'
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Read off `Sinatra::Base#dump_errors!` (`sinatra/base.rb`) before this was
|
|
27
|
+
* run, then confirmed against the live process, matching exactly:
|
|
28
|
+
*
|
|
29
|
+
* ```ruby
|
|
30
|
+
* msg = ["#{Time.now...} - #{boom.class} - #{msg}:", *additional_msg, *boom.backtrace].join("\n\t")
|
|
31
|
+
* @env['rack.errors'].puts(msg)
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* - **The header carries no location.** It is
|
|
35
|
+
* `TIMESTAMP - ClassName - message:`, never `file:line:in 'name': message`,
|
|
36
|
+
* so `HEADER_PATTERN` never matches it.
|
|
37
|
+
* - **The frames have no `from` prefix.** `boom.backtrace` is the raw
|
|
38
|
+
* `Exception#backtrace` array — Ruby's own top-level printer is what adds
|
|
39
|
+
* `from `, not `Exception#backtrace` itself — so `FROM_FRAME_PATTERN`
|
|
40
|
+
* never matches them either.
|
|
41
|
+
*
|
|
42
|
+
* Result, measured against the live process rather than assumed:
|
|
43
|
+
* **0 headers, 0 frames** — RT-111's exact signature, on the framework
|
|
44
|
+
* built directly on Rack rather than on Rack itself. (Bare Rack — no
|
|
45
|
+
* framework at all — was also measured, in `rack-framework-lifecycle.test.ts`,
|
|
46
|
+
* and needed no new grammar: its dispatch frames print in Ruby's own
|
|
47
|
+
* `file:line:in 'name'` / `from ...` shape and the existing classifier
|
|
48
|
+
* reads them unchanged.)
|
|
49
|
+
*
|
|
50
|
+
* ## Why this is a third classifier, not a widened Rails one
|
|
51
|
+
*
|
|
52
|
+
* Sinatra's header shape (`TIMESTAMP - Class - message:`) and Rails'
|
|
53
|
+
* (`Class (message):`) are different enough that one pattern covering both
|
|
54
|
+
* would have to be loose enough to risk matching an application's own log
|
|
55
|
+
* line — the same rule that ruled out widening Ruby's `isFrame` for Rails
|
|
56
|
+
* (see `rails-frame-parsing.ts`). The bare `file:line:in 'name'` frame shape
|
|
57
|
+
* *is* identical to Rails' — both are literally `Exception#backtrace`
|
|
58
|
+
* entries with no `from` — but is kept as its own pattern here rather than
|
|
59
|
+
* imported from `rails-frame-parsing.ts`, so a change scoped to one
|
|
60
|
+
* framework's grammar can never silently reach the other's.
|
|
61
|
+
*
|
|
62
|
+
* `isFrame` is stateful for the same reason Rails' is: a bare
|
|
63
|
+
* `file:line:in 'name'` is confined to "after a header has been seen" so it
|
|
64
|
+
* can never open a block from idle on its own.
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* `2026-08-21 00:27:09 - RuntimeError - invoice 3 is corrupt (RuntimeError):`
|
|
68
|
+
*
|
|
69
|
+
* `Sinatra::Base#dump_errors!` composes
|
|
70
|
+
* `"#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} - #{boom.class} - #{msg}:"`.
|
|
71
|
+
* Anchored at the start (the timestamp is always first — Sinatra never
|
|
72
|
+
* prefixes it, unlike Ruby's own header pattern which allows a leading
|
|
73
|
+
* logger prefix) and requiring the trailing `:`, because a partial match is
|
|
74
|
+
* evidence the line is not a header rather than a reason to guess at one.
|
|
75
|
+
* The class group allows `::` so a namespaced error class matches.
|
|
76
|
+
*/
|
|
77
|
+
const SINATRA_HEADER = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} - (?<class>[A-Z][A-Za-z0-9_]*(?:::[A-Z][A-Za-z0-9_]*)*) - (?<message>.*):\s*$/;
|
|
78
|
+
/**
|
|
79
|
+
* `sinatra_service.rb:44:in 'Object#charge_invoice'` — a raw
|
|
80
|
+
* `Exception#backtrace` entry, tab-indented by `dump_errors!`'s own
|
|
81
|
+
* `join("\n\t")`, no `from` prefix. The closing quote is always `'`; only
|
|
82
|
+
* the opening one varies by Ruby version (Feature #16495), matched the same
|
|
83
|
+
* way Ruby's and Rails' own patterns do.
|
|
84
|
+
*/
|
|
85
|
+
const SINATRA_FRAME = /^\s*(?<file>.+):(?<line>\d+):in\s+[`'](?<fn>[^']*)'\s*$/;
|
|
86
|
+
export function isSinatraHeaderLine(line) {
|
|
87
|
+
return SINATRA_HEADER.test(line);
|
|
88
|
+
}
|
|
89
|
+
export function isSinatraFrameLine(line) {
|
|
90
|
+
return SINATRA_FRAME.test(line);
|
|
91
|
+
}
|
|
92
|
+
/** `null` when the line is not `TIMESTAMP - Class - message:` shaped — never fabricated. */
|
|
93
|
+
export function parseSinatraHeader(line) {
|
|
94
|
+
const match = SINATRA_HEADER.exec(line);
|
|
95
|
+
if (!match?.groups)
|
|
96
|
+
return null;
|
|
97
|
+
const exceptionClass = match.groups["class"];
|
|
98
|
+
if (exceptionClass === undefined)
|
|
99
|
+
return null;
|
|
100
|
+
return { exceptionClass, message: match.groups["message"] ?? "" };
|
|
101
|
+
}
|
|
102
|
+
/** `null` for anything not shaped like a bare `file:line:in 'name'` frame — never fabricated. */
|
|
103
|
+
export function parseSinatraFrame(line) {
|
|
104
|
+
const match = SINATRA_FRAME.exec(line);
|
|
105
|
+
if (!match?.groups)
|
|
106
|
+
return null;
|
|
107
|
+
const file = match.groups["file"];
|
|
108
|
+
const lineNumber = Number(match.groups["line"]);
|
|
109
|
+
if (file === undefined || !Number.isInteger(lineNumber))
|
|
110
|
+
return null;
|
|
111
|
+
return { functionName: match.groups["fn"] ?? null, file, line: lineNumber };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* A stateful `LineClassifier` — see this file's header for why the loose
|
|
115
|
+
* frame pattern is safe only inside that state.
|
|
116
|
+
*
|
|
117
|
+
* A fresh classifier per collector keeps two processes' output from priming
|
|
118
|
+
* each other, the same construction rule every other adapter here follows.
|
|
119
|
+
*/
|
|
120
|
+
export function createSinatraLineClassifier() {
|
|
121
|
+
let sawHeader = false;
|
|
122
|
+
return {
|
|
123
|
+
isHeader(line) {
|
|
124
|
+
if (isSinatraHeaderLine(line)) {
|
|
125
|
+
sawHeader = true;
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
},
|
|
130
|
+
isFrame(line) {
|
|
131
|
+
// Never from idle. A bare `x.rb:12:in 'foo'` is frame-shaped and is
|
|
132
|
+
// also an entirely ordinary thing for an application to log.
|
|
133
|
+
if (!sawHeader)
|
|
134
|
+
return false;
|
|
135
|
+
if (isSinatraFrameLine(line))
|
|
136
|
+
return true;
|
|
137
|
+
sawHeader = false;
|
|
138
|
+
return false;
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=sinatra-frame-parsing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sinatra-frame-parsing.js","sourceRoot":"","sources":["../src/sinatra-frame-parsing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AASH;;;;;;;;;;GAUG;AACH,MAAM,cAAc,GAAG,oHAAoH,CAAC;AAE5I;;;;;;GAMG;AACH,MAAM,aAAa,GAAG,yDAAyD,CAAC;AAEhF,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,CAAC,KAAK,EAAE,MAAM;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,cAAc,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC9C,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;AACpE,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,EAAE,MAAM;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAChD,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACrE,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;AAC9E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B;IAIzC,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,OAAO;QACL,QAAQ,CAAC,IAAY;YACnB,IAAI,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,SAAS,GAAG,IAAI,CAAC;gBACjB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,CAAC,IAAY;YAClB,oEAAoE;YACpE,6DAA6D;YAC7D,IAAI,CAAC,SAAS;gBAAE,OAAO,KAAK,CAAC;YAC7B,IAAI,kBAAkB,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC1C,SAAS,GAAG,KAAK,CAAC;YAClB,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composes Sinatra's line-recognition functions with a
|
|
3
|
+
* `SourceLocationResolver` (plan 1C, mirroring `rails-stack-trace-parser.ts`).
|
|
4
|
+
*
|
|
5
|
+
* Sinatra's header carries **no location at all** —
|
|
6
|
+
* `TIMESTAMP - Class - message:` — so, exactly as for Rails, the raise site
|
|
7
|
+
* is the first backtrace line beneath the header rather than the header
|
|
8
|
+
* itself. `primaryFrameIndex` is `0` for the same reason Rails' is: the
|
|
9
|
+
* header contributes no frame, so index 0 is the first line Sinatra
|
|
10
|
+
* printed, and `Exception#backtrace` is innermost-first.
|
|
11
|
+
*
|
|
12
|
+
* `fidelity` is `"synchronous"` for the same reason every other Ruby
|
|
13
|
+
* parser's is: every frame is a genuine link in the call chain that was
|
|
14
|
+
* executing.
|
|
15
|
+
*/
|
|
16
|
+
import type { SourceLocationResolver, StackTraceParser } from "@descryy/runtime-backend-observation";
|
|
17
|
+
export declare function createSinatraStackTraceParser(resolver: SourceLocationResolver): StackTraceParser;
|
|
18
|
+
//# sourceMappingURL=sinatra-stack-trace-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sinatra-stack-trace-parser.d.ts","sourceRoot":"","sources":["../src/sinatra-stack-trace-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAIrG,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,sBAAsB,GAAG,gBAAgB,CAkChG"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composes Sinatra's line-recognition functions with a
|
|
3
|
+
* `SourceLocationResolver` (plan 1C, mirroring `rails-stack-trace-parser.ts`).
|
|
4
|
+
*
|
|
5
|
+
* Sinatra's header carries **no location at all** —
|
|
6
|
+
* `TIMESTAMP - Class - message:` — so, exactly as for Rails, the raise site
|
|
7
|
+
* is the first backtrace line beneath the header rather than the header
|
|
8
|
+
* itself. `primaryFrameIndex` is `0` for the same reason Rails' is: the
|
|
9
|
+
* header contributes no frame, so index 0 is the first line Sinatra
|
|
10
|
+
* printed, and `Exception#backtrace` is innermost-first.
|
|
11
|
+
*
|
|
12
|
+
* `fidelity` is `"synchronous"` for the same reason every other Ruby
|
|
13
|
+
* parser's is: every frame is a genuine link in the call chain that was
|
|
14
|
+
* executing.
|
|
15
|
+
*/
|
|
16
|
+
import { parseSinatraFrame, parseSinatraHeader } from "./sinatra-frame-parsing.js";
|
|
17
|
+
export function createSinatraStackTraceParser(resolver) {
|
|
18
|
+
return {
|
|
19
|
+
async parse(rawText) {
|
|
20
|
+
const lines = rawText.split(/\r\n|\r|\n/);
|
|
21
|
+
const frames = [];
|
|
22
|
+
for (const line of lines) {
|
|
23
|
+
// The header is tried first and produces no frame — it has no
|
|
24
|
+
// location to produce one from. Skipped explicitly rather than
|
|
25
|
+
// falling through, because `TIMESTAMP - Class - message:` can
|
|
26
|
+
// itself contain a colon-and-number substring that would otherwise
|
|
27
|
+
// be worth checking against the frame pattern.
|
|
28
|
+
if (parseSinatraHeader(line) !== null)
|
|
29
|
+
continue;
|
|
30
|
+
const raw = parseSinatraFrame(line);
|
|
31
|
+
if (raw === null)
|
|
32
|
+
continue;
|
|
33
|
+
const location = await resolver.resolve({
|
|
34
|
+
file: raw.file,
|
|
35
|
+
line: raw.line,
|
|
36
|
+
column: null,
|
|
37
|
+
functionName: raw.functionName,
|
|
38
|
+
});
|
|
39
|
+
frames.push({ location, raw: line });
|
|
40
|
+
}
|
|
41
|
+
// Null, never an empty-but-structured StackTrace standing in for
|
|
42
|
+
// "couldn't parse" — this interface's contract, and the reason a
|
|
43
|
+
// header-only block does not become a zero-frame trace.
|
|
44
|
+
if (frames.length === 0)
|
|
45
|
+
return null;
|
|
46
|
+
return { fidelity: "synchronous", frames, primaryFrameIndex: 0 };
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=sinatra-stack-trace-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sinatra-stack-trace-parser.js","sourceRoot":"","sources":["../src/sinatra-stack-trace-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEnF,MAAM,UAAU,6BAA6B,CAAC,QAAgC;IAC5E,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,OAAe;YACzB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAE1C,MAAM,MAAM,GAAiB,EAAE,CAAC;YAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,8DAA8D;gBAC9D,+DAA+D;gBAC/D,8DAA8D;gBAC9D,mEAAmE;gBACnE,+CAA+C;gBAC/C,IAAI,kBAAkB,CAAC,IAAI,CAAC,KAAK,IAAI;oBAAE,SAAS;gBAEhD,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBACpC,IAAI,GAAG,KAAK,IAAI;oBAAE,SAAS;gBAE3B,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;oBACtC,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,MAAM,EAAE,IAAI;oBACZ,YAAY,EAAE,GAAG,CAAC,YAAY;iBAC/B,CAAC,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;YACvC,CAAC;YAED,iEAAiE;YACjE,iEAAiE;YACjE,wDAAwD;YACxD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAErC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC;QACnE,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@descryy/runtime-adapter-ruby",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Ruby runtime adapter: backtrace parsing, self-contained source locations, the concrete RuntimeAdapter for Ruby.",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22.5"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"registry": "https://registry.npmjs.org",
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc -b"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@descryy/runtime-contracts": "*",
|
|
28
|
+
"@descryy/runtime-backend-observation": "*"
|
|
29
|
+
}
|
|
30
|
+
}
|