UNPKG

@magda/scripts

Version:

Scripts for building, running, and deploying MAGDA

244 lines (219 loc) 6.6 kB
#!/usr/bin/env node import childProcess from "node:child_process"; import yargs from "yargs"; import fs from "node:fs"; import path from "node:path"; import url from "url"; import { getCurrentDirPath, require } from "@magda/esm-utils"; const __dirname = getCurrentDirPath(); const argv = yargs .options({ input: { description: "Input root folder", type: "string", default: path.dirname(__dirname) }, output: { description: "Where to write output.", type: "string", demand: true }, config: { description: "Configuration direction.", type: "string", demand: true }, include: { description: "Regex for which components to include", type: "string", default: "^magda-.*$" } }) .help().argv; // Run APIDOCjs argv.include = new RegExp(argv.include); const input = fs .readdirSync(argv.input) .filter((x) => x.match(argv.include)) .map((x) => path.join(argv.input, x, "src")) .filter((x) => fs.existsSync(x)) .map((x) => `-i ${x}`) .join(" "); const output = `-o ${argv.output}`; const config = `-c ${argv.config}`; try { const execOutput = childProcess.execSync( `apidoc --debug --private true ${input} -f ".*\.scala$" -f ".*\.ts$" -f ".*\.js$" ${output} ${config}`, { stdio: "pipe" } ); process.stdout.write(execOutput.toString()); } catch (error) { process.stdout.write(error.stdout?.toString() || ""); process.stdout.write(error.stderr?.toString() || ""); } // Convert APIDOC to swagger and openapi specs function makeMeta(apiProject, apiData, flavor) { const title = apiProject.name; const version = require("./package.json").version; const description = apiProject.description; const info = { title, version, description }; if (flavor === "swagger") { const apiUrl = url.parse(apiProject.url); return { swagger: "2.0", info, schemes: [apiUrl.protocol.replace(/[:]/, "")], host: apiUrl.host, basePath: apiUrl.path }; } else { return { openapi: "3.0.1", info, servers: [ { url: apiProject.url } ] }; } } function makePaths(apiProject, apiData, flavor) { const paths = {}; for (const apiCall of apiData) { const { url, type } = apiCall; paths[url] = paths[url] || {}; paths[url][type] = makePathCall(apiCall, flavor); } return { paths }; } function makeParamaterSchema(part, flavor) { let schema = { type: part }; if (part.match(/\[\]$/)) { schema = { type: "array", items: { type: part.substr(0, part.length - 2) } }; } if (flavor === "openapi") { schema = { schema }; } return schema; } function makePathCall(apiCall, flavor) { const { group, title, description } = apiCall; const summary = title; const tags = [group]; const parameters = []; const bodyParameters = { type: "object", properties: {} }; let requestBody = undefined; if (apiCall.parameter && apiCall.parameter.fields) { for (const [type, params] of Object.entries(apiCall.parameter.fields)) { for (const param of params) { if (param.group.match(/body/gi)) { bodyParameters.properties[param.field] = { type: param.type, description: param.description }; if (!param.optional) { bodyParameters.required = bodyParameters.required || []; bodyParameters.required.push(param.field); } } else { parameters.push( Object.assign( { in: "query", name: param.field, description: param.description, required: !param.optional }, makeParamaterSchema(param.type, flavor) ) ); } } if (Object.keys(bodyParameters.properties).length > 0) { if (flavor === "swagger") { parameters.push({ in: "body", name: "body", description: "Request body", required: true, schema: bodyParameters }); } else { requestBody = { content: { "application/json": { schema: bodyParameters } } }; } } } } const responses = {}; if (apiCall.success && apiCall.success.examples) { for (const example of apiCall.success.examples) { responses[example.title] = { description: `<pre>${example.content}<pre>` }; } } if (apiCall.error && apiCall.error.examples) { for (const example of apiCall.error.examples) { responses[example.title] = { description: `<pre>${example.content}<pre>` }; } } return { tags, summary, description, parameters, requestBody, responses }; } const apiProject = JSON.parse( fs.readFileSync(path.join(argv.output, "api_project.json")) ); const apiData = JSON.parse( fs.readFileSync(path.join(argv.output, "api_data.json")) ); fs.writeFileSync( path.join(argv.output, "swagger.json"), JSON.stringify( Object.assign( makeMeta(apiProject, apiData, "swagger"), makePaths(apiProject, apiData, "swagger") ), null, 2 ) ); fs.writeFileSync( path.join(argv.output, "openapi.json"), JSON.stringify( Object.assign( makeMeta(apiProject, apiData, "openapi"), makePaths(apiProject, apiData, "openapi") ), null, 2 ) );