1
1
import { fileURLToPath } from 'url'
2
2
import path from 'path'
3
- import fs from 'fs'
4
3
import { readCompressedJsonFileFallback } from '../read-json-file.js'
5
4
import renderContent from '../render-content/index.js'
6
5
import getMiniTocItems from '../get-mini-toc-items.js'
7
6
import { allVersions } from '../all-versions.js'
8
- import { get } from 'lodash-es '
7
+ import languages from '../languages.js '
9
8
10
9
const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) )
11
10
const schemasPath = path . join ( __dirname , 'static/decorated' )
12
11
const ENABLED_APPS_FILENAME = path . join ( __dirname , 'static/apps/enabled-for-apps.json' )
13
- /*
12
+ /*
14
13
Loads the schemas from the static/decorated folder into a single
15
14
object organized by version.
16
15
@@ -23,23 +22,33 @@ const ENABLED_APPS_FILENAME = path.join(__dirname, 'static/apps/enabled-for-apps
23
22
}
24
23
}
25
24
*/
26
- export default async function getRest ( ) {
27
- const operations = { }
28
- fs . readdirSync ( schemasPath ) . forEach ( ( filename ) => {
29
- // In staging deploys, the `.json` files might have been converted to
30
- // to `.json.br`. In that case, we need to also remove the `.json`
31
- // extension from the key
32
- const key = path . parse ( filename ) . name . replace ( '.json' , '' )
25
+ const restOperationData = new Map ( )
26
+ Object . keys ( languages ) . forEach ( ( language ) => {
27
+ restOperationData . set ( language , new Map ( ) )
28
+ Object . keys ( allVersions ) . forEach ( ( version ) => {
29
+ // setting to undefined will allow us to perform checks
30
+ // more easily later on
31
+ restOperationData . get ( language ) . set ( version , new Map ( ) )
32
+ } )
33
+ } )
34
+
35
+ const restOperations = new Map ( )
36
+ export default async function getRest ( version , category ) {
37
+ const openApiVersion = getOpenApiVersion ( version )
38
+ if ( ! restOperations . has ( openApiVersion ) ) {
39
+ const filename = `${ openApiVersion } .json`
40
+
33
41
// The `readCompressedJsonFileFallback()` function
34
42
// will check for both a .br and .json extension.
35
- const value = readCompressedJsonFileFallback ( path . join ( schemasPath , filename ) )
36
- const docsVersions = getDocsVersions ( key )
37
- docsVersions . forEach ( ( docsVersion ) => {
38
- operations [ docsVersion ] = value
39
- } )
40
- } )
43
+ restOperations . set (
44
+ openApiVersion ,
45
+ readCompressedJsonFileFallback ( path . join ( schemasPath , filename ) )
46
+ )
47
+ }
41
48
42
- return operations
49
+ return category
50
+ ? restOperations . get ( openApiVersion ) [ category ]
51
+ : restOperations . get ( openApiVersion )
43
52
}
44
53
45
54
// Right now there is not a 1:1 mapping of openapi to docs versions,
@@ -52,48 +61,57 @@ function getDocsVersions(openApiVersion) {
52
61
return versions
53
62
}
54
63
55
- // Used for units tests
56
- export function getFlatListOfOperations ( operations ) {
57
- const flatList = [ ]
58
- Object . keys ( operations ) . forEach ( ( version ) => {
59
- Object . keys ( operations [ version ] ) . forEach ( ( category ) => {
60
- Object . keys ( operations [ version ] [ category ] ) . forEach ( ( subcategory ) => {
61
- flatList . push ( ...operations [ version ] [ category ] [ subcategory ] )
62
- } )
63
- } )
64
- } )
65
- return flatList
64
+ function getOpenApiVersion ( version ) {
65
+ if ( ! ( version in allVersions ) ) {
66
+ throw new Error ( `Unrecognized version '${ version } '. Not found in ${ Object . keys ( allVersions ) } ` )
67
+ }
68
+ return allVersions [ version ] . openApiVersionName
66
69
}
67
70
68
71
// Generates the rendered Markdown from the data files in the
69
72
// data/reusables/rest-reference directory for a given category
70
73
// and generates the miniToc for a rest reference page.
71
- export async function getRestOperationData ( category , categoryOperations , context ) {
72
- const descriptions = { }
73
- let toc = ''
74
- const reusablePath = context . site . data . reusables
75
- const subcategories = Object . keys ( categoryOperations )
76
- let introContent = null
77
- for ( const subcategory of subcategories ) {
78
- const markdown = get ( reusablePath [ 'rest-reference' ] [ category ] , subcategory )
79
- const renderedMarkdown = await renderContent ( markdown , context )
80
- descriptions [ subcategory ] = renderedMarkdown
81
- // only a string with the raw HTML of each heading level 2 and 3
82
- // is needed to generate the toc
83
- const titles = categoryOperations [ subcategory ]
84
- . map ( ( operation ) => `### ${ operation . summary } \n` )
85
- . join ( '' )
86
- toc += renderedMarkdown + ( await renderContent ( titles , context ) )
87
- }
88
- // This is Markdown content at the path
89
- // data/reusables/rest-reference/<category>/<subcategory>
90
- // that doesn't map directory to a group of operations.
91
- if ( get ( reusablePath [ 'rest-reference' ] [ category ] , category ) && ! categoryOperations [ category ] ) {
92
- const markdown = get ( reusablePath [ 'rest-reference' ] [ category ] , category )
93
- introContent = await renderContent ( markdown , context )
74
+ export async function getRestOperationData ( category , language , version , context ) {
75
+ if ( ! restOperationData . get ( language ) . get ( version ) . has ( category ) ) {
76
+ const languageTree = restOperationData . get ( language )
77
+ const descriptions = { }
78
+ let toc = ''
79
+ const reusablePath = context . site . data . reusables
80
+ const categoryOperations = await getRest ( version , category )
81
+ const subcategories = Object . keys ( categoryOperations )
82
+ let introContent = null
83
+ for ( const subcategory of subcategories ) {
84
+ const markdown = reusablePath [ 'rest-reference' ] ?. [ category ] ?. [ subcategory ]
85
+ const renderedMarkdown = await renderContent ( markdown , context )
86
+ descriptions [ subcategory ] = renderedMarkdown
87
+ // only a string with the raw HTML of each heading level 2 and 3
88
+ // is needed to generate the toc
89
+ const titles = categoryOperations [ subcategory ]
90
+ . map ( ( operation ) => `### ${ operation . summary } \n` )
91
+ . join ( '' )
92
+ toc += renderedMarkdown + ( await renderContent ( titles , context ) )
93
+ }
94
+ // Usually a Markdown file in
95
+ // data/resuables/rest-reference/<category>/<subcategory>
96
+ // will always map to a set of operations. But sometimes we have
97
+ // introductory text that doesn't map to any operations.
98
+ // When that is the case, the category and subcategory are the same.
99
+ // Example data/resuables/rest-reference/actions/actions
100
+ // The content in this file is called introContent and is displayed
101
+ // at the top of the rest reference page.
102
+ if ( reusablePath [ 'rest-reference' ] ?. [ category ] ?. [ category ] && ! categoryOperations [ category ] ) {
103
+ const markdown = reusablePath [ 'rest-reference' ] ?. [ category ] ?. [ category ]
104
+ introContent = await renderContent ( markdown , context )
105
+ }
106
+ const miniTocItems = getMiniTocItems ( toc , 3 )
107
+ languageTree . get ( version ) . set ( category , {
108
+ descriptions,
109
+ miniTocItems,
110
+ introContent,
111
+ } )
112
+ restOperationData . set ( restOperationData , languageTree )
94
113
}
95
- const miniTocItems = getMiniTocItems ( toc , 3 )
96
- return { descriptions, miniTocItems, introContent }
114
+ return restOperationData . get ( language ) . get ( version ) . get ( category )
97
115
}
98
116
99
117
export async function getEnabledForApps ( ) {
0 commit comments