Skip to content

Commit

Permalink
Merge pull request #79 from formio/feat/FIO-7615_cli_tool_migrate_pdfs
Browse files Browse the repository at this point in the history
FIO-7615: Add option to migrate pdf files to copy and migrate commands
  • Loading branch information
brendanbond authored Feb 25, 2025
2 parents 15923b6 + 7a8f392 commit c8b97b7
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 18 deletions.
5 changes: 5 additions & 0 deletions commands/copy.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ module.exports = function(program, next) {
.option('--src-admin-key [key]', 'The Admin API Key to provide to the source form')
.option('--dst-admin-key [key]', 'The Admin API Key to provide to the destination form')
.option('--full', 'Will copy full form or resource structure')
.option(
'--migrate-pdf-files [migratePdfFiles]',
'Pass this option if you want to migrate PDF files from source PDF server to the destination for PDF forms',
false
)
.action(series([
require('../src/authenticate')({
src: 1,
Expand Down
5 changes: 5 additions & 0 deletions commands/migrate.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ module.exports = function(program, next) {
.option('--dst-key [key]', 'The API Key to provide to the destination form')
.option('--src-admin-key [key]', 'The Admin API Key to provide to the source form')
.option('--dst-admin-key [key]', 'The Admin API Key to provide to the destination form')
.option(
'--migrate-pdf-files [migratePdfFiles]',
'Pass this option if you want to migrate PDF files from source PDF server to the destination for PDF forms',
false
)
.option('--start-with [startWith]', 'Start the migration from a specific form. Useful to replay migrations.')
.option('--delete [delete]', 'Deletes all submissions in the destination form before the migration occurs.')
.option('--delete-previous [deletePrevious]', 'Deletes previous submissions that have been migrated with the migrate script.')
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"JSONStream": "^1.3.5",
"adm-zip": "^0.5.5",
"async": "^3.2.4",
"axios": "^1.7.7",
"colors": "^1.4.0",
"commander": "^6.2.0",
"core-js": "^3.24.1",
Expand Down
10 changes: 8 additions & 2 deletions src/copy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
var async = require('async');
var _ = require('lodash');
var fetch = require('./fetch');
const {migratePdfFileForForm} = require('./utils');

module.exports = function(options, done) {
var type = options.params[0].trim();
Expand Down Expand Up @@ -31,15 +32,20 @@ module.exports = function(options, done) {
return next('Invalid form type given: ' + type);
}

var copyComponents = function(form, cb) {
var copyComponents = async function(form, cb) {
if (options.full) {
const formPart = _.omit(form, ['_id', '_vid', 'created', 'modified', 'machineName']);
destForm = _.assign(formPart, {components: [...formPart.components, ...destForm.components]});
}
else {
const formPart = _.pick(form, ['title', 'components', 'tags', 'properties', 'settings']);
const formPart = _.pick(form, ['title', 'components', 'tags', 'properties', 'settings', 'display']);
destForm = _.assign(formPart, {components: [...formPart.components, ...destForm.components]});
}

if (options.migratePdfFiles) {
await migratePdfFileForForm(destForm, options);
}

return cb();
};

Expand Down
31 changes: 18 additions & 13 deletions src/migrate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const request = require('request');
const formTransform = require('./transforms/form');
const fetch = require('./fetch');
const path = require('path');
const axios = require('axios');
const {migratePdfFileForForm} = require('./utils');

module.exports = function(options, next) {
let isProject = false;
Expand Down Expand Up @@ -295,30 +297,33 @@ module.exports = function(options, next) {
console.log(`Creating form ${_dest}`.green);

fetch(options.srcOptions)({
url: _src
}).then(({body}) => {
url: _src,
}).then(async({body}) => {
const dstProject = _dest.replace(`/${body.path}`, '');
request({
json: true,
method: 'POST',
url: `${dstProject}/form`,
headers: headers.dst,
body: {
try {
const destForm = {
title: body.title,
display: body.display,
path: body.path,
name: body.name,
type: body.type,
components: body.components,
settings: body.settings || {}
}
}, (err, resp) => {
if (err) {
return done(err);
};

if (options.migratePdfFiles) {
await migratePdfFileForForm(destForm, options);
}

await axios.post(`${dstProject}/form`, destForm, {'headers': {...headers.dst}});

// Migrate the data to this form.
deleteThenMigrate();
});
}
catch (err) {
console.log(err);
return done(err);
}
});
});
};
Expand Down
44 changes: 44 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict';
const axios = require('axios');
const crypto = require('crypto');

async function getPdfFile(url) {
const response = await axios.get(url, {responseType: 'arraybuffer'});
const buffer = Buffer.from(response.data, 'binary'); // Get the file buffer
const fileName = `${crypto.randomUUID()}.pdf`;

return {
name: fileName,
buffer
};
}

async function migratePdfFileForForm(form, options) {
if (form.display !== 'pdf' || !form.settings.pdf) {
return;
}

const destUploadUrl = `${options.dstOptions.server}/${options.dstOptions.projectName}/upload`;
const file = await getPdfFile(form.settings.pdf.src + '.pdf');
const formData = new FormData();
const fileBlob = new Blob([file.buffer], {type: 'application/pdf'});

formData.set('file', fileBlob, file.name);

const result = await axios.post(destUploadUrl, formData, {
headers: {
'x-token': options.dstOptions.key,
'Content-Type': 'multipart/form-data',
}
});

// Assign new pdf file info to the form
form.settings.pdf = {
src: `${options.dstOptions.server}/pdf-proxy${result.data.path}`,
id: result.data.file
};
}

module.exports = {
migratePdfFileForForm
};
25 changes: 22 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,15 @@ aws4@^1.8.0:
resolved "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3"
integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==

axios@^1.7.7:
version "1.7.7"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f"
integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==
dependencies:
follow-redirects "^1.15.6"
form-data "^4.0.0"
proxy-from-env "^1.1.0"

balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
Expand Down Expand Up @@ -760,9 +769,9 @@ create-server@~1.0.1:
connected "~0.0.2"

cross-spawn@^7.0.2:
version "7.0.6"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
version "7.0.3"
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
dependencies:
path-key "^3.1.0"
shebang-command "^2.0.0"
Expand Down Expand Up @@ -1379,6 +1388,11 @@ flatted@^3.1.0:
resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==

follow-redirects@^1.15.6:
version "1.15.9"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==

font-awesome@^4.7.0:
version "4.7.0"
resolved "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133"
Expand Down Expand Up @@ -2645,6 +2659,11 @@ proxy-addr@~2.0.7:
forwarded "0.2.0"
ipaddr.js "1.9.1"

proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==

psl@^1.1.28:
version "1.9.0"
resolved "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
Expand Down

0 comments on commit c8b97b7

Please sign in to comment.