@@ -16,46 +16,33 @@ import type {
1616import { getModelsAsDataLanguage } from "./languages" ;
1717import { Mode } from "./shared/mode" ;
1818import { assertNever } from "../common/helpers-pure" ;
19- import type { ModelExtensionFile } from "./model-extension-file" ;
19+ import type {
20+ ModelExtension ,
21+ ModelExtensionFile ,
22+ } from "./model-extension-file" ;
2023import type { QueryLanguage } from "../common/query-language" ;
2124
2225import modelExtensionFileSchema from "./model-extension-file.schema.json" ;
2326
2427const ajv = new Ajv ( { allErrors : true , allowUnionTypes : true } ) ;
2528const modelExtensionFileSchemaValidate = ajv . compile ( modelExtensionFileSchema ) ;
2629
27- function createDataProperty < T > (
28- methods : readonly T [ ] ,
29- definition : ModelsAsDataLanguagePredicate < T > ,
30- ) {
31- if ( methods . length === 0 ) {
32- return " []" ;
33- }
34-
35- return `\n${ methods
36- . map (
37- ( method ) =>
38- ` - ${ JSON . stringify (
39- definition . generateMethodDefinition ( method ) ,
40- ) } `,
41- )
42- . join ( "\n" ) } `;
43- }
44-
4530function createExtensions < T > (
4631 language : QueryLanguage ,
4732 methods : readonly T [ ] ,
4833 definition : ModelsAsDataLanguagePredicate < T > | undefined ,
49- ) {
34+ ) : ModelExtension | undefined {
5035 if ( ! definition ) {
51- return "" ;
36+ return undefined ;
5237 }
5338
54- return ` - addsTo:
55- pack: codeql/${ language } -all
56- extensible: ${ definition . extensiblePredicate }
57- data:${ createDataProperty ( methods , definition ) }
58- ` ;
39+ return {
40+ addsTo : {
41+ pack : `codeql/${ language } -all` ,
42+ extensible : definition . extensiblePredicate ,
43+ } ,
44+ data : methods . map ( ( method ) => definition . generateMethodDefinition ( method ) ) ,
45+ } ;
5946}
6047
6148export function createDataExtensionYaml (
@@ -99,7 +86,7 @@ export function createDataExtensionYaml(
9986 }
10087
10188 const extensions = Object . keys ( methodsByType )
102- . map ( ( typeKey ) => {
89+ . map ( ( typeKey ) : ModelExtension | undefined => {
10390 const type = typeKey as keyof ModelsAsDataLanguagePredicates ;
10491
10592 switch ( type ) {
@@ -137,10 +124,11 @@ export function createDataExtensionYaml(
137124 assertNever ( type ) ;
138125 }
139126 } )
140- . filter ( ( extensions ) => extensions !== "" ) ;
127+ . filter (
128+ ( extension ) : extension is ModelExtension => extension !== undefined ,
129+ ) ;
141130
142- return `extensions:
143- ${ extensions . join ( "\n" ) } `;
131+ return modelExtensionFileToYaml ( { extensions } ) ;
144132}
145133
146134export function createDataExtensionYamls (
@@ -341,6 +329,36 @@ function validateModelExtensionFile(data: unknown): data is ModelExtensionFile {
341329 return true ;
342330}
343331
332+ /**
333+ * Creates a string for the data extension YAML file from the
334+ * structure of the data extension file. This should be used
335+ * instead of creating a JSON string directly or dumping the
336+ * YAML directly to ensure that the file is formatted correctly.
337+ *
338+ * @param data The data extension file
339+ */
340+ function modelExtensionFileToYaml ( data : ModelExtensionFile ) {
341+ const extensions = data . extensions
342+ . map ( ( extension ) => {
343+ const data =
344+ extension . data . length === 0
345+ ? " []"
346+ : `\n${ extension . data
347+ . map ( ( row ) => ` - ${ JSON . stringify ( row ) } ` )
348+ . join ( "\n" ) } `;
349+
350+ return ` - addsTo:
351+ pack: ${ extension . addsTo . pack }
352+ extensible: ${ extension . addsTo . extensible }
353+ data:${ data }
354+ ` ;
355+ } )
356+ . filter ( ( extensions ) => extensions !== "" ) ;
357+
358+ return `extensions:
359+ ${ extensions . join ( "\n" ) } `;
360+ }
361+
344362export function loadDataExtensionYaml (
345363 data : unknown ,
346364 language : QueryLanguage ,
0 commit comments