kdx
Version:
kintone CLI for development & deployment, with Developer Experience
217 lines • 7.38 kB
JavaScript
// Copyright (c) 2020 Shellyl_N and Authors
// license: MIT
// https://github.com/shellyln
import { validate } from 'tynder/modules/validator';
import { stereotypes as dateStereotypes } from 'tynder/modules/stereotypes/date';
import { constraints as uniqueConstraints } from 'tynder/modules/constraints/unique';
const SUBTABLE_ID_FIELD = '$$_subtable_id_$$';
export function mapRecord(rec) {
const ret = {};
const keys = Object.keys(rec);
const subTableMapper = (x) => {
const r = mapRecord(x.value);
r[SUBTABLE_ID_FIELD] = x.id;
return r;
};
for (const k of keys) {
if (rec[k].value === void 0) {
continue;
}
switch (rec[k].type) {
case 'NUMBER':
ret[k] = typeof rec[k].value === 'string' ?
Number(rec[k].value.replace(/[,]/g, '')) :
rec[k].value;
if (Number.isNaN(ret[k])) {
ret[k] = null;
}
break;
case 'SUBTABLE':
ret[k] = rec[k].value.map(subTableMapper);
break;
default:
ret[k] = rec[k].value;
break;
}
}
return ret;
}
function getObjectTypeMembers(members, ty) {
if (ty.kind !== 'object') {
throw new Error(`Unexpected type assertion kind: ${ty.kind} (${ty.typeName})`);
}
for (const m of ty.members) {
members.set(m[0], m[1]);
}
return members;
}
export function writeBackToKintoneRecord(rec, input, ty) {
var _a;
const members = new Map();
if (ty.kind === 'one-of') {
for (const one of ty.oneOf) {
getObjectTypeMembers(members, one);
}
}
else {
getObjectTypeMembers(members, ty);
}
for (const k of members.keys()) {
const mTy = members.get(k);
if (rec[k] === void 0 || rec[k] === null) {
// NOTE: fieldType 'STATUS' and 'CATEGORY' are readonly.
// const fieldType = mTy.meta.fieldType;
// if (fieldType === 'STATUS' || fieldType === 'CATEGORY') {
// continue;
// }
// NOTE: If field permission is set to not visible, rec[k] should not have a value.
// rec[k] = { type: fieldType, value: void 0 };
continue;
}
if (input[k] === void 0 || input[k] === null) {
rec[k].value = void 0;
continue;
}
switch (rec[k].type || ((_a = mTy.meta) === null || _a === void 0 ? void 0 : _a.fieldType)) {
case 'NUMBER':
rec[k].value = String(input[k]);
break;
case 'SUBTABLE':
{
const r = [];
for (const q of input[k]) {
let s = null;
if (q[SUBTABLE_ID_FIELD] !== null && q[SUBTABLE_ID_FIELD] !== void 0) {
s = rec[k].value.find(x => x.id === q[SUBTABLE_ID_FIELD]);
if (!s) {
throw new Error(`Missing subtable id is found: ${q[SUBTABLE_ID_FIELD]}`);
}
}
else {
s = { id: null, value: {} };
}
const subTy = mTy.kind === 'optional' ? mTy.optional : mTy;
if (subTy.kind !== 'repeated') {
throw new Error(`Subtable type should be repeated: ${subTy.kind}`);
}
writeBackToKintoneRecord(s.value, q, subTy.repeated);
r.push(s);
}
rec[k].value = r;
}
break;
default:
rec[k].value = input[k];
break;
}
}
return rec;
}
export function removeBlankTableRow(rec, tableFieldCode) {
const validRecs = [];
for (const r of rec[tableFieldCode].value) {
if (r.id !== null) {
validRecs.push(r);
continue;
}
const keys = Object.keys(r.value);
for (const k of keys) {
const q = r.value[k];
if (q.type === 'CALC') {
continue;
}
if (q.value !== void 0 && q.value !== null && q.value !== '') {
validRecs.push(r);
break;
}
}
}
rec[tableFieldCode].value = validRecs;
return rec;
}
export function displayValidationErrorMessages(event, ctx) {
var _a;
for (const m of (_a = ctx.errors) !== null && _a !== void 0 ? _a : []) {
const dp = m.dataPath.split('.').map(x => x.split(':').slice(-1)[0]);
const fieldCode = dp[0];
if (m.dataPath.includes('repeated).')) {
const index = /\.\(([0-9]+):repeated\)\./.exec(m.dataPath);
if (index) {
const subFieldCode = dp[dp.length - 1];
event.record[fieldCode].value[Number(index[1])].value[subFieldCode].error = m.message;
}
}
else {
if (event.record[fieldCode]) {
event.record[fieldCode].error = m.message;
}
}
}
event.error = 'Validation error';
return event;
}
const ctxGen = {
checkAll: true,
stereotypes: new Map([...dateStereotypes]),
customConstraints: new Map([...uniqueConstraints]),
};
export function validateThen(ev, schema, tyApp, fn, errFn) {
for (const m of tyApp.members) {
if (m[1].meta.fieldType === 'SUBTABLE') {
ev.record = removeBlankTableRow(ev.record, m[0]);
}
}
const unknownInput = mapRecord(ev.record);
const ctx = Object.assign(Object.assign({}, ctxGen), { schema });
const validated = validate(unknownInput, tyApp, ctx);
if (!validated) {
displayValidationErrorMessages(ev, ctx);
try {
if (errFn) {
errFn(ev);
}
}
catch (e) {
ev.error = e.message;
}
return ev;
}
const rec = validated.value;
const errHandler = (e) => {
ev.error = e.message;
try {
if (errFn) {
errFn(ev);
}
}
catch (e2) {
ev.error = e2.message;
}
};
let evRet = ev;
try {
const retVal = fn(rec, ev);
if (retVal) {
if (retVal.then) {
const p = (retVal
.then(d => {
writeBackToKintoneRecord(ev.record, d, tyApp);
return ev;
})
.catch(err => {
errHandler(err);
return ev; // NOTE: kintone will receive resolved promise.
}));
evRet = p;
}
else {
writeBackToKintoneRecord(ev.record, retVal, tyApp);
}
}
}
catch (e) {
errHandler(e);
}
return evRet;
}
//# sourceMappingURL=index.js.map