Skip to content

Commit 145ec69

Browse files
committed
chore(apps): deprecate legacy backend runtime global
1 parent 30ef62c commit 145ec69

2 files changed

Lines changed: 23 additions & 11 deletions

File tree

packages/plugins/apps/src/backend/virtual-entry.test.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,6 @@ describe('Backend Functions - generateVirtualEntryContent', () => {
3838
expect(result).toContain('export async function main($)');
3939
});
4040

41-
test('Should set globalThis.$ = $', () => {
42-
const result = generateVirtualEntryContent(
43-
'myHandler',
44-
'/src/handler.ts',
45-
PROJECT_ROOT,
46-
);
47-
expect(result).toContain('globalThis.$ = $');
48-
});
49-
5041
test('Should read args from $.backendFunctionArgs (no source-text substitution)', () => {
5142
const result = generateVirtualEntryContent(
5243
'myHandler',
@@ -70,6 +61,7 @@ describe('Backend Functions - generateVirtualEntryContent', () => {
7061
PROJECT_ROOT,
7162
);
7263
expect(result).toContain('await myHandler(...args)');
64+
expect(result).not.toContain('await myHandler(...args, $)');
7365
});
7466

7567
test('Should include the setExecuteActionImplementation bridge snippet', () => {
@@ -164,6 +156,10 @@ describe('Backend Functions - args round-trip via $.backendFunctionArgs', () =>
164156
jest.spyOn(shared, 'isActionCatalogInstalled').mockReturnValue(false);
165157
});
166158

159+
afterEach(() => {
160+
Reflect.deleteProperty(global, '$');
161+
});
162+
167163
// Extract the body of the generated `main($)` function so we can eval it
168164
// directly with a custom $ that includes a mocked handler import.
169165
function buildMainFromSource(source: string, handler: (...args: unknown[]) => unknown) {
@@ -176,8 +172,7 @@ describe('Backend Functions - args round-trip via $.backendFunctionArgs', () =>
176172
.join('\n')
177173
// Replace the call site with a $-bound handler we control.
178174
.replace(/await myHandler\(\.\.\.args\)/, 'await $.__handler(...args)');
179-
// The generated code declares globalThis.$, which has no effect in this
180-
// sandbox but is harmless. Wrap the body so we can return main().
175+
// Wrap the executable body so we can return main().
181176
const wrapper = `${body}\nreturn main($);`;
182177
// eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func
183178
const fn = new Function(
@@ -229,4 +224,18 @@ describe('Backend Functions - args round-trip via $.backendFunctionArgs', () =>
229224
await main({});
230225
expect(received).toEqual([]);
231226
});
227+
228+
test('Should expose the runtime context globally for legacy handlers', async () => {
229+
const source = generateVirtualEntryContent('myHandler', '/src/handler.ts', PROJECT_ROOT);
230+
let exposedContext: unknown;
231+
const handler = () => {
232+
exposedContext = Reflect.get(global, '$');
233+
return 'ok';
234+
};
235+
const main = buildMainFromSource(source, handler);
236+
237+
await main({ backendFunctionArgs: [], privateRuntimeValue: 'secret' });
238+
239+
expect(exposedContext).toMatchObject({ privateRuntimeValue: 'secret' });
240+
});
232241
});

packages/plugins/apps/src/backend/virtual-entry.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ export function generateVirtualEntryContent(
2828
lines.push('');
2929
lines.push('/** @param {import("./context.types").Context} $ */');
3030
lines.push('export async function main($) {');
31+
lines.push(' // Deprecated compatibility shim: existing customer functions may read');
32+
lines.push(' // the runtime context through globalThis.$. Remove only in a breaking');
33+
lines.push(' // release after customers migrate to @datadog/apps backend APIs.');
3134
lines.push(' globalThis.$ = $;');
3235
lines.push('');
3336
lines.push(` // Register the $.Actions-based implementation for executeAction`);

0 commit comments

Comments
 (0)