Skip to content

Commit ef2890a

Browse files
committed
Merge branch 'master' of github.com:formio/formio-cli into fix-created-comparison
2 parents 753b440 + c8b97b7 commit ef2890a

File tree

8 files changed

+106
-20
lines changed

8 files changed

+106
-20
lines changed

commands/copy.js

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ module.exports = function(program, next) {
1414
.option('--src-admin-key [key]', 'The Admin API Key to provide to the source form')
1515
.option('--dst-admin-key [key]', 'The Admin API Key to provide to the destination form')
1616
.option('--full', 'Will copy full form or resource structure')
17+
.option(
18+
'--migrate-pdf-files [migratePdfFiles]',
19+
'Pass this option if you want to migrate PDF files from source PDF server to the destination for PDF forms',
20+
false
21+
)
1722
.action(series([
1823
require('../src/authenticate')({
1924
src: 1,

commands/migrate.js

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ module.exports = function(program, next) {
1313
.option('--dst-key [key]', 'The API Key to provide to the destination form')
1414
.option('--src-admin-key [key]', 'The Admin API Key to provide to the source form')
1515
.option('--dst-admin-key [key]', 'The Admin API Key to provide to the destination form')
16+
.option(
17+
'--migrate-pdf-files [migratePdfFiles]',
18+
'Pass this option if you want to migrate PDF files from source PDF server to the destination for PDF forms',
19+
false
20+
)
1621
.option('--start-with [startWith]', 'Start the migration from a specific form. Useful to replay migrations.')
1722
.option('--delete [delete]', 'Deletes all submissions in the destination form before the migration occurs.')
1823
.option('--delete-previous [deletePrevious]', 'Deletes previous submissions that have been migrated with the migrate script.')

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"JSONStream": "^1.3.5",
1919
"adm-zip": "^0.5.5",
2020
"async": "^3.2.4",
21+
"axios": "^1.7.7",
2122
"colors": "^1.4.0",
2223
"commander": "^6.2.0",
2324
"core-js": "^3.24.1",

src/authenticate.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ module.exports = function(config) {
6060

6161
// If the API Key is provided.
6262
if (options.key || options.adminKey || (options.srcAdminKey && options.dstAdminKey)) {
63-
console.log('An API Key was provided. Authenticated as Project Owner.');
63+
console.log('An API Key was provided for authentication');
6464
console.log('');
6565
return next(null);
6666
}

src/copy.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
var async = require('async');
44
var _ = require('lodash');
55
var fetch = require('./fetch');
6+
const {migratePdfFileForForm} = require('./utils');
67

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

34-
var copyComponents = function(form, cb) {
35+
var copyComponents = async function(form, cb) {
3536
if (options.full) {
3637
const formPart = _.omit(form, ['_id', '_vid', 'created', 'modified', 'machineName']);
3738
destForm = _.assign(formPart, {components: [...formPart.components, ...destForm.components]});
3839
}
3940
else {
40-
const formPart = _.pick(form, ['title', 'components', 'tags', 'properties']);
41+
const formPart = _.pick(form, ['title', 'components', 'tags', 'properties', 'settings', 'display']);
4142
destForm = _.assign(formPart, {components: [...formPart.components, ...destForm.components]});
4243
}
44+
45+
if (options.migratePdfFiles) {
46+
await migratePdfFileForForm(destForm, options);
47+
}
48+
4349
return cb();
4450
};
4551

src/migrate.js

+20-14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ const request = require('request');
88
const formTransform = require('./transforms/form');
99
const fetch = require('./fetch');
1010
const path = require('path');
11+
const axios = require('axios');
12+
const {migratePdfFileForForm} = require('./utils');
1113

1214
module.exports = function(options, next) {
1315
let isProject = false;
@@ -295,29 +297,33 @@ module.exports = function(options, next) {
295297
console.log(`Creating form ${_dest}`.green);
296298

297299
fetch(options.srcOptions)({
298-
url: _src
299-
}).then(({body}) => {
300+
url: _src,
301+
}).then(async({body}) => {
300302
const dstProject = _dest.replace(`/${body.path}`, '');
301-
request({
302-
json: true,
303-
method: 'POST',
304-
url: `${dstProject}/form`,
305-
headers: headers.dst,
306-
body: {
303+
try {
304+
const destForm = {
307305
title: body.title,
306+
display: body.display,
308307
path: body.path,
309308
name: body.name,
310309
type: body.type,
311-
components: body.components
312-
}
313-
}, (err, resp) => {
314-
if (err) {
315-
return done(err);
310+
components: body.components,
311+
settings: body.settings || {}
312+
};
313+
314+
if (options.migratePdfFiles) {
315+
await migratePdfFileForForm(destForm, options);
316316
}
317317

318+
await axios.post(`${dstProject}/form`, destForm, {'headers': {...headers.dst}});
319+
318320
// Migrate the data to this form.
319321
deleteThenMigrate();
320-
});
322+
}
323+
catch (err) {
324+
console.log(err);
325+
return done(err);
326+
}
321327
});
322328
});
323329
};

src/utils.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use strict';
2+
const axios = require('axios');
3+
const crypto = require('crypto');
4+
5+
async function getPdfFile(url) {
6+
const response = await axios.get(url, {responseType: 'arraybuffer'});
7+
const buffer = Buffer.from(response.data, 'binary'); // Get the file buffer
8+
const fileName = `${crypto.randomUUID()}.pdf`;
9+
10+
return {
11+
name: fileName,
12+
buffer
13+
};
14+
}
15+
16+
async function migratePdfFileForForm(form, options) {
17+
if (form.display !== 'pdf' || !form.settings.pdf) {
18+
return;
19+
}
20+
21+
const destUploadUrl = `${options.dstOptions.server}/${options.dstOptions.projectName}/upload`;
22+
const file = await getPdfFile(form.settings.pdf.src + '.pdf');
23+
const formData = new FormData();
24+
const fileBlob = new Blob([file.buffer], {type: 'application/pdf'});
25+
26+
formData.set('file', fileBlob, file.name);
27+
28+
const result = await axios.post(destUploadUrl, formData, {
29+
headers: {
30+
'x-token': options.dstOptions.key,
31+
'Content-Type': 'multipart/form-data',
32+
}
33+
});
34+
35+
// Assign new pdf file info to the form
36+
form.settings.pdf = {
37+
src: `${options.dstOptions.server}/pdf-proxy${result.data.path}`,
38+
id: result.data.file
39+
};
40+
}
41+
42+
module.exports = {
43+
migratePdfFileForForm
44+
};

yarn.lock

+22-3
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,15 @@ aws4@^1.8.0:
407407
resolved "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3"
408408
integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==
409409

410+
axios@^1.7.7:
411+
version "1.7.7"
412+
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f"
413+
integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==
414+
dependencies:
415+
follow-redirects "^1.15.6"
416+
form-data "^4.0.0"
417+
proxy-from-env "^1.1.0"
418+
410419
balanced-match@^1.0.0:
411420
version "1.0.2"
412421
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@@ -760,9 +769,9 @@ create-server@~1.0.1:
760769
connected "~0.0.2"
761770

762771
cross-spawn@^7.0.2:
763-
version "7.0.6"
764-
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
765-
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
772+
version "7.0.3"
773+
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
774+
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
766775
dependencies:
767776
path-key "^3.1.0"
768777
shebang-command "^2.0.0"
@@ -1379,6 +1388,11 @@ flatted@^3.1.0:
13791388
resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
13801389
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
13811390

1391+
follow-redirects@^1.15.6:
1392+
version "1.15.9"
1393+
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
1394+
integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
1395+
13821396
font-awesome@^4.7.0:
13831397
version "4.7.0"
13841398
resolved "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133"
@@ -2645,6 +2659,11 @@ proxy-addr@~2.0.7:
26452659
forwarded "0.2.0"
26462660
ipaddr.js "1.9.1"
26472661

2662+
proxy-from-env@^1.1.0:
2663+
version "1.1.0"
2664+
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
2665+
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
2666+
26482667
psl@^1.1.28:
26492668
version "1.9.0"
26502669
resolved "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"

0 commit comments

Comments
 (0)