All files / src/generate client.ts

33.33% Statements 6/18
0% Branches 0/13
0% Functions 0/7
37.5% Lines 6/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77  1x     1x 1x       1x     1x                                                                                                                             1x  
import { OutputSuccess } from '../transform/types.js'
import { typeDef, name } from './common.js'
import { Validation } from 'yaschva'
 
const getTokenDefaultPath = '../getToken'
const containsOptional = (input: Validation) =>
  (Array.isArray(input) && input.some(y => y === '?')) ||
   input === '?'
 
const allOptional = (input: Validation) =>
  Object.values(input).every(containsOptional)
 
export const client = (input: OutputSuccess[], getTokenPath?:string): string => {
  const functions = input.map(x => {
    const url =
      x.method === 'GET' ? `\`/api/${x.name}?\${serialize(input || {})}\`` : `"/api/${x.name}"`
    const fn = `
    const valid = validate(contracts.${name(x)}.arguments, input);
      if (valid.result === "fail") throw valid;
    return fetch(${url}, {
      method: "${x.method}",
      headers: await defaultHeader(),
      body: ${x.method === 'GET' ? 'undefined' : 'JSON.stringify(input)'},
      signal
    }).then(x=> x.json())
    .then(x=> {
      if(x.errorType){throw x}
      const r = validate(contracts.${name(x)}.returns, x);
      if(r.result ==="fail") throw r; return x})\n`
 
    return `export const ${name(x)} =
      async (input: ${name(x)}Argument${allOptional(x.arguments) ? ' = {}' : ''},
        signal: AbortSignal | undefined = undefined):
       Promise<${name(x)}Returns> => {\n${fn}};\n`
  }).join('\n')
 
  const contractDescription = input.map(x => `${name(x)}: {
    name: "${x.name}",
    authentication: ${JSON.stringify(x.authentication, undefined, 2)},
    type: "${x.method}",
    arguments: ${JSON.stringify(x.arguments)},
    returns: ${JSON.stringify(x.returns)}}`).join(',')
 
  const fileContent = `/* eslint-disable max-lines */
/**********************************************
  DO NOT EDIT THIS FILE, IT WILL BE OVERRIDDEN
***********************************************/
 
  import { validate, Validation } from "yaschva";
  import { deepFreeze, serialize } from "microtil";
  import getToken from "${getTokenPath ?? getTokenDefaultPath}"
  const defaultHeader = async () => {
    const token = await getToken();
    const headers =  {
      'Authorization': \`Bearer \${token}\`,
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    }
 
    if(!token) delete headers.Authorization
    return headers;
  };
 
    export const contracts: {[key:string]:{
      name:string, type:string, authentication:any,
      arguments: Validation, returns:Validation}} =
        deepFreeze({${contractDescription}});
 
    ${typeDef(input)}
    ${functions}
    export const functions = {${input.map(x => `${name(x)}: ${name(x)}`)}}
  `
  return fileContent
}
 
export default client