const changeCase = require('change-case'); // flatMap: https://gist.github.com/samgiles/762ee337dff48623e729 // [B](f: (A) ⇒ [B]): [B] ; Although the types in the arrays aren't strict (: Array.prototype.flatMap = function(lambda) { return Array.prototype.concat.apply([], this.map(lambda)); }; Array.prototype.groupBy = function(lambda) { return Object.entries(this.reduce((agg, x) => { const k = lambda(x); (agg[k] = agg[k] || []).push(x); return agg; }, {})); }; Array.prototype.sortBy = function(lambda) { return this.sort((a, b) => { const va = lambda(a); const vb = lambda(b); if ((typeof va) !== (typeof vb)) throw Error(`Mismatched sort types: ${typeof va}, ${typeof vb}.`); if (typeof va === 'number') return va - vb; if (typeof va === 'string') return va.localeCompare(vb); throw Error(`Unknown sort type: ${typeof va}.`); }); }; function preamble() { return `\ #![cfg_attr(any(), rustfmt::skip)] /////////////////////////////////////////////// // // // ! // // This file is automatically generated! // // Do not directly edit! // // // ///////////////////////////////////////////////`; } function capitalize(input) { return input[0].toUpperCase() + input.slice(1); } function decapitalize(input) { return input[0].toLowerCase() + input.slice(1); } function normalizeSchemaName(name) { return name.replace(/DTO/ig, ''); } function normalizeArgName(name) { const tokens = name.split('_'); const argName = decapitalize(tokens.map(capitalize).join('')); return 'base' === argName ? 'Base' : argName; } function normalizePropName(propName) { let out = changeCase.snakeCase(propName); if (/^\d/.test(out)) // No leading digits. out = 'x' + out; if ('type' === out) return 'r#' + out; return out; } function stringifyType(prop, { endpoint = null, optional = false, fullpath = true, owned = true }) { if (prop.anyOf) { prop = prop.anyOf[0]; } if (optional) { return `Option<${stringifyType(prop, { endpoint, fullpath, owned })}>`; } let enumType = prop['x-enum']; if (enumType && 'locale' !== enumType) return 'crate::consts::' + changeCase.pascalCase(enumType); let refType = prop['$ref']; if (refType) { return (!endpoint ? '' : changeCase.snakeCase(endpoint) + '::') + normalizeSchemaName(refType.slice(refType.indexOf('.') + 1)); } switch (prop.type) { case 'boolean': return 'bool'; case 'integer': return ('int32' === prop.format ? 'i32' : 'i64'); case 'number': return ('float' === prop.format ? 'f32' : 'f64'); case 'array': const subprop = stringifyType(prop.items, { endpoint, optional, fullpath, owned }); return (owned ? (fullpath ? 'std::vec::' : '') + `Vec<${subprop}>` : `&[${subprop}]`); case 'string': return (owned ? 'String' : '&str'); case 'object': if (1 === Object.keys(prop).length) { // Only `{ "type": "object" }`. return 'serde_json::Map' } return 'std::collections::HashMap<' + stringifyType(prop['x-key'], { endpoint, optional, fullpath, owned }) + ', ' + stringifyType(prop.additionalProperties, { endpoint, optional, fullpath, owned }) + '>'; default: return prop.type; } } function formatJsonProperty(name, prop) { const alias = prop['x-alias']; if (alias) return `#[serde(rename = ${JSON.stringify(name)}, alias = ${JSON.stringify(alias)})]`; else return `#[serde(rename = ${JSON.stringify(name)})]`; } function formatAddQueryParam(param) { const k = `"${param.name}"`; const name = normalizePropName(param.name); const condStart = param.required ? '' : `if let Some(${name}) = ${name} { `; const condEnd = param.required ? '' : ' } else { request }' const prop = param.schema; switch (prop.type) { case 'array': return `let request = ${condStart}request.query(&*${name}.iter()` + `.map(|w| ( ${k}, w )).collect::>())${condEnd};`; case 'object': throw 'unsupported'; default: return `let request = ${condStart}request.query(&[ (${k}, ${name}) ])${condEnd};`; } } function formatAddHeaderParam(param) { const k = `"${param.name}"`; const name = changeCase.snakeCase(param.name); const condStart = param.required ? '' : `mut request = request; if let Some(${name}) = ${name} { `; const condEnd = param.required ? '' : ' }' const prop = param.schema; switch (prop.type) { case 'string': return `let ${condStart}request = request.header(${k}, ${name});${condEnd}`; case 'object': throw 'unsupported'; default: return `let ${condStart}request = request.header(${k}, ${name}.to_string());${condEnd}`; } } function formatRouteArgument(route, pathParams = []) { if (!pathParams.length) return `"${route}"`; route = route.replace(/\{\S+?\}/g, '{}'); const args = pathParams .map(({name}) => name) .map(changeCase.snakeCase) .join(', '); return `&format!("${route}", ${args})`; } module.exports = { changeCase, preamble, capitalize, decapitalize, normalizeSchemaName, normalizeArgName, normalizePropName, stringifyType, formatJsonProperty, formatAddQueryParam, formatAddHeaderParam, formatRouteArgument, };