3
3
* SPDX-License-Identifier: Apache-2.0
4
4
*/
5
5
6
- import { mkdirSync , writeFileSync } from 'fs'
7
- import * as path from 'path'
8
6
import * as vscode from 'vscode'
9
7
import globals from './extensionGlobals'
10
8
import { activateYamlExtension , YamlExtension } from './extensions/yaml'
11
- import * as filesystemUtilities from './filesystemUtilities'
12
9
import * as pathutil from '../shared/utilities/pathUtils'
13
10
import { getLogger } from './logger'
14
11
import { FileResourceFetcher } from './resourcefetcher/fileResourceFetcher'
@@ -17,8 +14,12 @@ import { Settings } from './settings'
17
14
import { once } from './utilities/functionUtils'
18
15
import { normalizeSeparator } from './utilities/pathUtils'
19
16
import { Any , ArrayConstructor } from './utilities/typeConstructors'
17
+ import { AWS_SCHEME } from './constants'
18
+ import { writeFile } from 'fs-extra'
19
+ import { SystemUtilities } from './systemUtilities'
20
20
21
21
const GOFORMATION_MANIFEST_URL = 'https://api.github.com/repos/awslabs/goformation/releases/latest'
22
+ const SCHEMA_PREFIX = `${ AWS_SCHEME } ://`
22
23
23
24
export type Schemas = { [ key : string ] : vscode . Uri }
24
25
export type SchemaType = 'yaml' | 'json'
@@ -139,29 +140,28 @@ export class SchemaService {
139
140
*/
140
141
export async function getDefaultSchemas ( extensionContext : vscode . ExtensionContext ) : Promise < Schemas | undefined > {
141
142
try {
142
- // Convert the paths to URIs which is what the YAML extension expects
143
- const cfnSchemaUri = vscode . Uri . file (
144
- normalizeSeparator ( path . join ( extensionContext . globalStorageUri . fsPath , 'cloudformation.schema.json' ) )
145
- )
146
- const samSchemaUri = vscode . Uri . file (
147
- normalizeSeparator ( path . join ( extensionContext . globalStorageUri . fsPath , 'sam.schema.json' ) )
148
- )
143
+ const cfnSchemaUri = vscode . Uri . joinPath ( extensionContext . globalStorageUri , 'cloudformation.schema.json' )
144
+ const samSchemaUri = vscode . Uri . joinPath ( extensionContext . globalStorageUri , 'sam.schema.json' )
145
+
149
146
const goformationSchemaVersion = await getPropertyFromJsonUrl ( GOFORMATION_MANIFEST_URL , 'tag_name' )
150
147
151
- await getRemoteOrCachedFile ( {
152
- filepath : cfnSchemaUri . fsPath ,
148
+ await updateSchemaFromRemote ( {
149
+ destination : cfnSchemaUri ,
153
150
version : goformationSchemaVersion ,
154
151
url : `https://raw.githubusercontent.com/awslabs/goformation/${ goformationSchemaVersion } /schema/cloudformation.schema.json` ,
155
152
cacheKey : 'cfnSchemaVersion' ,
156
153
extensionContext,
154
+ title : SCHEMA_PREFIX + 'cloudformation.schema.json' ,
157
155
} )
158
- await getRemoteOrCachedFile ( {
159
- filepath : samSchemaUri . fsPath ,
156
+ await updateSchemaFromRemote ( {
157
+ destination : samSchemaUri ,
160
158
version : goformationSchemaVersion ,
161
159
url : `https://raw.githubusercontent.com/awslabs/goformation/${ goformationSchemaVersion } /schema/sam.schema.json` ,
162
160
cacheKey : 'samSchemaVersion' ,
163
161
extensionContext,
162
+ title : SCHEMA_PREFIX + 'sam.schema.json' ,
164
163
} )
164
+
165
165
return {
166
166
cfn : cfnSchemaUri ,
167
167
sam : samSchemaUri ,
@@ -183,43 +183,52 @@ export async function getDefaultSchemas(extensionContext: vscode.ExtensionContex
183
183
* @param params.cacheKey Cache key to check version against
184
184
* @param params.extensionContext VSCode extension context
185
185
*/
186
- export async function getRemoteOrCachedFile ( params : {
187
- filepath : string
186
+ export async function updateSchemaFromRemote ( params : {
187
+ destination : vscode . Uri
188
188
version ?: string
189
189
url : string
190
190
cacheKey : string
191
191
extensionContext : vscode . ExtensionContext
192
- } ) : Promise < string > {
193
- const dir = path . parse ( params . filepath ) . dir
194
- if ( ! ( await filesystemUtilities . fileExists ( dir ) ) ) {
195
- mkdirSync ( dir , { recursive : true } )
196
- }
197
-
192
+ title : string
193
+ } ) : Promise < void > {
198
194
const cachedVersion = params . extensionContext . globalState . get < string > ( params . cacheKey )
199
195
const outdated = params . version && params . version !== cachedVersion
200
- if ( ! outdated ) {
201
- // Check that the cached file actually can be fetched. Else we might
202
- // never update the cache.
203
- const fileFetcher = new FileResourceFetcher ( params . filepath )
204
- const content = await fileFetcher . get ( )
205
- if ( content ) {
206
- return content
207
- }
196
+
197
+ // Check that the cached file actually can be fetched. Else we might
198
+ // never update the cache.
199
+ const fileFetcher = new FileResourceFetcher ( params . destination . fsPath )
200
+ const cachedContent = await fileFetcher . get ( )
201
+
202
+ if ( ! outdated && cachedContent ) {
203
+ return
208
204
}
209
205
210
- const httpFetcher = new HttpResourceFetcher ( params . url , {
211
- showUrl : true ,
212
- // updates curr version
213
- onSuccess : contents => {
214
- writeFileSync ( params . filepath , contents )
215
- params . extensionContext . globalState . update ( params . cacheKey , params . version )
216
- } ,
217
- } )
218
- const content = await httpFetcher . get ( )
219
- if ( ! content ) {
220
- throw new Error ( `failed to resolve schema: ${ params . filepath } ` )
206
+ try {
207
+ const httpFetcher = new HttpResourceFetcher ( params . url , { showUrl : true } )
208
+ const content = await httpFetcher . get ( )
209
+
210
+ if ( ! content ) {
211
+ throw new Error ( `failed to resolve schema: ${ params . destination } ` )
212
+ }
213
+
214
+ const parsedFile = { ...JSON . parse ( content ) , title : params . title }
215
+ const dir = vscode . Uri . joinPath ( params . destination , '..' )
216
+ await SystemUtilities . createDirectory ( dir )
217
+ await writeFile ( params . destination . fsPath , JSON . stringify ( parsedFile ) )
218
+ await params . extensionContext . globalState . update ( params . cacheKey , params . version ) . then ( undefined , err => {
219
+ getLogger ( ) . warn ( `schemas: failed to update cache key for "${ params . title } ": ${ err ?. message } ` )
220
+ } )
221
+ } catch ( err ) {
222
+ if ( cachedContent ) {
223
+ getLogger ( ) . warn (
224
+ `schemas: failed to fetch the latest version for "${ params . title } ": ${
225
+ ( err as Error ) . message
226
+ } . Using cached schema instead.`
227
+ )
228
+ } else {
229
+ throw err
230
+ }
221
231
}
222
- return content
223
232
}
224
233
225
234
/**
0 commit comments