kintone JS SDKを使って、指定したアプリとそのレコードを一括でコピーするコードを書いてみました。
コード
constkintone=require('@kintone/kintone-js-sdk');constfs=require('fs');constreduce=require('awaity/reduce').default;constauth=newkintone.Auth();auth.setBasicAuth({//Basic認証情報(必要な場合のみ)username:'\*\*\*\*',
password:'\*\*\*\*'});auth.setPasswordAuth({//kintoneログインユーザー情報(「kintoneのシステム管理権限」、「コピー元アプリのアプリ・レコード・フィールドの閲覧権限」を持ったユーザー)username:'\*\*\*\*',
password:'\*\*\*\*'});constconnection=newkintone.Connection({
domain:'\*\*\*\*.cybozu.com',//kintoneのドメインauth:auth
});constoriginAppId=\*\*\*\*;//コピーするアプリのIDconstappApi=newkintone.App({connection});constrecordApi=newkintone.Record({connection});constfileApi=newkintone.File({connection});constcopyFile=asyncfile=\>{awaitfileApi.download({
fileKey:file.fileKey,
outPutFilePath:file.name});constfileUploadResponse=awaitfileApi.upload({filePath:file.name});fs.unlink(file.name, ()=\>{});returnfileUploadResponse.fileKey;
};constformatProperties=properties=\>(Object.fromEntries(Object.entries(properties).filter(([fieldCode])=\>(!['レコード番号','$id','$revision','作成者','更新者','作成日時','更新日時','カテゴリー','作業者','ステータス'].includes(fieldCode)
)))
);constformatRecords=asyncrecords=\>await(Promise.all(records.map(asyncrecord=\>await(reduce(Object.entries(record).filter(([fieldCode])=\>(!['レコード番号','$id','$revision','作成者','更新者','作成日時','更新日時'].includes(fieldCode)
)),async(record, [fieldCode, field])=\>{
record[fieldCode]=field;if(field.type==='FILE'){
record[fieldCode].value=awaitPromise.all(field.value.map(asyncfile=\>await({...file,
fileKey:awaitcopyFile(file)
})));
}elseif(field.type==='SUBTABLE'){
record[fieldCode].value=awaitPromise.all(field.value.map(asyncrow=\>await({...row,
value:awaitreduce(Object.entries(row.value),async(rowValue, [fieldCode, field])=\>{
rowValue[fieldCode]=field;if(field.type==='FILE'){
rowValue[fieldCode].value=awaitPromise.all(field.value.map(asyncfile=\>await({...file,
fileKey:awaitcopyFile(file)
})));
}returnrowValue;
}, {})
})));
}returnrecord;
}, {})
)))
);
(async()=\>{constoriginApp=awaitPromise.all([appApi.getApp({id:originAppId}).then(app=\>({app})),appApi.getGeneralSettings({app:originAppId}).then(generalSettings=\>({generalSettings})),appApi.getFormFields({app:originAppId}).then(formFields=\>({formFields})),appApi.getFormLayout({app:originAppId}).then(formLayout=\>({formLayout})),appApi.getViews({app:originAppId}).then(views=\>({views})),recordApi.getAllRecordsByCursor({
app:originAppId,
query:'order by $id asc'}).then(records=\>({records}))
]).then(responses=\>{returnresponses.reduce((originApp,response)=\>{return{...originApp,
[Object.keys(response)[0]]:Object.values(response)[0]
};
}, {});
});constcopyAppName=`${originApp.app.name}\_copy\_${new Date()}`;//コピー先アプリ名constcopyAppId=awaitappApi.addPreviewApp({name:copyAppName}).then(response=\>response.app);awaitappApi.updateGeneralSettings({
app:copyAppId,
description:originApp.generalSettings.description,
icon:originApp.generalSettings.icon,
theme:originApp.generalSettings.theme});awaitappApi.addFormFields({
app:copyAppId,
fields:formatProperties(originApp.formFields.properties)
});awaitappApi.updateFormLayout({
app:copyAppId,
layout:originApp.formLayout.layout});if(!originApp.views.views){awaitappApi.updateViews({
app:copyAppId,
views:originApp.views.views});
}awaitappApi.deployAppSettings({apps:[{app:copyAppId}]});awaitnewPromise(resolve=\>{consttimer=setInterval(async()=\>{conststatus=awaitappApi.getAppDeployStatus({apps:[copyAppId]}).then(response=\>response.apps[0].status);if(status==='SUCCESS'){clearInterval(timer);resolve();
}
},1000);
});awaitrecordApi.addAllRecords({
app:copyAppId,
records:awaitformatRecords(originApp.records.records)
});console.log(`「${originApp.app.name}(appId:${originAppId})」を「${copyAppName}(appId:${copyAppId})」へコピーしました。`);
})();
・Node.js v12以上で動作します。(Object.fromEntries()を利用しているため。)
・「@kintone/kintone-js-sdk」及び「awaity」はnpm等でインストールして下さい。
・add、update処理に関してはエラーを避けるために直列処理としております。(参考)
・kintone REST API及びkintone JS SDKで対応していないアプリ設定値はコピーできません。
・過去記事でPHP版も紹介しています。PHP版では、kintone REST APIで対応しているアプリ設定値は全てコピーできます。