UNPKG

@docyrus/tanstack-db-generator

Version:

Code generator utilities for TanStack Query / Database integration with Docyrus API

204 lines (201 loc) 8.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateCollections = generateCollections; const list_parameter_definitions_1 = require("../list-parameter-definitions"); const fs_1 = require("fs"); const path_1 = require("path"); const typegen_1 = require("../utils/typegen"); async function generateCollections(spec, dataSources, outputDir) { // Generate individual collection files for (const dataSource of dataSources) { const collectionContent = generateCollectionFile(spec, dataSource); const fileName = `${dataSource.appName}-${dataSource.dataSourceName}.collection.ts`; (0, fs_1.writeFileSync)((0, path_1.join)(outputDir, fileName), collectionContent); } // Generate index file const indexContent = generateCollectionsIndex(dataSources); (0, fs_1.writeFileSync)((0, path_1.join)(outputDir, 'index.ts'), indexContent); } function generateCollectionFile(spec, dataSource) { const { appName, dataSourceName, entityName, endpoints } = dataSource; const collectionName = `${appName}${toPascalCase(dataSourceName)}Collection`; const methods = []; if (endpoints.list) { methods.push(generateListMethod(spec, endpoints.list, entityName)); } if (endpoints.get) { methods.push(generateGetMethod(spec, endpoints.get, entityName)); } if (endpoints.create) { methods.push(generateCreateMethod(spec, endpoints.create, entityName)); } if (endpoints.update) { methods.push(generateUpdateMethod(spec, endpoints.update, entityName)); } if (endpoints.delete) { methods.push(generateDeleteMethod(spec, endpoints.delete)); } if (endpoints.deleteMany) { methods.push(generateDeleteManyMethod(spec, endpoints.deleteMany)); } const inlineTypes = (0, typegen_1.generateInterfacesForNames)(spec, [entityName]); return `// Generated collection for ${appName}/${dataSourceName} import { apiClient } from '../lib/api'; ${inlineTypes ? inlineTypes + '\n' : ''} export const ${collectionName} = { ${methods.join(',\n\n')} }; `; } function generateListMethod(spec, endpoint, entityName) { const jsDoc = buildDsListJsDoc(); const paramsType = buildListParamsType(); const url = endpoint.path; return ` ${jsDoc}list: (params?: ${paramsType}): Promise<Array<${entityName}>> => { const { ['x-connection-id']: xConnectionId, ['x-connection-account-id']: xConnectionAccountId, ...query } = params || {} as any; return apiClient.get('${url}', query); }`; } function generateGetMethod(spec, endpoint, entityName) { const jsDoc = buildDsJsDoc(spec, endpoint, entityName); return ` ${jsDoc}get: (recordId: string, params?: { columns?: Array<string> }): Promise<${entityName}> => apiClient.get('${endpoint.path}'.replace('{recordId}', recordId), params)`; } function generateCreateMethod(spec, endpoint, entityName) { const jsDoc = buildDsJsDoc(spec, endpoint, entityName); return ` ${jsDoc}create: (data: { data: any }): Promise<${entityName}> => apiClient.post('${endpoint.path}', data)`; } function generateUpdateMethod(spec, endpoint, entityName) { const jsDoc = buildDsJsDoc(spec, endpoint, entityName); return ` ${jsDoc}update: (recordId: string, data: { data: any }): Promise<${entityName}> => apiClient.patch('${endpoint.path}'.replace('{recordId}', recordId), data)`; } function generateDeleteMethod(spec, endpoint) { const jsDoc = buildDsJsDoc(spec, endpoint, 'void'); return ` ${jsDoc}delete: (recordId: string): Promise<void> => apiClient.delete('${endpoint.path}'.replace('{recordId}', recordId))`; } function generateDeleteManyMethod(spec, endpoint) { const jsDoc = buildDsJsDoc(spec, endpoint, 'void'); return ` ${jsDoc}deleteMany: (data: { recordIds: Array<string> }): Promise<void> => apiClient.delete('${endpoint.path}', data)`; } function generateCollectionsIndex(dataSources) { const exports = dataSources.map(ds => { const collectionName = `${ds.appName}${toPascalCase(ds.dataSourceName)}Collection`; const fileName = `${ds.appName}-${ds.dataSourceName}.collection`; return `export { ${collectionName} } from './${fileName}';`; }); return `// Generated collections index ${exports.join('\n')} `; } function toPascalCase(str) { return str.split(/[_-]/) .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) .join(''); } function buildDsJsDoc(spec, endpoint, entityName, container) { const lines = []; if (endpoint.summary) lines.push(sanitizeJsDoc(endpoint.summary)); if (endpoint.description && endpoint.description !== endpoint.summary) lines.push(sanitizeJsDoc(endpoint.description)); // Param docs (only for the subset our signatures accept) const paramObjs = (endpoint.parameters || []).map((p) => resolveParameter(p, spec)).filter(Boolean); const byName = new Map(paramObjs.map(p => [p.name, p])); const docParam = (name, label) => { const p = byName.get(name); if (p?.description) lines.push(`@param ${label || name} - ${sanitizeJsDoc(p.description)}`); }; // For list docParam('limit', 'params.limit'); docParam('offset', 'params.offset'); docParam('columns', 'params.columns'); docParam('filters', 'params.filters'); // For record id docParam('recordId', 'recordId'); // For request body if (endpoint.requestBody) lines.push(`@param data - Request body`); // Return type if (entityName) { if (entityName === 'void') lines.push(`@returns void`); else if (container === 'Array') lines.push(`@returns Array<${entityName}>`); else lines.push(`@returns ${entityName}`); } if (lines.length === 0) return ''; return `/**\n * ${lines.join('\n * ')}\n */\n `; } function resolveParameter(p, spec) { if (p && p.$ref) { const ref = p.$ref; const path = ref.replace('#/', '').split('/'); let current = spec; for (const seg of path) current = current?.[seg]; return current || null; } return p; } function sanitizeJsDoc(text) { return String(text).replace(/\*\//g, '*\/').trim(); } function buildListParamsType() { const p = list_parameter_definitions_1.listParameterDefinitions; // Build a flat object type for query + header params used in list endpoints. const fields = []; const add = (name, type) => fields.push(`${JSON.stringify(name)}?: ${type}`); // Query parameters add('columns', 'Array<string>'); add('distinctColumns', 'Array<string>'); add('rows', 'Array<string>'); add('formulas', 'string'); add('calculations', 'Array<any>'); add('filters', 'any'); add('filterKeyword', 'string'); add('orderBy', 'string'); add('limit', 'number'); add('offset', 'number'); add('fullCount', 'boolean'); add('expand', 'string'); // Header parameters: keep original header names add('x-connection-id', 'string'); add('x-connection-account-id', 'string'); return `{ ${fields.join('; ')} }`; } function buildDsListJsDoc() { const p = list_parameter_definitions_1.listParameterDefinitions; const lines = []; lines.push('List data source records based on specified columns, filters, and other configuration options'); const addParam = (key, label) => { const def = p[key]; if (!def) return; const name = label || def.name; const desc = def.description ? ` - ${sanitizeJsDoc(def.description)}` : ''; lines.push(`@param params.${name}${desc}`.trim()); }; addParam('Columns'); addParam('DistinctColumns'); addParam('Rows'); addParam('Formulas'); addParam('Calculations'); addParam('Filters'); addParam('FilterKeyword'); addParam('OrderBy'); addParam('Limit'); addParam('Offset'); addParam('FullCount'); addParam('Expand'); // Headers addParam('XConnectionId', 'x-connection-id'); addParam('XConnectionAccountId', 'x-connection-account-id'); return `/**\n * ${lines.join('\n * ')}\n */\n `; }