{"version":3,"sources":["../src/api-meta-init.ts","../src/util/deep.ts"],"sourcesContent":["import path from \"path\"\nimport { readFileSync, writeFileSync } from \"node:fs\"\nimport axios from \"axios\"\nimport openapiTs, { astToString } from \"openapi-typescript\"\nimport { deepDel } from \"./util/deep\"\n\nexport interface InitOptions {\n  /**\n   * openapi json url or array of urls\n   */\n  jsonSchemaPath?: string\n  /**\n   * array of openapi json urls/paths (supports multiple schemas)\n   */\n  jsonSchemaPaths?: string[]\n  /**\n   * auto generated openapi-ts definition path\n   * @default ./api-typing-meta.d.ts\n   */\n  definitionPath?: string\n  /**\n   * auto generated openapi json cache path\n   * @default ./api-typing-meta.openapi.json\n   */\n  jsonCachePath?: string\n}\n\nconst importTemplate = `/* eslint-disable */\n/* prettier-ignore */\n// @ts-nocheck\nimport \"api-typing\"`\n\nconst declareTemplate = `\nexport interface ApiTypingMeta {\n  paths: paths;\n  components: components;\n  operations: operations;\n  external: external;\n}\n\ndeclare module \"api-typing\" {\n  export interface ApiTypingMeta {\n    paths: paths;\n    components: components;\n    operations: operations;\n    external: external;\n  }\n}\n\nexport {}`\n\n/**\n * Merge multiple OpenAPI schemas into a single schema\n */\nconst mergeOpenAPISchemas = (schemas: any[]): any => {\n  if (schemas.length === 1) {\n    return schemas[0]\n  }\n\n  const mergedSchema: any = {\n    openapi: schemas[0]?.openapi || \"3.0.0\",\n    info: {\n      title: \"Merged API\",\n      version: \"1.0.0\",\n      description: \"Merged from multiple OpenAPI schemas\",\n    },\n    paths: {},\n    components: {\n      schemas: {},\n      responses: {},\n      parameters: {},\n      examples: {},\n      requestBodies: {},\n      headers: {},\n      securitySchemes: {},\n      links: {},\n      callbacks: {},\n    },\n    tags: [],\n    servers: [],\n  }\n\n  // Merge each schema\n  schemas.forEach((schema, index) => {\n    if (!schema) return\n\n    // Merge paths\n    if (schema.paths) {\n      Object.keys(schema.paths).forEach((pathKey) => {\n        if (mergedSchema.paths[pathKey]) {\n          // Path already exists, merge the methods\n          Object.assign(mergedSchema.paths[pathKey], schema.paths[pathKey])\n        } else {\n          mergedSchema.paths[pathKey] = schema.paths[pathKey]\n        }\n      })\n    }\n\n    // Merge components\n    if (schema.components) {\n      Object.keys(schema.components).forEach((componentType) => {\n        if (\n          schema.components[componentType] &&\n          typeof schema.components[componentType] === \"object\"\n        ) {\n          Object.assign(\n            mergedSchema.components[componentType] || {},\n            schema.components[componentType],\n          )\n        }\n      })\n    }\n\n    // Merge tags\n    if (schema.tags && Array.isArray(schema.tags)) {\n      schema.tags.forEach((tag: any) => {\n        if (\n          !mergedSchema.tags.find(\n            (existingTag: any) => existingTag.name === tag.name,\n          )\n        ) {\n          mergedSchema.tags.push(tag)\n        }\n      })\n    }\n\n    // Merge servers\n    if (schema.servers && Array.isArray(schema.servers)) {\n      schema.servers.forEach((server: any) => {\n        if (\n          !mergedSchema.servers.find(\n            (existingServer: any) => existingServer.url === server.url,\n          )\n        ) {\n          mergedSchema.servers.push(server)\n        }\n      })\n    }\n\n    // Use info from first non-empty schema, but allow title to be combined\n    if (index === 0 && schema.info) {\n      mergedSchema.info = { ...schema.info }\n    } else if (schema.info && schema.info.title) {\n      if (mergedSchema.info.title === \"Merged API\") {\n        mergedSchema.info.title = schema.info.title\n      } else {\n        mergedSchema.info.title += ` & ${schema.info.title}`\n      }\n    }\n  })\n\n  return mergedSchema\n}\n\n/**\n * Load a single OpenAPI schema from file or URL\n */\nconst loadSchema = async (schemaPath: string): Promise<any> => {\n  if (schemaPath.startsWith(\"http\")) {\n    const response = await axios.get(schemaPath)\n    return deepDel(\n      response.data,\n      \"x-apifox-folder\",\n      \"x-apifox-status\",\n      \"x-apifox-refs\",\n      \"x-apifox-orders\",\n      \"x-apifox-overrides\",\n      \"x-apifox-ignore-properties\",\n    )\n  } else {\n    const str = readFileSync(path.join(path.dirname(\".\"), schemaPath), {\n      encoding: \"utf8\",\n    })\n    return JSON.parse(str)\n  }\n}\n\n/**\n * get api definition from url(s)\n * @param param0 @link InitOptions\n * @returns Promise\n */\nexport const getDefinition = async ({\n  jsonSchemaPath,\n  jsonSchemaPaths,\n  definitionPath = \"./api-typing-meta.d.ts\",\n  jsonCachePath = \"./api-typing-meta.openapi.json\",\n}: InitOptions) => {\n  try {\n    // Handle backward compatibility: if jsonSchemaPath is provided, use it\n    const schemaPaths =\n      jsonSchemaPaths || (jsonSchemaPath ? [jsonSchemaPath] : [])\n\n    if (schemaPaths.length === 0) {\n      throw new Error(\"No schema paths provided\")\n    }\n\n    console.log(`Loading ${schemaPaths.length} OpenAPI schema(s)...`)\n\n    // Load all schemas\n    const schemas = await Promise.all(\n      schemaPaths.map(async (schemaPath, index) => {\n        console.log(\n          `Loading schema ${index + 1}/${schemaPaths.length}: ${schemaPath}`,\n        )\n        return await loadSchema(schemaPath)\n      }),\n    )\n\n    // Merge schemas if multiple, or use single schema\n    const finalSchema =\n      schemas.length > 1 ? mergeOpenAPISchemas(schemas) : schemas[0]\n\n    // Save merged openapi json to local\n    writeFileSync(\n      path.join(path.dirname(\".\"), jsonCachePath),\n      JSON.stringify(finalSchema, null, 2),\n      { encoding: \"utf8\" },\n    )\n    console.log(`Merged OpenAPI JSON saved to ${jsonCachePath}`)\n\n    const output = await openapiTs(finalSchema)\n    const content = `${importTemplate}\\n${astToString(output)}\\n${declareTemplate}`\n    const finalContent = tryDecodeURIComponent(content)\n\n    writeFileSync(\n      path.join(path.dirname(\".\"), `${definitionPath}`),\n      finalContent,\n      {\n        encoding: \"utf8\",\n      },\n    )\n\n    console.log(`TypeScript definitions generated to ${definitionPath}`)\n    return Promise.resolve(true)\n  } catch (error) {\n    console.error(\"Error during getDefinition:\", error)\n    return Promise.reject(error)\n  }\n}\n\nconst tryDecodeURIComponent = (str: string) => {\n  try {\n    return decodeURIComponent(encodeURIComponent(str))\n  } catch (e) {\n    console.log(\"decodeURIComponent error: \", e)\n    return str\n  }\n}\n","export type DeepDel<T, Key extends (string | symbol | number)[]> = T extends\n  | Function\n  | number\n  | null\n  | string\n  | symbol\n  | undefined\n  ? T\n  : T extends (infer A)[]\n  ? A extends object\n    ? DeepDel<A, Key>[]\n    : A extends Function | number | null | string | symbol | undefined\n    ? A[]\n    : [DeepDel<A, Key>]\n  : Pick<\n      { [k in keyof T]: T[k] extends object ? DeepDel<T[k], Key> : T[k] },\n      Exclude<keyof T, Key[number]>\n    >\n\n/**\n * deep delete key from obj\n * @param obj any obj\n * @param keys keys to delete\n * @default [\"_uid\"]\n * @returns obj without key\n */\nexport function deepDel<T, K extends (string | symbol | number)[]>(\n  obj: T,\n  ...keys: K\n): DeepDel<T, K> {\n  if (typeof obj === \"object\") {\n    if (Array.isArray(obj)) {\n      obj.forEach((d) => deepDel(d, ...keys))\n    } else if (obj !== null) {\n      keys.forEach((k) => {\n        delete (obj as any)[k]\n      })\n      for (const k in obj) {\n        deepDel(obj[k], ...keys)\n      }\n    }\n  }\n  return obj as any\n}\n"],"mappings":"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","names":["axios","path","openapiTs"]}