{"version":3,"sources":["../src/index.ts","../src/endpoints.ts","../src/error.ts","../src/sdkBuilder.ts"],"sourcesContent":["// import './fetch';\n\nexport * from './endpoints';\nexport * from './error';\nexport * from './sdkBuilder';\n","import qs from 'qs';\nimport { MetorialSDKError } from './error';\n\nexport interface MetorialRequest {\n  path: string | string[];\n  host?: string;\n  query?: Record<string, any>;\n  body?: Record<string, any> | FormData;\n  headers?: Record<string, string>;\n}\n\ntype Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\nexport class MetorialEndpointManager<Config> {\n  constructor(\n    public readonly config: Config,\n    public readonly apiHost: string,\n    public readonly getHeaders: (config: Config) => Record<string, string>,\n    public readonly fetchImpl: typeof fetch | undefined | null,\n    private readonly options: {\n      enableDebugLogging: boolean;\n    }\n  ) {}\n\n  get fetch() {\n    return this.fetchImpl ?? globalThis.fetch.bind(globalThis);\n  }\n\n  private async request(method: Method, request: MetorialRequest, tryCount = 0): Promise<any> {\n    let path = Array.isArray(request.path) ? request.path.join('/') : request.path;\n    let url = new URL(request.host ?? this.apiHost);\n    url.pathname = url.pathname.replace(/\\/$/, '') + '/' + path.replace(/^\\//, '');\n\n    if (request.query) {\n      url.search = qs.stringify(request.query);\n    }\n\n    let defaultHeaders = this.getHeaders?.(this.config) ?? {};\n    let mergedHeaders: Record<string, string> = {\n      ...defaultHeaders,\n      ...(request.headers ?? {})\n    };\n    let headers = new Headers(mergedHeaders);\n\n    let hasBody = method === 'POST' || method === 'PUT' || method === 'PATCH';\n    let isFormData = request.body instanceof FormData;\n\n    if (hasBody && !isFormData && !headers.has('Content-Type')) {\n      headers.set('Content-Type', 'application/json');\n    }\n\n    if (this.options.enableDebugLogging) {\n      console.log(`[Metorial] ${method} ${url.toString()}`, {\n        body: request.body,\n        query: request.query,\n        headers: Object.fromEntries(headers.entries())\n      });\n    }\n\n    let response: Response;\n    try {\n      response = await this.fetch(url.toString(), {\n        method,\n        headers,\n        body: hasBody\n          ? isFormData\n            ? (request.body as FormData)\n            : JSON.stringify(request.body ?? {})\n          : undefined,\n        credentials: 'include',\n        redirect: 'follow',\n        referrerPolicy: 'no-referrer-when-downgrade',\n        cache: 'no-cache',\n        keepalive: true,\n        mode: 'cors'\n      });\n\n      // Re-try for too many requests\n      if (response.status === 429 && tryCount < 3) {\n        let retryAfter = response.headers.get('Retry-After');\n        if (retryAfter) {\n          await new Promise(resolve => setTimeout(resolve, (parseInt(retryAfter) + 3) * 1000));\n          return this.request(method, request, tryCount + 1);\n        }\n      }\n    } catch (error) {\n      if (this.options.enableDebugLogging) {\n        console.error(`[Metorial] ${method} ${url.toString()}`, error);\n      }\n      throw new MetorialSDKError({\n        status: 0,\n        code: 'network_error',\n        message: 'Unable to connect to Metorial API - please check your internet connection'\n      });\n    }\n\n    let data: any;\n    try {\n      data = await response.json();\n    } catch (error) {\n      if (this.options.enableDebugLogging) {\n        console.error(`[Metorial] ${method} ${url.toString()}`, error);\n      }\n      throw new MetorialSDKError({\n        status: response.status,\n        code: 'malformed_response',\n        message: 'The Metorial API returned an unexpected response. Expected JSON.'\n      });\n    }\n\n    if (!response.ok) {\n      if (this.options.enableDebugLogging) {\n        console.error(`[Metorial] ${method} ${url.toString()}`, data);\n      }\n      throw new MetorialSDKError(data);\n    }\n\n    if (this.options.enableDebugLogging) {\n      console.log(`[Metorial] ${method} ${url.toString()}`, data);\n    }\n\n    return data;\n  }\n\n  private requestAndTransform(method: Method, request: MetorialRequest) {\n    return {\n      transform: async <T>(mapper: { transformFrom: (input: any) => T }): Promise<T> => {\n        let data = await this.request(method, request);\n        return mapper.transformFrom(data);\n      }\n    };\n  }\n\n  _get(request: MetorialRequest) {\n    return this.requestAndTransform('GET', request);\n  }\n\n  _post(request: MetorialRequest) {\n    return this.requestAndTransform('POST', request);\n  }\n\n  _put(request: MetorialRequest) {\n    return this.requestAndTransform('PUT', request);\n  }\n\n  _patch(request: MetorialRequest) {\n    return this.requestAndTransform('PATCH', request);\n  }\n\n  _delete(request: MetorialRequest) {\n    return this.requestAndTransform('DELETE', request);\n  }\n}\n\nexport abstract class BaseMetorialEndpoint<Config> {\n  constructor(protected readonly manager: MetorialEndpointManager<Config>) {}\n\n  protected _get(request: MetorialRequest) {\n    return this.manager._get(request);\n  }\n\n  protected _post(request: MetorialRequest) {\n    return this.manager._post(request);\n  }\n\n  protected _put(request: MetorialRequest) {\n    return this.manager._put(request);\n  }\n\n  protected _patch(request: MetorialRequest) {\n    return this.manager._patch(request);\n  }\n\n  protected _delete(request: MetorialRequest) {\n    return this.manager._delete(request);\n  }\n}\n","// export class MetorialError extends Error {\n//   __typename: 'metorial.error' | 'metorial.sdk.error' = 'metorial.error';\n//   __isMetorialError = true;\n\n//   constructor(message: string) {\n//     super(`[METORIAL ERROR]: ${message}`);\n//   }\n\n//   static isMetorialError(error: any): error is MetorialError {\n//     return error?.__isMetorialError;\n//   }\n// }\n\nconst METORIAL_SDK_ERROR = 'metorial.sdk.error' as const;\n\nexport class MetorialSDKError extends Error {\n  __typename = METORIAL_SDK_ERROR;\n  __isMetorialError = true;\n\n  constructor(\n    public readonly response: {\n      status: number;\n      code: string;\n      message: string;\n      hint?: string;\n      description?: string;\n      entity?: string;\n      reason?: string;\n      errors?: {\n        code: string;\n        message: string;\n        expected?: any;\n        received?: any;\n        path?: string[];\n        min?: number;\n        max?: number;\n        positive?: boolean;\n        negative?: boolean;\n      }[];\n      [key: string]: any;\n    }\n  ) {\n    // console.log(`[METORIAL ERROR]: ${response.code} - ${response.message}`);\n    // console.error('Response:');\n    // console.error(JSON.stringify(response, null, 2));\n\n    super(`[METORIAL ERROR]: ${response.code} - ${response.message}`);\n  }\n\n  get code() {\n    return this.response.code;\n  }\n\n  get message() {\n    return this.response.message;\n  }\n\n  get hint() {\n    return this.response.hint;\n  }\n\n  get description() {\n    return this.response.description;\n  }\n\n  get reason() {\n    return this.response.reason;\n  }\n\n  get validationErrors() {\n    return this.response.errors;\n  }\n\n  get entity() {\n    return this.response.entity;\n  }\n}\n\nexport let isMetorialSDKError = (error: any): error is MetorialSDKError => {\n  return (\n    error?.__typename === METORIAL_SDK_ERROR ||\n    error.__isMetorialError ||\n    error instanceof MetorialSDKError\n  );\n};\n","import { MetorialEndpointManager } from './endpoints';\n\nexport class MetorialSDKBuilder<\n  ApiVersion,\n  Config extends {\n    apiKey?: string;\n    apiVersion: ApiVersion;\n    fetch?: typeof fetch;\n  }\n> {\n  #getApiHost?: (config: Config) => string;\n  #getHeaders?: (config: Config) => Record<string, string>;\n\n  private constructor(\n    private apiName: string,\n    private apiVersion: ApiVersion\n  ) {}\n\n  static create<ApiVersion, Config extends { apiVersion: ApiVersion; apiKey?: string }>(\n    apiName: string,\n    apiVersion: ApiVersion\n  ): MetorialSDKBuilder<ApiVersion, Config> {\n    return new MetorialSDKBuilder(apiName, apiVersion);\n  }\n\n  setGetApiHost(getApiHost: (config: Config) => string) {\n    this.#getApiHost = getApiHost;\n    return this;\n  }\n\n  setGetHeaders(getHeaders: (config: Config) => Record<string, string>) {\n    this.#getHeaders = getHeaders;\n    return this;\n  }\n\n  build<SoftConfig extends Partial<Config>>(getConfig: (config: SoftConfig) => Config) {\n    if (!this.#getHeaders) {\n      throw new Error('getHeaders must be set');\n    }\n\n    if (!this.#getApiHost) {\n      throw new Error('apiHost must be set');\n    }\n\n    return <E extends { [key: string]: any }>(\n        getEndpoints: (manager: MetorialEndpointManager<Config>) => E\n      ) =>\n      (\n        config: SoftConfig & {\n          enableDebugLogging?: boolean;\n        }\n      ): E & {\n        _config: Config & {\n          apiHost: string;\n        };\n      } => {\n        let fullConfig = getConfig(config);\n        let apiHost = this.#getApiHost!(fullConfig);\n\n        let manager = new MetorialEndpointManager(\n          fullConfig,\n          apiHost,\n          this.#getHeaders!,\n          fullConfig.fetch,\n          { enableDebugLogging: !!(fullConfig as any).enableDebugLogging }\n        );\n\n        return {\n          _config: {\n            apiHost,\n            ...fullConfig\n          },\n\n          ...getEndpoints(manager)\n        } as any;\n      };\n  }\n}\n\nexport type GetMetorialSDKConfig<Builder extends MetorialSDKBuilder<any, any>> =\n  Builder extends MetorialSDKBuilder<infer ApiVersion, infer Config> ? Config : never;\n"],"mappings":"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","names":["qs"]}