UNPKG

supertokens-web-js

Version:
186 lines (149 loc) β€’ 6.42 kB
const fs = require("fs/promises"); const path = require("path"); const { exec } = require("child_process"); // Dynamic import for node-fetch because it’s an ESM module const fetch = (...args) => import("node-fetch").then(({ default: fetch }) => fetch(...args)); const frontendJsonPath = path.join(__dirname, "..", "frontendDriverInterfaceSupported.json"); const specsDir = path.join(__dirname, "..", "specs"); const libDir = path.join(__dirname, "..", "lib", "ts", "sdk", "versions"); const BASE_URL = "https://raw.githubusercontent.com/supertokens/frontend-driver-interface/refs/heads"; async function run() { const localFilePath = process.argv[2]; const localVersion = process.argv[3]; if (localFilePath && localVersion) { await processLocalSpec(localFilePath, localVersion); } else { await processRemoteSpecs(); } } async function processLocalSpec(filePath, version) { const outputDir = path.join(libDir, version); const outputPath = path.join(outputDir, "schema.d.ts"); await fs.mkdir(outputDir, { recursive: true }); console.log(`πŸ“„ Using local spec file: ${filePath}`); await execPromise(`npx openapi-typescript ${filePath} -o ${outputPath}`); let schemaContent = await fs.readFile(outputPath, "utf-8"); schemaContent = schemaContent .replace(/"\/\{apiBasePath\}([^"]*)":/g, (_, rest) => `"${rest}":`) .replace(/Record<string, never>/g, "Record<string, unknown>") .replace(/\bstatus\?\s*:/g, "status:"); await fs.writeFile(outputPath, schemaContent, "utf-8"); console.log(`βœ… Generated and cleaned schema for local version ${version}`); console.log("⚠️ Skipping remote specs generation for local version"); } async function processRemoteSpecs() { const file = await fs.readFile(frontendJsonPath, "utf-8"); const json = JSON.parse(file); const versions = json.versions; console.log("πŸ“ Creating specs directory..."); await fs.mkdir(specsDir, { recursive: true }); try { for (const version of versions) { const url = `${BASE_URL}/${version}/api_spec.yaml`; const specPath = path.join(specsDir, `api_spec_${version}.yaml`); console.log(`πŸ“₯ Downloading: ${url}`); const res = await fetch(url); if (!res.ok) { console.error(`❌ Failed to fetch ${url}: ${res.statusText}`); continue; } const specContent = await res.text(); await fs.writeFile(specPath, specContent, "utf-8"); console.log(`βœ… Saved to ${specPath}`); } for (const version of versions) { const inputPath = path.join(specsDir, `api_spec_${version}.yaml`); const outputDir = path.join(libDir, version); const outputPath = path.join(outputDir, "schema.d.ts"); await fs.mkdir(outputDir, { recursive: true }); console.log(`πŸ”§ Generating schema for version ${version}...`); await execPromise(`npx openapi-typescript ${inputPath} -o ${outputPath}`); console.log(`🧹 Post-processing ${outputPath}...`); let schemaContent = await fs.readFile(outputPath, "utf-8"); schemaContent = schemaContent .replace(/"\/\{apiBasePath\}([^"]*)":/g, (_, rest) => `"${rest}":`) .replace(/Record<string, never>/g, "Record<string, unknown>") .replace(/\bstatus\?\s*:/g, "status:"); await fs.writeFile(outputPath, schemaContent, "utf-8"); console.log(`βœ… Cleaned ${outputPath}`); } } finally { console.log("🧹 Cleaning up specs directory..."); await fs.rm(specsDir, { recursive: true, force: true }); console.log("βœ… Specs directory deleted."); } await generatePathsFile(versions); console.log("βœ… Created paths.ts for all versions"); console.log("πŸŽ‰ All done!"); } async function generatePathsFile(versions) { const outputPath = path.join(libDir, "..", "paths.ts"); if (versions.length === 0) { console.warn("⚠️ No versions found β€” skipping paths.ts generation."); return; } if (versions.length === 1) { const singleTemplate = (version) => `/* This file was auto-generated by scripts/generate-schema.js */ import { paths } from "./versions/${version}/schema"; export { paths }; `; await fs.writeFile(outputPath, singleTemplate(versions[0]), "utf-8"); console.log(`βœ… Created single-version paths.ts for ${versions[0]}`); } else { const imports = versions .map((v) => `import { paths as pathsV${v.replace(/\./g, "_")} } from "./versions/${v}/schema";`) .join("\n"); const mergedTemplate = `type MergeMethods<M1, M2> = { [K in keyof M1 | keyof M2]: K extends keyof M1 ? K extends keyof M2 ? M1[K] | M2[K] : M1[K] : K extends keyof M2 ? M2[K] : never; }; type MergePaths<P1, P2> = { [K in keyof P1 | keyof P2]: K extends keyof P1 ? K extends keyof P2 ? MergeMethods<P1[K], P2[K]> : P1[K] : K extends keyof P2 ? P2[K] : never; }; type MergeManyPaths<T extends Record<string, any>[]> = T extends [infer First, ...infer Rest] ? First extends Record<string, any> ? Rest extends Record<string, any>[] ? MergePaths<First, MergeManyPaths<Rest>> : First : never : {}; `; const mergedTypes = `export type paths = MergeManyPaths<[${versions .map((v) => `pathsV${v.replace(/\./g, "_")}`) .join(", ")}]>;`; const fullContent = `/* This file was auto-generated by scripts/generate-schema.js */ ${imports} ${mergedTemplate} ${mergedTypes} `; await fs.writeFile(outputPath, fullContent, "utf-8"); console.log(`βœ… Created merged paths.ts for ${versions.length} versions`); } } function execPromise(command) { return new Promise((resolve, reject) => { exec(command, (err, stdout, stderr) => { if (err) { console.error(`Error: ${stderr}`); reject(err); } else { resolve(stdout); } }); }); } run().catch((err) => { console.error("Unhandled error:", err); process.exit(1); });