{"version":3,"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n  \"name\": \"geckoboard\",\n  \"version\": \"2.0.2\",\n  \"description\": \"\",\n  \"main\": \"dist/index.js\",\n  \"scripts\": {\n    \"build\": \"tsup\",\n    \"test\": \"jest\",\n    \"lint\": \"eslint src --ext .ts\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/geckoboard/geckoboard-node.git\"\n  },\n  \"keywords\": [\n    \"geckoboard\",\n    \"node\",\n    \"javascript\"\n  ],\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/geckoboard/geckoboard-node/issues\"\n  },\n  \"homepage\": \"https://developer.geckoboard.com/\",\n  \"devDependencies\": {\n    \"@types/jest\": \"^29.5.8\",\n    \"@typescript-eslint/eslint-plugin\": \"^6.10.0\",\n    \"@typescript-eslint/parser\": \"^6.10.0\",\n    \"eslint\": \"^8.53.0\",\n    \"eslint-config-prettier\": \"^9.0.0\",\n    \"eslint-plugin-prettier\": \"^5.0.1\",\n    \"jest\": \"^29.7.0\",\n    \"prettier\": \"3.1.0\",\n    \"ts-jest\": \"^29.1.1\",\n    \"ts-node\": \"^10.9.1\",\n    \"tsup\": \"^7.2.0\",\n    \"typescript\": \"^5.2.2\"\n  },\n  \"dependencies\": {\n    \"undici\": \"^6.24.0\"\n  }\n}\n","import { version } from '../package.json';\nimport { fetch, Response } from 'undici';\n\nconst USER_AGENT = `Geckoboard Node Client ${version}`;\n\ntype ErrorResponse = {\n  error?: {\n    message?: string;\n  };\n};\n\ntype HTTP_METHOD = 'GET' | 'PUT' | 'POST' | 'DELETE';\n\ntype MandatoryField = {\n  name: string;\n  optional?: false;\n};\ntype OptionalField = {\n  name: string;\n  optional: true;\n};\ntype Field = MandatoryField | OptionalField;\n\ntype DateField = {\n  type: 'date';\n} & Field;\n\ntype DateTimeField = {\n  type: 'datetime';\n} & Field;\n\ntype DurationField = {\n  type: 'duration';\n  time_unit: 'milliseconds' | 'seconds' | 'minutes' | 'hours';\n} & Field;\n\ntype CurrencyCode =\n  | 'AED'\n  | 'AFN'\n  | 'ALL'\n  | 'AMD'\n  | 'ANG'\n  | 'AOA'\n  | 'ARS'\n  | 'AUD'\n  | 'AWG'\n  | 'AZN'\n  | 'BAM'\n  | 'BBD'\n  | 'BDT'\n  | 'BGN'\n  | 'BHD'\n  | 'BIF'\n  | 'BMD'\n  | 'BND'\n  | 'BOB'\n  | 'BOV'\n  | 'BRL'\n  | 'BSD'\n  | 'BTN'\n  | 'BWP'\n  | 'BYN'\n  | 'BZD'\n  | 'CAD'\n  | 'CDF'\n  | 'CHE'\n  | 'CHF'\n  | 'CHW'\n  | 'CLF'\n  | 'CLP'\n  | 'COP'\n  | 'COU'\n  | 'CRC'\n  | 'CUP'\n  | 'CVE'\n  | 'CZK'\n  | 'DJF'\n  | 'DKK'\n  | 'DOP'\n  | 'DZD'\n  | 'EGP'\n  | 'ERN'\n  | 'ETB'\n  | 'EUR'\n  | 'FJD'\n  | 'FKP'\n  | 'GBP'\n  | 'GEL'\n  | 'GHS'\n  | 'GIP'\n  | 'GMD'\n  | 'GNF'\n  | 'GTQ'\n  | 'GYD'\n  | 'HKD'\n  | 'HNL'\n  | 'HTG'\n  | 'HUF'\n  | 'IDR'\n  | 'ILS'\n  | 'INR'\n  | 'IQD'\n  | 'IRR'\n  | 'ISK'\n  | 'JMD'\n  | 'JOD'\n  | 'JPY'\n  | 'KES'\n  | 'KGS'\n  | 'KHR'\n  | 'KMF'\n  | 'KPW'\n  | 'KRW'\n  | 'KWD'\n  | 'KYD'\n  | 'KZT'\n  | 'LAK'\n  | 'LBP'\n  | 'LKR'\n  | 'LRD'\n  | 'LSL'\n  | 'LYD'\n  | 'MAD'\n  | 'MDL'\n  | 'MGA'\n  | 'MKD'\n  | 'MMK'\n  | 'MNT'\n  | 'MOP'\n  | 'MRU'\n  | 'MUR'\n  | 'MVR'\n  | 'MWK'\n  | 'MXN'\n  | 'MXV'\n  | 'MYR'\n  | 'MZN'\n  | 'NAD'\n  | 'NGN'\n  | 'NIO'\n  | 'NOK'\n  | 'NPR'\n  | 'NZD'\n  | 'OMR'\n  | 'PAB'\n  | 'PEN'\n  | 'PGK'\n  | 'PHP'\n  | 'PKR'\n  | 'PLN'\n  | 'PYG'\n  | 'QAR'\n  | 'RON'\n  | 'RSD'\n  | 'CNY'\n  | 'RUB'\n  | 'RWF'\n  | 'SAR'\n  | 'SBD'\n  | 'SCR'\n  | 'SDG'\n  | 'SEK'\n  | 'SGD'\n  | 'SHP'\n  | 'SLE'\n  | 'SLL'\n  | 'SOS'\n  | 'SRD'\n  | 'SSP'\n  | 'STN'\n  | 'SVC'\n  | 'SYP'\n  | 'SZL'\n  | 'THB'\n  | 'TJS'\n  | 'TMT'\n  | 'TND'\n  | 'TOP'\n  | 'TRY'\n  | 'TTD'\n  | 'TWD'\n  | 'TZS'\n  | 'UAH'\n  | 'UGX'\n  | 'USD'\n  | 'USN'\n  | 'UYI'\n  | 'UYU'\n  | 'UYW'\n  | 'UZS'\n  | 'VED'\n  | 'VES'\n  | 'VND'\n  | 'VUV'\n  | 'WST'\n  | 'XAF'\n  | 'XAG'\n  | 'XAU'\n  | 'XBA'\n  | 'XBB'\n  | 'XBC'\n  | 'XBD'\n  | 'XCD'\n  | 'XDR'\n  | 'XOF'\n  | 'XPD'\n  | 'XPF'\n  | 'XPT'\n  | 'XSU'\n  | 'XTS'\n  | 'XUA'\n  | 'XXX'\n  | 'YER'\n  | 'ZAR'\n  | 'ZMW'\n  | 'ZWL';\ntype MoneyField = {\n  type: 'money';\n  currency_code: CurrencyCode;\n} & Field;\n\ntype NumberField = {\n  type: 'number';\n} & Field;\n\ntype PercentageField = {\n  type: 'percentage';\n} & Field;\n\ntype StringField = {\n  type: 'string';\n} & Field;\n\ntype Fields = Record<\n  string,\n  | DateField\n  | DateTimeField\n  | DurationField\n  | MoneyField\n  | NumberField\n  | PercentageField\n  | StringField\n>;\n\ntype KeysMatching<T, V> = {\n  [K in keyof T]-?: T[K] extends V ? K : never;\n}[keyof T];\n\ntype Schema<T extends Fields> = {\n  id: string;\n  fields: T;\n  uniqueBy: Array<KeysMatching<T, StringField | DateField | DateTimeField>>;\n};\n\ntype FieldType<T> = T extends DateField | DateTimeField\n  ? string | Date\n  : T extends StringField\n    ? string\n    : T extends DurationField | MoneyField | NumberField | PercentageField\n      ? number\n      : never;\n\ntype IsOptional<\n  K extends keyof F,\n  F extends Fields,\n> = F[K] extends OptionalField ? K : never;\ntype IsRequired<\n  K extends keyof F,\n  F extends Fields,\n> = F[K] extends OptionalField ? never : K;\n\ntype DatasetDataItem<F extends Fields> = {\n  [K in keyof F as IsRequired<K, F>]: FieldType<F[K]>;\n} & {\n  [K in keyof F as IsOptional<K, F>]?: FieldType<F[K]>;\n};\n\nclass Dataset<T extends Fields> {\n  id: string;\n  fields: T;\n  uniqueBy: Array<KeysMatching<T, StringField | DateField | DateTimeField>>;\n\n  gb: Geckoboard;\n\n  constructor(schema: Schema<T>, gb: Geckoboard) {\n    this.id = schema.id;\n    this.fields = schema.fields;\n    this.uniqueBy = schema.uniqueBy;\n\n    this.gb = gb;\n  }\n\n  async create(): Promise<void> {\n    const { id, fields, uniqueBy } = this;\n    await this.gb.request('PUT', `/datasets/${id}`, {\n      fields,\n      unique_by: uniqueBy,\n    });\n  }\n\n  replaceDateObjects(items: DatasetDataItem<T>[]): DatasetDataItem<T>[] {\n    const dateFields: Array<keyof T> = [];\n    const dateTimeFields: Array<keyof T> = [];\n\n    const keys = Object.keys(this.fields);\n    keys.forEach((fieldName) => {\n      const field = this.fields[fieldName];\n      if (field.type === 'date') {\n        dateFields.push(fieldName);\n      }\n      if (field.type === 'datetime') {\n        dateTimeFields.push(fieldName);\n      }\n    });\n    return items.map((item) => {\n      dateFields.forEach((fieldName) => {\n        const fieldValue = item[fieldName as keyof DatasetDataItem<T>];\n        if (fieldValue instanceof Date) {\n          item = {\n            ...item,\n            [fieldName]: fieldValue.toISOString().split('T')[0],\n          };\n        }\n      });\n      dateTimeFields.forEach((fieldName) => {\n        const fieldValue = item[fieldName as keyof DatasetDataItem<T>];\n        if (fieldValue instanceof Date) {\n          item = {\n            ...item,\n            [fieldName]: fieldValue.toISOString(),\n          };\n        }\n      });\n\n      return item;\n    });\n  }\n  async append(items: DatasetDataItem<T>[], deleteBy?: keyof T): Promise<void> {\n    const { id } = this;\n    const data = this.replaceDateObjects(items);\n    await this.gb.request('POST', `/datasets/${id}/data`, {\n      data,\n      deleteBy,\n    });\n  }\n\n  async replace(items: DatasetDataItem<T>[]): Promise<void> {\n    const { id } = this;\n    const data = this.replaceDateObjects(items);\n    await this.gb.request('PUT', `/datasets/${id}/data`, {\n      data,\n    });\n  }\n\n  async delete(): Promise<void> {\n    const { id } = this;\n    await this.gb.request('DELETE', `/datasets/${id}`);\n  }\n}\n\nexport class Geckoboard {\n  apiKey: string;\n  apiHost: string;\n  version: string;\n\n  constructor(apiKey: string) {\n    this.apiKey = apiKey;\n    this.apiHost =\n      process.env.GECKOBOARD_API_HOST || 'https://api.geckoboard.com';\n    this.version = version;\n  }\n\n  async request(\n    method: HTTP_METHOD,\n    path: string,\n    body?: object,\n  ): Promise<Response> {\n    const auth = btoa(`${this.apiKey}:`);\n    const headers = new Headers({\n      Authorization: `Basic ${auth}`,\n      'User-Agent': USER_AGENT,\n    });\n    if (method === 'POST' || method === 'PUT') {\n      headers.set('Content-Type', 'application/json');\n    }\n    const res = await fetch(new URL(path, this.apiHost), {\n      body: JSON.stringify(body),\n      method: method,\n      headers,\n    });\n    if (!res.ok) {\n      const json = (await res.json()) as ErrorResponse;\n      const message =\n        json.error?.message || 'Something went wrong with the request';\n      throw new Error(message);\n    }\n    return res;\n  }\n\n  defineDataset<T extends Fields>(schema: Schema<T>): Dataset<T> {\n    return new Dataset(schema, this);\n  }\n\n  async ping(): Promise<void> {\n    await this.request('GET', '/');\n  }\n}\n"],"mappings":"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","names":[]}