33// Copyright 2019-Present Datadog, Inc.
44
55import type { Logger } from '@dd/core/types' ;
6- import { randomUUID } from 'crypto' ;
76import * as esbuild from 'esbuild' ;
8- import { mkdir , readdir , readFile , rm , stat } from 'fs/promises' ;
7+ import { mkdir , readdir , readFile , rm , stat , writeFile } from 'fs/promises' ;
98import { tmpdir } from 'os' ;
109import path from 'path' ;
1110
11+ import type { Asset } from './assets' ;
1212import {
1313 ACTION_CATALOG_EXPORT_LINE ,
1414 NODE_EXTERNALS ,
@@ -21,28 +21,7 @@ export interface BackendFunction {
2121 entryPath : string ;
2222}
2323
24- interface BackendFunctionQuery {
25- id : string ;
26- type : string ;
27- name : string ;
28- properties : {
29- spec : {
30- fqn : string ;
31- inputs : {
32- script : string ;
33- } ;
34- } ;
35- } ;
36- }
37-
38- interface AuthConfig {
39- apiKey : string ;
40- appKey : string ;
41- site : string ;
42- }
43-
4424const EXTENSIONS = [ '.ts' , '.js' , '.tsx' , '.jsx' ] ;
45- const JS_FUNCTION_WITH_ACTIONS_FQN = 'com.datadoghq.datatransformation.jsFunctionWithActions' ;
4625
4726/**
4827 * Discover backend functions in the backend directory.
@@ -189,109 +168,37 @@ ${SET_EXECUTE_ACTION_SNIPPET}
189168}
190169
191170/**
192- * Build the ActionQuery objects for each backend function.
193- */
194- function buildQueries ( functions : { name : string ; script : string } [ ] ) : BackendFunctionQuery [ ] {
195- return functions . map ( ( func ) => ( {
196- id : randomUUID ( ) ,
197- type : 'action' ,
198- name : func . name ,
199- properties : {
200- spec : {
201- fqn : JS_FUNCTION_WITH_ACTIONS_FQN ,
202- inputs : {
203- script : func . script ,
204- } ,
205- } ,
206- } ,
207- } ) ) ;
208- }
209-
210- /**
211- * Call the Update App endpoint to set backend function queries on the app definition.
212- * PATCH /api/v2/app-builder/apps/{app_builder_id}
171+ * Discover, bundle, and transform backend functions for inclusion in the upload archive.
172+ * Writes transformed scripts to temp files and returns file references for archiving.
213173 */
214- async function updateApp (
215- appBuilderId : string ,
216- queries : BackendFunctionQuery [ ] ,
217- auth : AuthConfig ,
218- log : Logger ,
219- ) : Promise < void > {
220- const endpoint = `https://api.${ auth . site } /api/v2/app-builder/apps/${ appBuilderId } ` ;
221-
222- const body = {
223- data : {
224- type : 'appDefinitions' ,
225- attributes : {
226- queries,
227- } ,
228- } ,
229- } ;
230-
231- log . debug ( `Updating app ${ appBuilderId } with ${ queries . length } backend function query(ies)` ) ;
232-
233- const response = await fetch ( endpoint , {
234- method : 'PATCH' ,
235- headers : {
236- 'Content-Type' : 'application/json' ,
237- 'DD-API-KEY' : auth . apiKey ,
238- 'DD-APPLICATION-KEY' : auth . appKey ,
239- } ,
240- body : JSON . stringify ( body ) ,
241- } ) ;
242-
243- if ( ! response . ok ) {
244- const errorText = await response . text ( ) ;
245- throw new Error (
246- `Failed to update app with backend functions (${ response . status } ): ${ errorText } ` ,
247- ) ;
248- }
249-
250- log . debug ( `Successfully updated app ${ appBuilderId } with backend function queries` ) ;
251- }
252-
253- /**
254- * Discover, bundle, transform, and publish backend functions to the app definition.
255- * Called after a successful app upload to emulate backend function support.
256- */
257- export async function publishBackendFunctions (
174+ export async function bundleBackendFunctions (
258175 projectRoot : string ,
259176 backendDir : string ,
260- appBuilderId : string ,
261- auth : AuthConfig ,
262177 log : Logger ,
263- ) : Promise < { errors : Error [ ] ; warnings : string [ ] } > {
264- const errors : Error [ ] = [ ] ;
265- const warnings : string [ ] = [ ] ;
266-
267- try {
268- const absoluteBackendDir = path . resolve ( projectRoot , backendDir ) ;
269- const functions = await discoverBackendFunctions ( absoluteBackendDir , log ) ;
178+ ) : Promise < { files : Asset [ ] ; tempDir : string } > {
179+ const absoluteBackendDir = path . resolve ( projectRoot , backendDir ) ;
180+ const functions = await discoverBackendFunctions ( absoluteBackendDir , log ) ;
270181
271- if ( functions . length === 0 ) {
272- log . debug ( 'No backend functions found, skipping update.' ) ;
273- return { errors, warnings } ;
274- }
275-
276- // Bundle and transform each function
277- const transformedFunctions : { name : string ; script : string } [ ] = [ ] ;
278- for ( const func of functions ) {
279- const bundledCode = await bundleFunction ( func , projectRoot , log ) ;
280- const script = transformToProductionScript ( bundledCode , func . name ) ;
281- transformedFunctions . push ( { name : func . name , script } ) ;
282- }
182+ if ( functions . length === 0 ) {
183+ log . debug ( 'No backend functions found.' ) ;
184+ return { files : [ ] , tempDir : '' } ;
185+ }
283186
284- // Build queries and update the app
285- const queries = buildQueries ( transformedFunctions ) ;
286- await updateApp ( appBuilderId , queries , auth , log ) ;
187+ const tempDir = path . join ( tmpdir ( ) , `dd-apps-backend-${ Date . now ( ) } ` ) ;
188+ await mkdir ( tempDir , { recursive : true } ) ;
287189
288- log . info (
289- `Published ${ transformedFunctions . length } backend function(s): ${ transformedFunctions . map ( ( f ) => f . name ) . join ( ', ' ) } ` ,
290- ) ;
291- } catch ( error : unknown ) {
292- const err = error instanceof Error ? error : new Error ( String ( error ) ) ;
293- errors . push ( err ) ;
190+ const files : Asset [ ] = [ ] ;
191+ for ( const func of functions ) {
192+ const bundledCode = await bundleFunction ( func , projectRoot , log ) ;
193+ const script = transformToProductionScript ( bundledCode , func . name ) ;
194+ const absolutePath = path . join ( tempDir , `${ func . name } .js` ) ;
195+ await writeFile ( absolutePath , script , 'utf-8' ) ;
196+ files . push ( { absolutePath, relativePath : `backend/${ func . name } .js` } ) ;
294197 }
295198
296- return { errors, warnings } ;
199+ log . info (
200+ `Bundled ${ files . length } backend function(s): ${ functions . map ( ( f ) => f . name ) . join ( ', ' ) } ` ,
201+ ) ;
202+
203+ return { files, tempDir } ;
297204}
0 commit comments