UNPKG

kdx

Version:

kintone CLI for development & deployment, with Developer Experience

220 lines (200 loc) 7.6 kB
// Copyright (c) 2020 Shellyl_N and Authors // license: MIT // https://github.com/shellyln import { promisify } from 'util'; import * as fs from 'fs'; import * as path from 'path'; import { escapeString } from './index'; const readFile = promisify(fs.readFile); const getRawFields = (interfaceComment: string, interfaceName: string, fields: object, nestLv: number) => { let code = ''; let subTableCode = ''; const indent = ''.padEnd((nestLv + 1) * 4); const indent2 = ''.padEnd((nestLv + 2) * 4); const keys = Object.keys(fields); OUTER: for (const k of keys) { let isArray = false; let typeName = 'any'; let decorators = ''; const field = fields[k]; switch (field.type) { case 'STATUS': typeName = 'string'; break; case 'CATEGORY': typeName = 'string'; break; case 'NUMBER': decorators += `@match(/^[+-]?(?:[1-9][0-9]*|0)(?:\\.[0-9]+)?(?:[Ee][+-]?[0-9]+)?$/)`; typeName = 'string'; break; case 'SINGLE_LINE_TEXT': typeName = 'string'; break; case 'MULTI_LINE_TEXT': typeName = 'string'; break; case 'RICH_TEXT': typeName = 'string'; break; case 'LINK': typeName = 'string'; break; case 'DATE': decorators += `@stereotype('lcdate')`; typeName = 'string'; break; case 'DATETIME': decorators += `@stereotype('lcdatetime')`; typeName = 'string'; break; case 'TIME': decorators += `@match(/^[0-2]\\d:[0-5]\\d$/)`; typeName = 'string'; break; case 'RADIO_BUTTON': case 'DROP_DOWN': typeName = Object.keys(field.options) .map(x => `'${escapeString(x)}'`).join(' | '); break; case 'CHECK_BOX': case 'MULTI_SELECT': isArray = true; typeName = `(${Object.keys(field.options) .map(x => `'${escapeString(x)}'`).join(' | ')})[${field.required ? ', 1..' : ''}]`; break; case 'USER_SELECT': isArray = true; typeName = `Array<{code: string, name: string}${field.required ? ', 1..' : ''}>`; break; case 'GROUP_SELECT': isArray = true; typeName = `Array<{code: string, name: string}${field.required ? ', 1..' : ''}>`; break; case 'ORGANIZATION_SELECT': isArray = true; typeName = `Array<{code: string, name: string}${field.required ? ', 1..' : ''}>`; break; case 'SUBTABLE': { isArray = true; typeName = field.code[0].toUpperCase() + field.code.slice(1); const sub = getRawFields(field.label, typeName, field.fields, nestLv); subTableCode += sub.subTableCode + sub.code; typeName = `${typeName}[${field.required ? ', 1..' : ''}]`; } break; case 'CALC': typeName = 'string'; break; case 'FILE': isArray = true; typeName = `Array<{contentType: string, fileKey: string, name: string, size: string}>`; break; case 'STATUS_ASSIGNEE': isArray = true; typeName = `Array<{code: string, name: string}>`; break; // system fields case 'RECORD_NUMBER': typeName = 'string'; break; case 'CREATED_TIME': decorators += `@stereotype('lcdatetime')`; typeName = 'string'; break; case 'CREATOR': typeName = `{code: string, name: string}`; break; case 'UPDATED_TIME': decorators += `@stereotype('lcdatetime')`; typeName = 'string'; break; case 'MODIFIER': typeName = `{code: string, name: string}`; break; case '__ID__': typeName = 'string'; break; case '__REVISION__': typeName = 'string'; break; // UI elements (no record fields) case 'REFERENCE_TABLE': case 'GROUP': default: continue OUTER; } if (field.maxValue) { let v = ''; if (field.type === 'NUMBER') { v = field.maxValue; } else { v = `'${escapeString(field.maxValue)}'`; } decorators += `${decorators ? ' ' : ''}@maxValue(${v})`; } if (field.minValue) { let v = ''; if (field.type === 'NUMBER') { v = field.minValue; } else { v = `'${escapeString(field.minValue)}'`; } decorators += `${decorators ? ' ' : ''}@minValue(${v})`; } if (field.maxLength) { let v = ''; v = field.maxLength; decorators += `${decorators ? ' ' : ''}@maxLength(${v})`; } if (field.minLength) { let v = ''; v = field.minLength; decorators += `${decorators ? ' ' : ''}@minLength(${v})`; } code += `${code ? '\n' : ''}${ indent}/** ${field.label} */\n${indent}@meta({fieldType:'${escapeString(field.type)}'})\n${ indent}${/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(field.code) ? field.code : `'${escapeString(field.code)}'`}${ (isArray || field.required) ? '' : '?'}: {\n${ indent2}type: '${escapeString(field.type)}';\n${ indent2}${decorators ? decorators + '\n' + indent2 : ''}value: ${typeName};\n${ field.type === 'SINGLE_LINE_TEXT' || field.type === 'NUMBER' ? `${indent2}lookup?: boolean | 'UPDATE';\n` : ''}${ indent2}error?: string;\n${ indent2}disabled?: boolean;\n${ indent}};\n`; } code = `\n\n${interfaceComment ? `/** ${interfaceComment} */\n` : ''}export interface ${interfaceName} {\n${code}}\n\n`; return ({subTableCode, code}); }; const appendSystemFields = (fields: any) => { if (! fields.$id) { fields.$id = { type: "__ID__", code: "$id", label: "$id", enabled: false, required: false, }; } if (! fields.$revision) { fields.$revision = { type: "__REVISION__", code: "$revision", label: "$revision", enabled: false, required: false, }; } return fields; } export const generateRawAppSchema = async (projectDir: string, appName: string) => { // app.json const metaApp = JSON.parse(await readFile(path.join(projectDir, 'meta/apps', appName, 'app.json'), { encoding: 'utf8' })); // form/fields.json const metaFields = JSON.parse(await readFile(path.join(projectDir, 'meta/apps', appName, 'form/fields.json'), { encoding: 'utf8' })); const fields = metaFields.properties; appendSystemFields(fields); const { subTableCode, code } = getRawFields(metaApp.name, 'RawApp', fields, 0); return '// @ts-nocheck\n\n' + subTableCode + code; };