Skip to content

Commit e537341

Browse files
committed
fix(sdk): preserve hosted client generator overrides
1 parent fc615f2 commit e537341

2 files changed

Lines changed: 133 additions & 2 deletions

File tree

‎sdks/python/scripts/generate-client-methods.js‎

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,22 @@ const SKIP_GENERATE = new Set([
4545
'filterEvents', // pure local computation, no sidecar
4646
]);
4747

48+
// Hosted-mode trading/read methods carry hand-maintained dispatch in client.py.
49+
// Keep these sections inside the generated region stable when regenerating the
50+
// sidecar pass-through surface from BaseExchange.ts. Without this preservation,
51+
// a focused SDK/doc PR that runs this generator drops hosted-mode guards/helpers
52+
// unrelated to the PR and fails generated-sync checks with broad drift.
53+
const PRESERVE_GENERATED_METHODS = [
54+
'cancel_order',
55+
'fetch_order',
56+
'fetch_open_orders',
57+
'fetch_my_trades',
58+
'fetch_closed_orders',
59+
'fetch_all_orders',
60+
'fetch_positions',
61+
'fetch_balance',
62+
];
63+
4864
// ---------------------------------------------------------------------------
4965
// TypeScript type name -> Python type info
5066
//
@@ -475,6 +491,54 @@ function generatePyMethod(name, params, config, sf) {
475491
].join('\n');
476492
}
477493

494+
function extractGeneratedRegion(client) {
495+
const beginIdx = client.indexOf(MARKER_BEGIN);
496+
const endIdx = client.indexOf(MARKER_END);
497+
if (beginIdx === -1 || endIdx === -1 || endIdx <= beginIdx) return '';
498+
return client.slice(beginIdx + MARKER_BEGIN.length, endIdx);
499+
}
500+
501+
function methodPrefix(methodName) {
502+
return ` def ${methodName}(`;
503+
}
504+
505+
function findMethodSegment(region, methodName) {
506+
const start = region.indexOf(methodPrefix(methodName));
507+
if (start === -1) return null;
508+
509+
const nextDef = region.indexOf('\n def ', start + methodPrefix(methodName).length);
510+
const end = nextDef === -1 ? region.length : nextDef + 1;
511+
return region.slice(start, end).replace(/\n+$/u, '');
512+
}
513+
514+
function replaceMethodSegment(region, methodName, replacement) {
515+
const start = region.indexOf(methodPrefix(methodName));
516+
if (start === -1) {
517+
throw new Error(`Generated ${methodName} not found while preserving hosted overrides`);
518+
}
519+
520+
const nextDef = region.indexOf('\n def ', start + methodPrefix(methodName).length);
521+
const end = nextDef === -1 ? region.length : nextDef + 1;
522+
return `${region.slice(0, start)}${replacement}\n\n${region.slice(end).replace(/^\n+/u, '')}`;
523+
}
524+
525+
function preserveHostedMethodOverrides(existingClient, generated) {
526+
const existingRegion = extractGeneratedRegion(existingClient);
527+
let nextGenerated = generated;
528+
529+
for (const methodName of PRESERVE_GENERATED_METHODS) {
530+
const existingSegment = findMethodSegment(existingRegion, methodName);
531+
if (!existingSegment) continue;
532+
533+
// Only preserve methods that actually contain hosted-mode dispatch. This
534+
// avoids freezing unrelated generated methods if the source file changes.
535+
if (!existingSegment.includes('self.is_hosted')) continue;
536+
nextGenerated = replaceMethodSegment(nextGenerated, methodName, existingSegment);
537+
}
538+
539+
return nextGenerated;
540+
}
541+
478542
// ---------------------------------------------------------------------------
479543
// Main
480544
// ---------------------------------------------------------------------------
@@ -485,13 +549,14 @@ function main() {
485549

486550
const methods = extractMethods(sf);
487551

488-
const generated = methods.map(m => {
552+
let generated = methods.map(m => {
489553
const name = m.name.text;
490554
const config = inferReturnConfig(m.type, name, sf);
491555
return generatePyMethod(name, m.parameters, config, sf);
492556
}).join('\n\n');
493557

494558
let client = fs.readFileSync(CLIENT_PATH, 'utf-8');
559+
generated = preserveHostedMethodOverrides(client, generated);
495560

496561
const beginIdx = client.indexOf(MARKER_BEGIN);
497562
const endIdx = client.indexOf(MARKER_END);

‎sdks/typescript/scripts/generate-client-methods.js‎

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,23 @@ const SKIP_GENERATE = new Set([
4343
'filterEvents', // pure local computation, no sidecar
4444
]);
4545

46+
// Hosted-mode trading/read methods carry hand-maintained dispatch in client.ts.
47+
// Keep these sections inside the generated region stable when regenerating the
48+
// sidecar pass-through surface from BaseExchange.ts. Without this preservation,
49+
// a focused SDK/doc PR that runs this generator drops hosted-mode guards/helpers
50+
// unrelated to the PR and fails generated-sync checks with broad drift.
51+
const PRESERVE_GENERATED_METHODS = [
52+
'submitOrder',
53+
'cancelOrder',
54+
'fetchOrder',
55+
'fetchOpenOrders',
56+
'fetchMyTrades',
57+
'fetchClosedOrders',
58+
'fetchAllOrders',
59+
'fetchPositions',
60+
'fetchBalance',
61+
];
62+
4663
// ---------------------------------------------------------------------------
4764
// TypeScript type name -> SDK type info
4865
//
@@ -460,6 +477,54 @@ function generateMethod(name, params, config, sf) {
460477
].join('\n');
461478
}
462479

480+
function extractGeneratedRegion(client) {
481+
const beginIdx = client.indexOf(MARKER_BEGIN);
482+
const endIdx = client.indexOf(MARKER_END);
483+
if (beginIdx === -1 || endIdx === -1 || endIdx <= beginIdx) return '';
484+
return client.slice(beginIdx + MARKER_BEGIN.length, endIdx);
485+
}
486+
487+
function methodPrefix(methodName) {
488+
return ` async ${methodName}(`;
489+
}
490+
491+
function findMethodSegment(region, methodName) {
492+
const start = region.indexOf(methodPrefix(methodName));
493+
if (start === -1) return null;
494+
495+
const nextMethod = region.indexOf('\n async ', start + methodPrefix(methodName).length);
496+
const end = nextMethod === -1 ? region.length : nextMethod + 1;
497+
return region.slice(start, end).replace(/\n+$/u, '');
498+
}
499+
500+
function replaceMethodSegment(region, methodName, replacement) {
501+
const start = region.indexOf(methodPrefix(methodName));
502+
if (start === -1) {
503+
throw new Error(`Generated ${methodName} not found while preserving hosted overrides`);
504+
}
505+
506+
const nextMethod = region.indexOf('\n async ', start + methodPrefix(methodName).length);
507+
const end = nextMethod === -1 ? region.length : nextMethod + 1;
508+
return `${region.slice(0, start)}${replacement}\n\n${region.slice(end).replace(/^\n+/u, '')}`;
509+
}
510+
511+
function preserveHostedMethodOverrides(existingClient, generated) {
512+
const existingRegion = extractGeneratedRegion(existingClient);
513+
let nextGenerated = generated;
514+
515+
for (const methodName of PRESERVE_GENERATED_METHODS) {
516+
const existingSegment = findMethodSegment(existingRegion, methodName);
517+
if (!existingSegment) continue;
518+
519+
// Only preserve methods that actually contain hosted-mode dispatch. This
520+
// avoids freezing unrelated generated methods if the source file changes.
521+
if (!existingSegment.includes('isHostedTradingMode()')) continue;
522+
nextGenerated = replaceMethodSegment(nextGenerated, methodName, existingSegment);
523+
}
524+
525+
return nextGenerated;
526+
}
527+
463528
// ---------------------------------------------------------------------------
464529
// Main
465530
// ---------------------------------------------------------------------------
@@ -470,13 +535,14 @@ function main() {
470535

471536
const methods = extractMethods(sf);
472537

473-
const generated = methods.map(m => {
538+
let generated = methods.map(m => {
474539
const name = m.name.text;
475540
const config = inferReturnConfig(m.type, name, sf);
476541
return generateMethod(name, m.parameters, config, sf);
477542
}).join('\n\n');
478543

479544
let client = fs.readFileSync(CLIENT_PATH, 'utf-8');
545+
generated = preserveHostedMethodOverrides(client, generated);
480546

481547
const beginIdx = client.indexOf(MARKER_BEGIN);
482548
const endIdx = client.indexOf(MARKER_END);

0 commit comments

Comments
 (0)