Skip to content

Commit f879136

Browse files
committed
fix(bundle): derive SentrySDK type declarations from sdk.generated.ts
Replace hand-written SentrySDK type in bundle.ts TYPE_DECLARATIONS with types extracted from src/sdk.generated.ts at bundle time. This ensures the .d.cts file stays in sync with the generated SDK automatically. The previous hand-written type was missing many parameters (platform, cursor, sort, period, query, spans) and used Promise<unknown> instead of the actual return types from the generated methods. The extraction: 1. Collects all exported param type blocks (XxxParams) verbatim 2. Parses createSDKMethods return shape into SentrySDK type 3. Transforms method implementations into type signatures 4. Strips invoke call bodies, preserves JSDoc comments
1 parent 3c07a81 commit f879136

1 file changed

Lines changed: 125 additions & 33 deletions

File tree

script/bundle.ts

Lines changed: 125 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@ if (!SENTRY_CLIENT_ID) {
2222
const BUN_SQLITE_FILTER = /^bun:sqlite$/;
2323
const ANY_FILTER = /.*/;
2424

25+
// Regex patterns for SDK type extraction
26+
/** Matches `export type FooParams = { ... };` blocks (multiline via dotAll) */
27+
const EXPORTED_TYPE_BLOCK_RE = /^export type \w+Params = \{[^}]*\};/gms;
28+
29+
/** Matches method lines: `name: (params): Promise<T> =>` */
30+
const SDK_METHOD_RE = /^(\s+)(\w+): \(([^)]*)\): (Promise<.+>)\s*=>$/;
31+
32+
/** Matches namespace opening: ` name: {` */
33+
const SDK_NAMESPACE_RE = /^\s+\w+: \{$/;
34+
35+
/** Matches invoke call bodies to strip from output */
36+
const SDK_INVOKE_RE = /^\s+invoke/;
37+
38+
/** Matches trailing comma before closing brace in method tree */
39+
const TRAILING_COMMA_BRACE_RE = /},?$/;
40+
2541
/** Plugin to replace bun:sqlite with our node:sqlite polyfill. */
2642
const bunSqlitePlugin: Plugin = {
2743
name: "bun-sqlite-polyfill",
@@ -48,6 +64,102 @@ const bunSqlitePlugin: Plugin = {
4864

4965
type InjectedFile = { jsPath: string; mapPath: string; debugId: string };
5066

67+
/** Count net brace depth change in a line (`{` = +1, `}` = -1). */
68+
function countBraces(line: string): number {
69+
let delta = 0;
70+
for (const ch of line) {
71+
if (ch === "{") {
72+
delta += 1;
73+
}
74+
if (ch === "}") {
75+
delta -= 1;
76+
}
77+
}
78+
return delta;
79+
}
80+
81+
/**
82+
* Extract the method tree lines from `createSDKMethods` function body.
83+
* Returns lines between `return {` and the closing `}` of the function,
84+
* excluding the `return {` line itself.
85+
*/
86+
function extractMethodTreeLines(lines: string[]): string[] {
87+
const methodLines: string[] = [];
88+
let inMethodTree = false;
89+
let depth = 0;
90+
91+
for (const line of lines) {
92+
if (line.includes("export function createSDKMethods")) {
93+
inMethodTree = true;
94+
depth = 0;
95+
continue;
96+
}
97+
if (!inMethodTree) {
98+
continue;
99+
}
100+
101+
depth += countBraces(line);
102+
103+
if (depth <= 0) {
104+
break;
105+
}
106+
if (line.trim() === "return {") {
107+
continue;
108+
}
109+
110+
methodLines.push(line);
111+
}
112+
113+
return methodLines;
114+
}
115+
116+
/** Transform a method implementation line into a type declaration line. */
117+
function transformMethodLine(line: string): string | null {
118+
const methodMatch = SDK_METHOD_RE.exec(line);
119+
if (methodMatch) {
120+
const [, indent, name, params, returnType] = methodMatch;
121+
return `${indent}${name}(${params}): ${returnType};`;
122+
}
123+
if (SDK_NAMESPACE_RE.test(line)) {
124+
return line;
125+
}
126+
if (line.trim().startsWith("}")) {
127+
return line.replace(TRAILING_COMMA_BRACE_RE, "};");
128+
}
129+
// JSDoc comments
130+
if (line.trim().startsWith("/**") || line.trim().startsWith("*")) {
131+
return line;
132+
}
133+
// Invoke call bodies — skip
134+
if (SDK_INVOKE_RE.test(line)) {
135+
return null;
136+
}
137+
return line;
138+
}
139+
140+
/**
141+
* Extract parameter types and SentrySDK type from the generated SDK source.
142+
*
143+
* Parses `sdk.generated.ts` to produce standalone `.d.cts`-safe type declarations:
144+
* 1. All `export type XxxParams = { ... };` blocks (extracted verbatim)
145+
* 2. The `SentrySDK` type built from `createSDKMethods` return shape
146+
* (method implementations → type signatures, invoke bodies stripped)
147+
*/
148+
function extractSdkTypes(source: string): string {
149+
const paramTypes = [...source.matchAll(EXPORTED_TYPE_BLOCK_RE)].map(
150+
(m) => m[0]
151+
);
152+
153+
const methodLines = extractMethodTreeLines(source.split("\n"));
154+
const sdkBody = methodLines
155+
.map(transformMethodLine)
156+
.filter((l): l is string => l !== null)
157+
.join("\n");
158+
159+
const sdkType = `export type SentrySDK = {\n${sdkBody}\n};`;
160+
return `${paramTypes.join("\n\n")}\n\n${sdkType}`;
161+
}
162+
51163
/** Delete .map files after a successful upload — they shouldn't ship to users. */
52164
async function deleteMapFiles(injected: InjectedFile[]): Promise<void> {
53165
for (const { mapPath } of injected) {
@@ -181,9 +293,8 @@ const result = await build({
181293
entryPoints: ["./src/index.ts"],
182294
bundle: true,
183295
minify: true,
184-
banner: {
185-
js: `{let e=process.emit;process.emit=function(n,...a){return n==="warning"?!1:e.apply(this,[n,...a])}}`,
186-
},
296+
// No banner — warning suppression moved to dist/bin.cjs (CLI-only).
297+
// The library bundle must not suppress the host application's warnings.
187298
sourcemap: true,
188299
platform: "node",
189300
target: "node22",
@@ -207,12 +318,14 @@ const result = await build({
207318
// Write the CLI bin wrapper (tiny — shebang + version check + dispatch)
208319
const BIN_WRAPPER = `#!/usr/bin/env node
209320
if(parseInt(process.versions.node)<22){console.error("Error: sentry requires Node.js 22 or later (found "+process.version+").\\n\\nEither upgrade Node.js, or install the standalone binary instead:\\n curl -fsSL https://cli.sentry.dev/install | bash\\n");process.exit(1)}
321+
{let e=process.emit;process.emit=function(n,...a){return n==="warning"?!1:e.apply(this,[n,...a])}}
210322
require('./index.cjs')._cli().catch(()=>{process.exitCode=1});
211323
`;
212324
await Bun.write("./dist/bin.cjs", BIN_WRAPPER);
213325

214-
// Write TypeScript declarations for the library API
215-
const TYPE_DECLARATIONS = `export type SentryOptions = {
326+
// Write TypeScript declarations for the library API.
327+
// The SentrySDK type is derived from sdk.generated.ts to stay in sync.
328+
const CORE_DECLARATIONS = `export type SentryOptions = {
216329
/** Auth token. Auto-filled from SENTRY_AUTH_TOKEN / SENTRY_TOKEN env vars. */
217330
token?: string;
218331
/** Return human-readable text instead of parsed JSON. */
@@ -234,35 +347,14 @@ export { sentry };
234347
export default sentry;
235348
236349
export declare function createSentrySDK(options?: SentryOptions): SentrySDK;
237-
238-
export type SentrySDK = {
239-
organizations: {
240-
list(params?: { limit?: number }): Promise<unknown>;
241-
get(params?: { org?: string }): Promise<unknown>;
242-
};
243-
projects: {
244-
list(params?: { target?: string; limit?: number }): Promise<unknown>;
245-
get(params?: { target?: string }): Promise<unknown>;
246-
};
247-
issues: {
248-
list(params: { org: string; project: string; limit?: number; query?: string }): Promise<unknown>;
249-
get(params: { issueId: string }): Promise<unknown>;
250-
};
251-
events: {
252-
get(params: { eventId: string }): Promise<unknown>;
253-
};
254-
traces: {
255-
list(params?: { target?: string; limit?: number }): Promise<unknown>;
256-
get(params: { traceId: string }): Promise<unknown>;
257-
};
258-
spans: {
259-
list(params?: { target?: string; limit?: number }): Promise<unknown>;
260-
};
261-
teams: {
262-
list(params?: { target?: string; limit?: number }): Promise<unknown>;
263-
};
264-
};
265350
`;
351+
352+
// Extract parameter types and SentrySDK type from sdk.generated.ts.
353+
// This keeps the bundled .d.cts in sync with the generated SDK automatically.
354+
const sdkSource = await Bun.file("./src/sdk.generated.ts").text();
355+
const sdkTypes = extractSdkTypes(sdkSource);
356+
357+
const TYPE_DECLARATIONS = `${CORE_DECLARATIONS}\n${sdkTypes}\n`;
266358
await Bun.write("./dist/index.d.cts", TYPE_DECLARATIONS);
267359

268360
console.log(" -> dist/bin.cjs (CLI wrapper)");

0 commit comments

Comments
 (0)