1 | const path = require('path');
|
2 | const fs = require('fs-extra');
|
3 | const prettier = require('prettier');
|
4 |
|
5 | const {
|
6 | createTable,
|
7 | createRows,
|
8 | fetchTable,
|
9 | fetchRows,
|
10 | publishTable,
|
11 | } = require('./api/hubdb');
|
12 |
|
13 | async function createHubDbTable(portalId, src) {
|
14 | try {
|
15 | const stats = fs.statSync(src);
|
16 | if (!stats.isFile()) {
|
17 | throw new Error(`The "${src}" path is not a path to a file`);
|
18 | }
|
19 | } catch (e) {
|
20 | throw new Error(`The "${src}" path is not a path to a file`);
|
21 | }
|
22 |
|
23 | if (path.extname(src) !== '.json') {
|
24 | throw new Error('The HubDB table file must be a ".json" file');
|
25 | }
|
26 |
|
27 | const table = fs.readJsonSync(src);
|
28 | const { rows, ...schema } = table;
|
29 |
|
30 | const { columns, id } = await createTable(portalId, schema);
|
31 |
|
32 | const rowsToUpdate = rows.map(row => {
|
33 | const values = {};
|
34 |
|
35 | columns.forEach(col => {
|
36 | const { name, id } = col;
|
37 | if (typeof row.values[name] !== 'undefined') {
|
38 | values[id] = row.values[name];
|
39 | } else {
|
40 | values[id] = null;
|
41 | }
|
42 | });
|
43 | return {
|
44 | childTableId: 0,
|
45 | isSoftEditable: false,
|
46 | ...row,
|
47 | values,
|
48 | };
|
49 | });
|
50 |
|
51 | let response;
|
52 | if (rowsToUpdate.length > 0) {
|
53 | response = await createRows(portalId, id, rowsToUpdate);
|
54 | }
|
55 |
|
56 | await publishTable(portalId, id);
|
57 |
|
58 | return {
|
59 | tableId: id,
|
60 | rowCount:
|
61 | response && Array.isArray(response) && response.length
|
62 | ? response[0].rows.length
|
63 | : 0,
|
64 | };
|
65 | }
|
66 |
|
67 | function convertToJSON(table, rows) {
|
68 | const {
|
69 | allowChildTables,
|
70 | allowPublicApiAccess,
|
71 | columns,
|
72 | dynamicMetaTags,
|
73 | enableChildTablePages,
|
74 | label,
|
75 | name,
|
76 | useForPages,
|
77 | } = table;
|
78 |
|
79 | const cleanedColumns = columns
|
80 | .filter(column => !column.deleted)
|
81 | .map(column => {
|
82 | const cleanedColumn = {
|
83 | ...column,
|
84 | };
|
85 |
|
86 | delete cleanedColumn.id;
|
87 | delete cleanedColumn.deleted;
|
88 | delete cleanedColumn.foreignIdsByName;
|
89 | delete cleanedColumn.foreignIdsById;
|
90 |
|
91 | return cleanedColumn;
|
92 | });
|
93 |
|
94 | const cleanedRows = rows.map(row => {
|
95 | const values = {};
|
96 |
|
97 | columns.forEach(col => {
|
98 | const { name, id } = col;
|
99 | if (row.values[id] !== null) {
|
100 | values[name] = row.values[id];
|
101 | }
|
102 | });
|
103 | return {
|
104 | path: row.path,
|
105 | name: row.name,
|
106 | isSoftEditable: row.isSoftEditable,
|
107 | values,
|
108 | };
|
109 | });
|
110 |
|
111 | return {
|
112 | name,
|
113 | useForPages,
|
114 | label,
|
115 | allowChildTables,
|
116 | allowPublicApiAccess,
|
117 | dynamicMetaTags,
|
118 | enableChildTablePages,
|
119 | columns: cleanedColumns,
|
120 | rows: cleanedRows,
|
121 | };
|
122 | }
|
123 |
|
124 | async function downloadHubDbTable(portalId, tableId, dest) {
|
125 | const table = await fetchTable(portalId, tableId);
|
126 |
|
127 | let totalRows = null;
|
128 | let rows = [];
|
129 | let count = 0;
|
130 | let offset = 0;
|
131 | while (totalRows === null || count < totalRows) {
|
132 | const response = await fetchRows(portalId, tableId, { offset });
|
133 | if (totalRows === null) {
|
134 | totalRows = response.total;
|
135 | }
|
136 |
|
137 | count += response.objects.length;
|
138 | offset += response.objects.length;
|
139 | rows = rows.concat(response.objects);
|
140 | }
|
141 |
|
142 | const tableToWrite = JSON.stringify(convertToJSON(table, rows));
|
143 | const tableJson = prettier.format(tableToWrite, {
|
144 | parser: 'json',
|
145 | });
|
146 |
|
147 | await fs.writeFileSync(dest, tableJson);
|
148 | }
|
149 |
|
150 | module.exports = {
|
151 | createHubDbTable,
|
152 | downloadHubDbTable,
|
153 | };
|