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