From 637d50143ad8984df55843f7d1f3352719277902 Mon Sep 17 00:00:00 2001 From: abrahamchandy95 Date: Wed, 4 Mar 2026 19:47:31 +0530 Subject: [PATCH 1/3] fixed frontend issue for solution kit readmes and schemas not showing together --- scripts/markdown.js | 50 +++++---- scripts/script.js | 241 +++++++++++++------------------------------- 2 files changed, 102 insertions(+), 189 deletions(-) diff --git a/scripts/markdown.js b/scripts/markdown.js index 5c106ad1..e05d3027 100644 --- a/scripts/markdown.js +++ b/scripts/markdown.js @@ -25,11 +25,12 @@ export function renderMarkdown(solution, file) { - - - TigerGraph - ${normalizeName( - basename(solution, extname(solution)) - )} - ${normalizeName(basename(file, extname(file)))} + + + TigerGraph - ${normalizeName(solutionId)} - ${normalizeName( + basename(file, extname(file)) + )} + + + } + - + +
${htmlContent}
diff --git a/scripts/script.js b/scripts/script.js index e3e6b3bd..d280d8fa 100644 --- a/scripts/script.js +++ b/scripts/script.js @@ -25,15 +25,44 @@ const commonBucketConfig = { Bucket: getBucketName(), }; + +function toS3Key(p) { + return p.split(path.sep).join("/"); +} +function toLocalPathFromS3Key(k) { + return k.split("/").join(path.sep); +} + + +function mdToHtmlKey(markdownFile) { + const htmlLocalPath = path.join( + path.dirname(markdownFile), + path.basename(markdownFile, path.extname(markdownFile)) + ".html" + ); + return toS3Key(htmlLocalPath); +} + + +function findReadmeFile(solutionDir) { + try { + const files = fs.readdirSync(solutionDir); + const readme = files.find((f) => f.toLowerCase() === "readme.md"); + return readme ? path.join(solutionDir, readme) : null; + } catch (_) { + return null; + } +} + async function syncFile(file, cacheControl = disableCacheControl) { const fileStat = fs.statSync(file); + const s3Key = toS3Key(file); let shouldUpload = true; try { const object = await s3 .headObject({ Bucket: getBucketName(), - Key: file, + Key: s3Key, }) .promise(); @@ -48,6 +77,7 @@ async function syncFile(file, cacheControl = disableCacheControl) { } } catch (error) { if (error.code === "NotFound") { + // keep shouldUpload = true } else { shouldUpload = false; } @@ -57,7 +87,7 @@ async function syncFile(file, cacheControl = disableCacheControl) { if (shouldUpload) { const params = { ...commonBucketConfig, - Key: file, + Key: s3Key, Body: fs.readFileSync(file), ContentType: mime.getType(path.extname(file)), CacheControl: cacheControl, @@ -68,28 +98,30 @@ async function syncFile(file, cacheControl = disableCacheControl) { try { const data = await s3.upload(params).promise(); - console.log(`${file} => ${data.Location}`); + console.log(`${s3Key} => ${data.Location}`); return data.Location; } catch (error) { console.error(`Error uploading ${file}:`, error); } } - return `https://${getBucketName()}.s3.us-west-1.amazonaws.com/${file}`; + return `https://${getBucketName()}.s3.us-west-1.amazonaws.com/${s3Key}`; } async function syncFolder(folder, cacheControl = disableCacheControl) { const result = await s3 .listObjectsV2({ Bucket: getBucketName(), - Prefix: folder, + Prefix: toS3Key(folder), }) .promise(); - const conents = result.Contents; + + const conents = result.Contents || []; // small robustness improvement (both branches assumed Contents exists) // delete all remote file not existed on local for (let content of conents) { - if (!fs.existsSync(content.Key)) { + const localPath = toLocalPathFromS3Key(content.Key); + if (!fs.existsSync(localPath)) { console.log(`${content.Key} not existed on local, delete it.`); await s3 .deleteObject({ @@ -119,17 +151,6 @@ function getAllSolutions() { return metaFiles.map((file) => file.slice(0, -"/meta/meta.yml".length)); } -// Find a case-insensitive Readme.md file in the solution root -function findReadmeFile(solutionDir) { - try { - const files = fs.readdirSync(solutionDir); - const readme = files.find((f) => f.toLowerCase() === "readme.md"); - return readme ? path.join(solutionDir, readme) : null; - } catch (_) { - return null; - } -} - async function getSolution(dir) { console.log("\n\nProcessing", dir, "..."); const file = fs.readFileSync(`${dir}/meta/meta.yml`, "utf8"); @@ -163,24 +184,23 @@ async function getSolution(dir) { await syncFolder(`${dir}/model`); await syncFolder(`${dir}/doc`); - const insightsFiles = await globSync(`${dir}/meta/Insights*.json`); + const insightsFiles = globSync(`${dir}/meta/Insights*.json`); content.metadata.hasInsights = insightsFiles.length > 0; - const markdownFiles = globSync([ - `${dir}/model/**/*.md`, - `${dir}/doc/**/*.md`, - ]); + // KEEP (from main): docLinks behavior stays the same so Savanna panes keep working + const markdownFiles = globSync([`${dir}/model/**/*.md`, `${dir}/doc/**/*.md`]); const htmlFiles = []; + for (let markdownFile of markdownFiles) { const html = renderMarkdown(dir, markdownFile); - const htmlFile = path.join( - path.dirname(markdownFile), - path.basename(markdownFile, path.extname(markdownFile)) + ".html" - ); + + // UPDATED (merge helper): + // safer extension replacement + consistent S3 key formatting + const htmlKey = mdToHtmlKey(markdownFile); const params = { ...commonBucketConfig, - Key: htmlFile, + Key: htmlKey, Body: html, ContentType: "text/html", CacheControl: disableCacheControl, @@ -188,7 +208,7 @@ async function getSolution(dir) { try { const data = await s3.upload(params).promise(); - console.log(`${htmlFile} => ${data.Location}`); + console.log(`${htmlKey} => ${data.Location}`); htmlFiles.push(data.Location); } catch (error) { console.error("Error uploading html file:", error); @@ -196,18 +216,14 @@ async function getSolution(dir) { } } - // Handle root-level README (case-insensitive) const readmeFile = findReadmeFile(dir); if (readmeFile) { const html = renderMarkdown(dir, readmeFile); - const htmlFile = path.join( - path.dirname(readmeFile), - path.basename(readmeFile, path.extname(readmeFile)) + ".html" - ); + const htmlKey = mdToHtmlKey(readmeFile); const params = { ...commonBucketConfig, - Key: htmlFile, + Key: htmlKey, Body: html, ContentType: "text/html", CacheControl: disableCacheControl, @@ -215,11 +231,11 @@ async function getSolution(dir) { try { const data = await s3.upload(params).promise(); - console.log(`${htmlFile} => ${data.Location}`); - // Expose README link separately + console.log(`${htmlKey} => ${data.Location}`); + content.metadata.readme = data.Location; } catch (error) { - console.error("Error uploading html file:", error); + console.error("Error uploading README html file:", error); process.exit(1); } } @@ -256,9 +272,7 @@ function concatFilesForQuery(files, lastFiles, graphName, is_library) { content += `INSTALL QUERY ALL\n`; } - const lastFileContents = lastFiles.map((file) => - fs.readFileSync(file, "utf8") - ); + const lastFileContents = lastFiles.map((file) => fs.readFileSync(file, "utf8")); for (let i = 0; i < lastFiles.length; i++) { content += "#File: " + lastFiles[i] + "\n"; content += lastFileContents[i]; @@ -278,9 +292,7 @@ function concatFilesForLastFile(lastFiles, graphName, is_library) { } let content = `USE GRAPH ${graphName}\n`; - const lastFileContents = lastFiles.map((file) => - fs.readFileSync(file, "utf8") - ); + const lastFileContents = lastFiles.map((file) => fs.readFileSync(file, "utf8")); for (let i = 0; i < lastFiles.length; i++) { content += lastFileContents[i]; content += "\n"; @@ -294,9 +306,7 @@ function concatFilesForLastFile(lastFiles, graphName, is_library) { function concatLoadingFiles(files) { const fileContents = files .map((file) => fs.readFileSync(file, "utf8")) - .map((content) => - content.replaceAll("tigergraph-solution-kits", getBucketName()) - ); + .map((content) => content.replaceAll("tigergraph-solution-kits", getBucketName())); let content = ""; for (let i = 0; i < files.length; i++) { @@ -321,28 +331,25 @@ async function getSolutionDetail(dir, first, last, graphName, is_library) { styleJSON = fs.readFileSync(`${dir}/meta/style.json`, "utf8"); } catch (error) {} - const queryFiles = globSync([ - `${dir}/queries/*.gsql`, - `${dir}/queries/*/*.gsql`, - ]); + const queryFiles = globSync([`${dir}/queries/*.gsql`, `${dir}/queries/*/*.gsql`]); const firstFiles = []; for (let file of first) { - const path = `${dir}/queries/${file}`; - if (queryFiles.includes(path)) { - firstFiles.push(path); + const p = `${dir}/queries/${file}`; + if (queryFiles.includes(p)) { + firstFiles.push(p); } } const lastFiles = []; for (let file of last) { - const path = `${dir}/queries/${file}`; - if (queryFiles.includes(path)) { - lastFiles.push(path); + const p = `${dir}/queries/${file}`; + if (queryFiles.includes(p)) { + lastFiles.push(p); } } const middleFiles = queryFiles.filter( - (file) => !firstFiles.includes(file) && !lastFiles.includes(file) + (f) => !firstFiles.includes(f) && !lastFiles.includes(f) ); const query = concatFilesForQuery( @@ -360,7 +367,7 @@ async function getSolutionDetail(dir, first, last, graphName, is_library) { const resetFiles = globSync(`${dir}/reset/*.gsql`); const reset = concatFiles(resetFiles); - const insightsFiles = await globSync(`${dir}/meta/Insights*.json`); + const insightsFiles = globSync(`${dir}/meta/Insights*.json`); const insightsApplications = []; for (let insightsFile of insightsFiles) { const application = JSON.parse(fs.readFileSync(`${insightsFile}`, "utf8")); @@ -382,10 +389,9 @@ async function getSolutionDetail(dir, first, last, graphName, is_library) { async function main() { const solutions = getAllSolutions(); const metadataList = []; + for (let solution of solutions) { - const { metadata, queries: { first, last } = {} } = await getSolution( - solution - ); + const { metadata, queries: { first, last } = {} } = await getSolution(solution); if (metadata.production === false) { console.log("hide solution", metadata.name); @@ -393,7 +399,7 @@ async function main() { } metadataList.push({ - ...metadata, + ...metadata, // includes metadata.readme when present (ADDED path) path: solution, }); @@ -404,6 +410,7 @@ async function main() { metadata.graph, metadata.is_library ); + const params = { ...commonBucketConfig, Key: `${solution}/meta.json`, @@ -422,6 +429,7 @@ async function main() { } } + // list.json now also contains metadata.readme per solution (ADDED) const params = { ...commonBucketConfig, Key: "list.json", @@ -459,110 +467,3 @@ async function main() { } main(); - -// Debug code -// function decodeSolution(path) { -// const file = fs.readFileSync(path, "utf8"); -// const content = JSON.parse(file); -// const { schema, query, sampleLoadingJob, reset } = content; -// console.log(schema); -// console.log(query); -// console.log(sampleLoadingJob); -// console.log(reset); -// } - -async function generateFileForImportSolution() { - const dir = "solution_metadata"; - const list_data = []; - fs.mkdirSync(dir); - - const solutions = getAllSolutions(); - const metadataList = []; - for (let solution of solutions) { - const { metadata, queries: { first, last } = {} } = await getSolution( - solution - ); - - if (metadata.production === false) { - console.log("hide solution", metadata.name); - continue; - } - - const solutionDetails = await getSolutionDetail( - solution, - first || [], - last || [], - metadata.graph, - metadata.is_library - ); - - // strip aws s3 url prefix - if (metadata.icon) { - metadata.icon = - dir + "/" + metadata.icon.slice(metadata.icon.indexOf(solution)); - } - if (metadata.images) { - metadata.images = metadata.images.map((image) => { - return dir + "/" + image.slice(image.indexOf(solution)); - }); - } - - metadataList.push({ - ...metadata, - path: solution, - initQuery: solutionDetails.lastQuery, - }); - - if (!solutionDetails.is_library) { - // https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com/financial_crime/application_fraud/4.x/solution_with_data.tar.gz - const solution_with_data = `https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com/${solution}/4.x/solution_with_data.tar.gz`; - const solution_without_data = `https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com/${solution}/4.x/solution_without_data.tar.gz`; - list_data.push({ - name: metadata.name, - path: solution, - graph: metadata.graph, - solution_with_data: solution_with_data, - solution_without_data: solution_without_data, - }); - } - - // copy images and icon - fs.mkdirSync(`${dir}/${solution}/meta`, { recursive: true }); - if (fs.existsSync(`${solution}/meta/icon.png`)) { - fs.copyFileSync( - `${solution}/meta/icon.png`, - `${dir}/${solution}/meta/icon.png` - ); - } else if (fs.existsSync(`${solution}/meta/icon.jpg`)) { - fs.copyFileSync( - `${solution}/meta/icon.jpg`, - `${dir}/${solution}/meta/icon.jpg` - ); - } else if (fs.existsSync(`${solution}/meta/icon.svg`)) { - fs.copyFileSync( - `${solution}/meta/icon.svg`, - `${dir}/${solution}/meta/icon.svg` - ); - } - if (fs.existsSync(`${solution}/meta/images`)) { - fs.mkdirSync(`${dir}/${solution}/meta/images`); - const images = globSync([`${solution}/meta/images/*`]); - for (let image of images) { - const fileName = path.basename(image); - fs.copyFileSync(image, `${dir}/${solution}/meta/images/${fileName}`); - } - } - } - - fs.writeFileSync( - `${dir}/solution_list.json`, - JSON.stringify(metadataList, null, 2) - ); - fs.writeFileSync( - `${dir}/solution_data.json`, - JSON.stringify(list_data, null, 2) - ); -} - -// generate meta data for import solution, used by https://dl.tigergraph.com/?tab=solution -// generateFileForImportSolution(); From bd75f6f54bbadfbd5d6218df86e8aff86355757c Mon Sep 17 00:00:00 2001 From: abrahamchandy95 Date: Wed, 4 Mar 2026 19:59:52 +0530 Subject: [PATCH 2/3] added back the debugging function for future use --- scripts/script.js | 78 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/scripts/script.js b/scripts/script.js index d280d8fa..ce962f3c 100644 --- a/scripts/script.js +++ b/scripts/script.js @@ -467,3 +467,81 @@ async function main() { } main(); + +async function generateFileForImportSolution() { + const dir = "solution_metadata"; + const list_data = []; + const solutions = getAllSolutions(); + const metadataList = []; + + fs.mkdirSync(dir, { recursive: true }); + + for (let solution of solutions) { + const { metadata, queries: { first, last } = {} } = await getSolution(solution); + + if (metadata.production === false) { + console.log("hide solution", metadata.name); + continue; + } + + const solutionDetails = await getSolutionDetail( + solution, + first || [], + last || [], + metadata.graph, + metadata.is_library + ); + + if (metadata.icon) { + metadata.icon = dir + "/" + metadata.icon.slice(metadata.icon.indexOf(solution)); + } + if (metadata.images) { + metadata.images = metadata.images.map((image) => { + return dir + "/" + image.slice(image.indexOf(solution)); + }); + } + + metadataList.push({ + ...metadata, + path: solution, + initQuery: solutionDetails.lastQuery, + }); + + + if (!metadata.is_library) { + // https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com//4.x/solution_with_data.tar.gz + const solution_with_data = `https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com/${solution}/4.x/solution_with_data.tar.gz`; + const solution_without_data = `https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com/${solution}/4.x/solution_without_data.tar.gz`; + list_data.push({ + name: metadata.name, + path: solution, + graph: metadata.graph, + solution_with_data, + solution_without_data, + }); + } + + // copy images and icon (kept from dev branch) + fs.mkdirSync(`${dir}/${solution}/meta`, { recursive: true }); + + if (fs.existsSync(`${solution}/meta/icon.png`)) { + fs.copyFileSync(`${solution}/meta/icon.png`, `${dir}/${solution}/meta/icon.png`); + } else if (fs.existsSync(`${solution}/meta/icon.jpg`)) { + fs.copyFileSync(`${solution}/meta/icon.jpg`, `${dir}/${solution}/meta/icon.jpg`); + } else if (fs.existsSync(`${solution}/meta/icon.svg`)) { + fs.copyFileSync(`${solution}/meta/icon.svg`, `${dir}/${solution}/meta/icon.svg`); + } + + if (fs.existsSync(`${solution}/meta/images`)) { + fs.mkdirSync(`${dir}/${solution}/meta/images`, { recursive: true }); + const images = globSync([`${solution}/meta/images/*`]); + for (let image of images) { + const fileName = path.basename(image); + fs.copyFileSync(image, `${dir}/${solution}/meta/images/${fileName}`); + } + } + } + + fs.writeFileSync(`${dir}/solution_list.json`, JSON.stringify(metadataList, null, 2)); + fs.writeFileSync(`${dir}/solution_data.json`, JSON.stringify(list_data, null, 2)); +} From ca090bfe31ef0ceb076e483fbc322daa3bcd7d9d Mon Sep 17 00:00:00 2001 From: abrahamchandy95 Date: Wed, 4 Mar 2026 20:47:06 +0530 Subject: [PATCH 3/3] fixed ui reference error --- scripts/markdown.js | 28 ++++++------ scripts/script.js | 104 +++++++++++++++++--------------------------- 2 files changed, 54 insertions(+), 78 deletions(-) diff --git a/scripts/markdown.js b/scripts/markdown.js index e05d3027..3aaa0f79 100644 --- a/scripts/markdown.js +++ b/scripts/markdown.js @@ -7,10 +7,7 @@ function capitalize(s) { } function normalizeName(name) { - return name - .split("_") - .map((name) => capitalize(name)) - .join(" "); + return name.split("_").map(capitalize).join(" "); } export function renderMarkdown(solution, file) { @@ -19,17 +16,18 @@ export function renderMarkdown(solution, file) { // Convert Markdown to HTML const htmlContent = marked(content); + const solutionId = basename(solution, extname(solution)); + const fileId = basename(file, extname(file)); + // Wrap the HTML content with the necessary HTML and CSS const htmlTemplate = ` - - - TigerGraph - ${normalizeName(solutionId)} - ${normalizeName( - basename(file, extname(file)) - )} + + + TigerGraph - ${normalizeName(solutionId)} - ${normalizeName(fileId)} +
${htmlContent} diff --git a/scripts/script.js b/scripts/script.js index ce962f3c..6846b07c 100644 --- a/scripts/script.js +++ b/scripts/script.js @@ -25,44 +25,15 @@ const commonBucketConfig = { Bucket: getBucketName(), }; - -function toS3Key(p) { - return p.split(path.sep).join("/"); -} -function toLocalPathFromS3Key(k) { - return k.split("/").join(path.sep); -} - - -function mdToHtmlKey(markdownFile) { - const htmlLocalPath = path.join( - path.dirname(markdownFile), - path.basename(markdownFile, path.extname(markdownFile)) + ".html" - ); - return toS3Key(htmlLocalPath); -} - - -function findReadmeFile(solutionDir) { - try { - const files = fs.readdirSync(solutionDir); - const readme = files.find((f) => f.toLowerCase() === "readme.md"); - return readme ? path.join(solutionDir, readme) : null; - } catch (_) { - return null; - } -} - async function syncFile(file, cacheControl = disableCacheControl) { const fileStat = fs.statSync(file); - const s3Key = toS3Key(file); let shouldUpload = true; try { const object = await s3 .headObject({ Bucket: getBucketName(), - Key: s3Key, + Key: file, }) .promise(); @@ -77,7 +48,6 @@ async function syncFile(file, cacheControl = disableCacheControl) { } } catch (error) { if (error.code === "NotFound") { - // keep shouldUpload = true } else { shouldUpload = false; } @@ -87,7 +57,7 @@ async function syncFile(file, cacheControl = disableCacheControl) { if (shouldUpload) { const params = { ...commonBucketConfig, - Key: s3Key, + Key: file, Body: fs.readFileSync(file), ContentType: mime.getType(path.extname(file)), CacheControl: cacheControl, @@ -98,30 +68,28 @@ async function syncFile(file, cacheControl = disableCacheControl) { try { const data = await s3.upload(params).promise(); - console.log(`${s3Key} => ${data.Location}`); + console.log(`${file} => ${data.Location}`); return data.Location; } catch (error) { console.error(`Error uploading ${file}:`, error); } } - return `https://${getBucketName()}.s3.us-west-1.amazonaws.com/${s3Key}`; + return `https://${getBucketName()}.s3.us-west-1.amazonaws.com/${file}`; } async function syncFolder(folder, cacheControl = disableCacheControl) { const result = await s3 .listObjectsV2({ Bucket: getBucketName(), - Prefix: toS3Key(folder), + Prefix: folder, }) .promise(); - - const conents = result.Contents || []; // small robustness improvement (both branches assumed Contents exists) + const conents = result.Contents || []; // delete all remote file not existed on local for (let content of conents) { - const localPath = toLocalPathFromS3Key(content.Key); - if (!fs.existsSync(localPath)) { + if (!fs.existsSync(content.Key)) { console.log(`${content.Key} not existed on local, delete it.`); await s3 .deleteObject({ @@ -151,6 +119,17 @@ function getAllSolutions() { return metaFiles.map((file) => file.slice(0, -"/meta/meta.yml".length)); } + +function findReadmeFile(solutionDir) { + try { + const files = fs.readdirSync(solutionDir); + const readme = files.find((f) => f.toLowerCase() === "readme.md"); + return readme ? path.join(solutionDir, readme) : null; + } catch (_) { + return null; + } +} + async function getSolution(dir) { console.log("\n\nProcessing", dir, "..."); const file = fs.readFileSync(`${dir}/meta/meta.yml`, "utf8"); @@ -187,20 +166,19 @@ async function getSolution(dir) { const insightsFiles = globSync(`${dir}/meta/Insights*.json`); content.metadata.hasInsights = insightsFiles.length > 0; - // KEEP (from main): docLinks behavior stays the same so Savanna panes keep working const markdownFiles = globSync([`${dir}/model/**/*.md`, `${dir}/doc/**/*.md`]); const htmlFiles = []; - for (let markdownFile of markdownFiles) { const html = renderMarkdown(dir, markdownFile); - // UPDATED (merge helper): - // safer extension replacement + consistent S3 key formatting - const htmlKey = mdToHtmlKey(markdownFile); + const htmlFile = path.join( + path.dirname(markdownFile), + path.basename(markdownFile, path.extname(markdownFile)) + ".html" + ); const params = { ...commonBucketConfig, - Key: htmlKey, + Key: htmlFile, Body: html, ContentType: "text/html", CacheControl: disableCacheControl, @@ -208,7 +186,7 @@ async function getSolution(dir) { try { const data = await s3.upload(params).promise(); - console.log(`${htmlKey} => ${data.Location}`); + console.log(`${htmlFile} => ${data.Location}`); htmlFiles.push(data.Location); } catch (error) { console.error("Error uploading html file:", error); @@ -216,14 +194,18 @@ async function getSolution(dir) { } } + const readmeFile = findReadmeFile(dir); if (readmeFile) { const html = renderMarkdown(dir, readmeFile); - const htmlKey = mdToHtmlKey(readmeFile); + const htmlFile = path.join( + path.dirname(readmeFile), + path.basename(readmeFile, path.extname(readmeFile)) + ".html" + ); const params = { ...commonBucketConfig, - Key: htmlKey, + Key: htmlFile, Body: html, ContentType: "text/html", CacheControl: disableCacheControl, @@ -231,11 +213,10 @@ async function getSolution(dir) { try { const data = await s3.upload(params).promise(); - console.log(`${htmlKey} => ${data.Location}`); - + console.log(`${htmlFile} => ${data.Location}`); content.metadata.readme = data.Location; } catch (error) { - console.error("Error uploading README html file:", error); + console.error("Error uploading html file:", error); process.exit(1); } } @@ -389,7 +370,6 @@ async function getSolutionDetail(dir, first, last, graphName, is_library) { async function main() { const solutions = getAllSolutions(); const metadataList = []; - for (let solution of solutions) { const { metadata, queries: { first, last } = {} } = await getSolution(solution); @@ -399,7 +379,7 @@ async function main() { } metadataList.push({ - ...metadata, // includes metadata.readme when present (ADDED path) + ...metadata, // includes metadata.images, metadata.docLinks, and ADDED metadata.readme when present path: solution, }); @@ -429,7 +409,6 @@ async function main() { } } - // list.json now also contains metadata.readme per solution (ADDED) const params = { ...commonBucketConfig, Key: "list.json", @@ -471,11 +450,11 @@ main(); async function generateFileForImportSolution() { const dir = "solution_metadata"; const list_data = []; - const solutions = getAllSolutions(); - const metadataList = []; - + // (small safety: allow reruns without throwing) fs.mkdirSync(dir, { recursive: true }); + const solutions = getAllSolutions(); + const metadataList = []; for (let solution of solutions) { const { metadata, queries: { first, last } = {} } = await getSolution(solution); @@ -492,6 +471,7 @@ async function generateFileForImportSolution() { metadata.is_library ); + // strip aws s3 url prefix if (metadata.icon) { metadata.icon = dir + "/" + metadata.icon.slice(metadata.icon.indexOf(solution)); } @@ -509,21 +489,19 @@ async function generateFileForImportSolution() { if (!metadata.is_library) { - // https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com//4.x/solution_with_data.tar.gz const solution_with_data = `https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com/${solution}/4.x/solution_with_data.tar.gz`; const solution_without_data = `https://tigergraph-solution-kits-prod.s3.us-west-1.amazonaws.com/${solution}/4.x/solution_without_data.tar.gz`; list_data.push({ name: metadata.name, path: solution, graph: metadata.graph, - solution_with_data, - solution_without_data, + solution_with_data: solution_with_data, + solution_without_data: solution_without_data, }); } - // copy images and icon (kept from dev branch) + // copy images and icon fs.mkdirSync(`${dir}/${solution}/meta`, { recursive: true }); - if (fs.existsSync(`${solution}/meta/icon.png`)) { fs.copyFileSync(`${solution}/meta/icon.png`, `${dir}/${solution}/meta/icon.png`); } else if (fs.existsSync(`${solution}/meta/icon.jpg`)) { @@ -531,7 +509,6 @@ async function generateFileForImportSolution() { } else if (fs.existsSync(`${solution}/meta/icon.svg`)) { fs.copyFileSync(`${solution}/meta/icon.svg`, `${dir}/${solution}/meta/icon.svg`); } - if (fs.existsSync(`${solution}/meta/images`)) { fs.mkdirSync(`${dir}/${solution}/meta/images`, { recursive: true }); const images = globSync([`${solution}/meta/images/*`]); @@ -545,3 +522,4 @@ async function generateFileForImportSolution() { fs.writeFileSync(`${dir}/solution_list.json`, JSON.stringify(metadataList, null, 2)); fs.writeFileSync(`${dir}/solution_data.json`, JSON.stringify(list_data, null, 2)); } +