@firecms/data_import_export 3.0.0-canary.19 → 3.0.0-canary.191
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +114 -21
- package/README.md +1 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.es.js +12 -994
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +29 -2
- package/dist/index.umd.js.map +1 -1
- package/dist/useImportExportPlugin.d.ts +6 -4
- package/package.json +17 -34
- package/src/index.ts +2 -4
- package/src/useImportExportPlugin.tsx +10 -6
- package/dist/components/DataNewPropertiesMapping.d.ts +0 -15
- package/dist/components/ImportFileUpload.d.ts +0 -3
- package/dist/components/ImportNewPropertyFieldPreview.d.ts +0 -10
- package/dist/components/ImportSaveInProgress.d.ts +0 -8
- package/dist/components/index.d.ts +0 -4
- package/dist/export_import/ExportCollectionAction.d.ts +0 -11
- package/dist/export_import/ImportCollectionAction.d.ts +0 -15
- package/dist/export_import/export.d.ts +0 -10
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/useImportConfig.d.ts +0 -2
- package/dist/types/column_mapping.d.ts +0 -22
- package/dist/types/index.d.ts +0 -1
- package/dist/utils/data.d.ts +0 -11
- package/dist/utils/file_to_json.d.ts +0 -11
- package/dist/utils/get_import_inference_type.d.ts +0 -2
- package/dist/utils/get_properties_mapping.d.ts +0 -3
- package/dist/utils/index.d.ts +0 -4
- package/src/components/DataNewPropertiesMapping.tsx +0 -128
- package/src/components/ImportFileUpload.tsx +0 -34
- package/src/components/ImportNewPropertyFieldPreview.tsx +0 -55
- package/src/components/ImportSaveInProgress.tsx +0 -122
- package/src/components/index.ts +0 -4
- package/src/export_import/ExportCollectionAction.tsx +0 -252
- package/src/export_import/ImportCollectionAction.tsx +0 -442
- package/src/export_import/export.ts +0 -200
- package/src/hooks/index.ts +0 -1
- package/src/hooks/useImportConfig.tsx +0 -28
- package/src/types/column_mapping.ts +0 -32
- package/src/types/index.ts +0 -1
- package/src/utils/data.ts +0 -223
- package/src/utils/file_to_json.ts +0 -88
- package/src/utils/get_import_inference_type.ts +0 -27
- package/src/utils/get_properties_mapping.ts +0 -59
- package/src/utils/index.ts +0 -4
@@ -1,32 +0,0 @@
|
|
1
|
-
import React from "react";
|
2
|
-
import { DataType, Entity, Property } from "@firecms/core";
|
3
|
-
|
4
|
-
export type ImportConfig = {
|
5
|
-
|
6
|
-
inUse: boolean;
|
7
|
-
setInUse: React.Dispatch<React.SetStateAction<boolean>>;
|
8
|
-
|
9
|
-
idColumn: string | undefined;
|
10
|
-
setIdColumn: React.Dispatch<React.SetStateAction<string | undefined>>;
|
11
|
-
|
12
|
-
importData: object[];
|
13
|
-
setImportData: React.Dispatch<React.SetStateAction<object[]>>;
|
14
|
-
|
15
|
-
entities: Entity<any>[];
|
16
|
-
setEntities: React.Dispatch<React.SetStateAction<Entity<any>[]>>;
|
17
|
-
|
18
|
-
// mapping of the column name in the import file to the property key in the data model
|
19
|
-
headersMapping: Record<string, string | null>;
|
20
|
-
setHeadersMapping: React.Dispatch<React.SetStateAction<Record<string, string | null>>>;
|
21
|
-
|
22
|
-
originProperties: Record<string, Property>;
|
23
|
-
setOriginProperties: React.Dispatch<React.SetStateAction<Record<string, Property>>>;
|
24
|
-
|
25
|
-
}
|
26
|
-
|
27
|
-
export type DataTypeMapping = {
|
28
|
-
from: DataType;
|
29
|
-
fromSubtype?: DataType;
|
30
|
-
to: DataType;
|
31
|
-
toSubtype?: DataType;
|
32
|
-
}
|
package/src/types/index.ts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export * from "./column_mapping";
|
package/src/utils/data.ts
DELETED
@@ -1,223 +0,0 @@
|
|
1
|
-
import { DataType, Entity, EntityReference, getPropertyInPath, Properties } from "@firecms/core";
|
2
|
-
import { unflattenObject } from "./file_to_json";
|
3
|
-
|
4
|
-
type DataTypeMapping = {
|
5
|
-
from: DataType;
|
6
|
-
fromSubtype?: DataType;
|
7
|
-
to: DataType;
|
8
|
-
toSubtype?: DataType;
|
9
|
-
}
|
10
|
-
|
11
|
-
export function convertDataToEntity(data: Record<any, any>,
|
12
|
-
idColumn: string | undefined,
|
13
|
-
headersMapping: Record<string, string | null>,
|
14
|
-
properties: Properties,
|
15
|
-
propertiesMapping: Record<string, DataTypeMapping>,
|
16
|
-
path: string): Entity<any> {
|
17
|
-
const flatObject = flattenEntry(data);
|
18
|
-
if (idColumn)
|
19
|
-
delete flatObject[idColumn];
|
20
|
-
const mappedKeysObject = Object.entries(flatObject)
|
21
|
-
.map(([key, value]) => {
|
22
|
-
const mappedKey = headersMapping[key] ?? key;
|
23
|
-
|
24
|
-
const mappedProperty = getPropertyInPath(properties, mappedKey);
|
25
|
-
if (!mappedProperty)
|
26
|
-
return {};
|
27
|
-
|
28
|
-
const propertyMapping = propertiesMapping[mappedKey];
|
29
|
-
let valueResult = value;
|
30
|
-
if (propertyMapping) {
|
31
|
-
valueResult = processValueMapping(value, propertyMapping);
|
32
|
-
}
|
33
|
-
return ({
|
34
|
-
[mappedKey]: valueResult
|
35
|
-
});
|
36
|
-
})
|
37
|
-
.reduce((acc, curr) => ({ ...acc, ...curr }), {});
|
38
|
-
const values = unflattenObject(mappedKeysObject);
|
39
|
-
let id = idColumn ? data[idColumn] : undefined;
|
40
|
-
if (typeof id === "string") {
|
41
|
-
id = id.trim();
|
42
|
-
} else if (typeof id === "number") {
|
43
|
-
id = id.toString();
|
44
|
-
} else if (typeof id === "boolean") {
|
45
|
-
id = id.toString();
|
46
|
-
} else if (id instanceof Date) {
|
47
|
-
id = id.toISOString();
|
48
|
-
} else if (id && "toString" in id) {
|
49
|
-
id = id.toString();
|
50
|
-
}
|
51
|
-
|
52
|
-
return {
|
53
|
-
id,
|
54
|
-
values,
|
55
|
-
path
|
56
|
-
};
|
57
|
-
}
|
58
|
-
|
59
|
-
export function flattenEntry(obj: any, parent = ""): any {
|
60
|
-
return Object.keys(obj).reduce((acc, key) => {
|
61
|
-
const prefixedKey = parent ? `${parent}.${key}` : key;
|
62
|
-
|
63
|
-
if (typeof obj[key] === "object" && obj[key] !== null && !Array.isArray(obj[key])) {
|
64
|
-
Object.assign(acc, flattenEntry(obj[key], prefixedKey));
|
65
|
-
} else {
|
66
|
-
// @ts-ignore
|
67
|
-
acc[prefixedKey] = obj[key];
|
68
|
-
}
|
69
|
-
|
70
|
-
return acc;
|
71
|
-
}, {});
|
72
|
-
}
|
73
|
-
|
74
|
-
// export function convertDataEntryValue({
|
75
|
-
// key,
|
76
|
-
// fullKey,
|
77
|
-
// value,
|
78
|
-
// idColumn,
|
79
|
-
// headersMapping,
|
80
|
-
// properties,
|
81
|
-
// propertiesMapping
|
82
|
-
// }: {
|
83
|
-
// key?: string,
|
84
|
-
// fullKey: string,
|
85
|
-
// value: any,
|
86
|
-
// idColumn?: string,
|
87
|
-
// headersMapping: Record<string, string | null>,
|
88
|
-
// properties: Properties,
|
89
|
-
// propertiesMapping: Record<string, DataTypeMapping>
|
90
|
-
// }): any {
|
91
|
-
//
|
92
|
-
// if (value === undefined) return value;
|
93
|
-
// if (value === null) return value;
|
94
|
-
//
|
95
|
-
// if (Array.isArray(value)) {
|
96
|
-
// const mappedKey = headersMapping[fullKey] || fullKey;
|
97
|
-
// const valueMapping = propertiesMapping[mappedKey];
|
98
|
-
// return processValueMapping(value, valueMapping);
|
99
|
-
// // return value.map(v => convertDataEntryValue({ value: v, fullKey, idColumn, headersMapping, propertiesMapping }));
|
100
|
-
// } else if (typeof value === "object") {
|
101
|
-
// return convertDataObjectValue({
|
102
|
-
// key,
|
103
|
-
// fullKey,
|
104
|
-
// value,
|
105
|
-
// idColumn,
|
106
|
-
// headersMapping,
|
107
|
-
// properties,
|
108
|
-
// propertiesMapping
|
109
|
-
// });
|
110
|
-
// } else {
|
111
|
-
// const mappedKey = headersMapping[fullKey] || fullKey;
|
112
|
-
// const valueMapping = propertiesMapping[mappedKey];
|
113
|
-
// return processValueMapping(value, valueMapping);
|
114
|
-
// }
|
115
|
-
// }
|
116
|
-
|
117
|
-
// export function convertDataObjectValue({
|
118
|
-
// key,
|
119
|
-
// fullKey,
|
120
|
-
// value,
|
121
|
-
// idColumn,
|
122
|
-
// headersMapping,
|
123
|
-
// properties,
|
124
|
-
// propertiesMapping
|
125
|
-
// }: {
|
126
|
-
// key?: string,
|
127
|
-
// fullKey?: string,
|
128
|
-
// value: object,
|
129
|
-
// idColumn?: string,
|
130
|
-
// headersMapping: Record<string, string | null>,
|
131
|
-
// properties: Properties,
|
132
|
-
// propertiesMapping: Record<string, DataTypeMapping>
|
133
|
-
// }): object {
|
134
|
-
//
|
135
|
-
// if (value instanceof Date) {
|
136
|
-
// const mappedKey = fullKey ? headersMapping[fullKey] || fullKey : undefined;
|
137
|
-
// const valueMapping = mappedKey ? propertiesMapping[mappedKey] : undefined;
|
138
|
-
// return processValueMapping(value, valueMapping);
|
139
|
-
// }
|
140
|
-
//
|
141
|
-
// return Object.entries(value)
|
142
|
-
// .map(([childKey, childValue]) => {
|
143
|
-
// const childFullKey = fullKey ? `${fullKey}.${childKey}` : childKey;
|
144
|
-
// const mappedKey = headersMapping[childFullKey] ?? childFullKey;
|
145
|
-
// const mappedKeyLastPart = mappedKey.split(".").slice(-1)[0];
|
146
|
-
// const property = getPropertyInPath(properties, mappedKey);
|
147
|
-
// // if (!property) {
|
148
|
-
// // console.log("ppp", { properties, mappedKey, })
|
149
|
-
// // return {};
|
150
|
-
// // }
|
151
|
-
// return ({
|
152
|
-
// [mappedKeyLastPart]: convertDataEntryValue({
|
153
|
-
// key: childKey,
|
154
|
-
// fullKey: childFullKey,
|
155
|
-
// value: childValue,
|
156
|
-
// idColumn,
|
157
|
-
// headersMapping,
|
158
|
-
// properties,
|
159
|
-
// propertiesMapping
|
160
|
-
// })
|
161
|
-
// });
|
162
|
-
// })
|
163
|
-
// .reduce((acc, curr) => ({ ...acc, ...curr }), {});
|
164
|
-
// }
|
165
|
-
|
166
|
-
export function processValueMapping(value: any, valueMapping?: DataTypeMapping): any {
|
167
|
-
if (valueMapping === undefined) return value;
|
168
|
-
const {
|
169
|
-
from,
|
170
|
-
to
|
171
|
-
} = valueMapping;
|
172
|
-
if (from === "array" && to === "array" && valueMapping.fromSubtype && valueMapping.toSubtype && Array.isArray(value)) {
|
173
|
-
return value.map(v => processValueMapping(v, {
|
174
|
-
from: valueMapping.fromSubtype!,
|
175
|
-
to: valueMapping.toSubtype!
|
176
|
-
}));
|
177
|
-
} else if (from === "string" && to === "number" && typeof value === "string") {
|
178
|
-
return Number(value);
|
179
|
-
} else if (from === "string" && to === "array" && valueMapping.toSubtype && typeof value === "string") {
|
180
|
-
return value.split(",").map((v: string) => processValueMapping(v, {
|
181
|
-
from: "string",
|
182
|
-
to: valueMapping.toSubtype!
|
183
|
-
}));
|
184
|
-
} else if (from === "string" && to === "boolean") {
|
185
|
-
return value === "true";
|
186
|
-
} else if (from === "number" && to === "boolean") {
|
187
|
-
return value === 1;
|
188
|
-
} else if (from === "boolean" && to === "number") {
|
189
|
-
return value ? 1 : 0;
|
190
|
-
} else if (from === "boolean" && to === "string") {
|
191
|
-
return value ? "true" : "false";
|
192
|
-
} else if (from === "number" && to === "string" && typeof value === "number") {
|
193
|
-
return value.toString();
|
194
|
-
} else if (from === "string" && to === "array" && typeof value === "string") {
|
195
|
-
return value.split(",").map((v: string) => v.trim());
|
196
|
-
} else if (from === "string" && to === "date" && typeof value === "string") {
|
197
|
-
try {
|
198
|
-
return new Date(value);
|
199
|
-
} catch (e) {
|
200
|
-
return value;
|
201
|
-
}
|
202
|
-
} else if (from === "date" && to === "string") {
|
203
|
-
return value instanceof Date && value.toISOString();
|
204
|
-
} else if (from === "number" && to === "date" && typeof value === "number") {
|
205
|
-
try {
|
206
|
-
return new Date(value);
|
207
|
-
} catch (e) {
|
208
|
-
return value;
|
209
|
-
}
|
210
|
-
} else if (from === "string" && to === "reference" && typeof value === "string") {
|
211
|
-
// split value into path and entityId (entityId is the last part of the path, after the last /)
|
212
|
-
const path = value.split("/").slice(0, -1).join("/");
|
213
|
-
const entityId = value.split("/").slice(-1)[0];
|
214
|
-
return new EntityReference(entityId, path);
|
215
|
-
|
216
|
-
} else if (from === to) {
|
217
|
-
return value;
|
218
|
-
} else if (from === "array" && to === "string" && Array.isArray(value)) {
|
219
|
-
return value.join(",");
|
220
|
-
}
|
221
|
-
|
222
|
-
return value;
|
223
|
-
}
|
@@ -1,88 +0,0 @@
|
|
1
|
-
import * as XLSX from "xlsx";
|
2
|
-
|
3
|
-
export function convertFileToJson(file: File): Promise<object[]> {
|
4
|
-
return new Promise((resolve, reject) => {
|
5
|
-
// check if file is a JSON file
|
6
|
-
if (file.type === "application/json") {
|
7
|
-
console.debug("Converting JSON file to JSON", file.name);
|
8
|
-
const reader = new FileReader();
|
9
|
-
reader.onload = function (e) {
|
10
|
-
const data = e.target?.result as string;
|
11
|
-
const jsonData = JSON.parse(data);
|
12
|
-
if (!Array.isArray(jsonData)) {
|
13
|
-
reject(new Error("JSON file should contain an array of objects"));
|
14
|
-
}
|
15
|
-
resolve(jsonData);
|
16
|
-
};
|
17
|
-
reader.readAsText(file);
|
18
|
-
} else {
|
19
|
-
console.debug("Converting Excel file to JSON", file.name);
|
20
|
-
const reader = new FileReader();
|
21
|
-
reader.onload = function (e) {
|
22
|
-
|
23
|
-
const data = new Uint8Array(e.target?.result as ArrayBuffer);
|
24
|
-
const workbook = XLSX.read(data,
|
25
|
-
{
|
26
|
-
type: "array",
|
27
|
-
codepage: 65001,
|
28
|
-
cellDates: true,
|
29
|
-
});
|
30
|
-
const worksheetName = workbook.SheetNames[0];
|
31
|
-
const worksheet = workbook.Sheets[worksheetName];
|
32
|
-
const parsedData: Array<any> = XLSX.utils.sheet_to_json(worksheet);
|
33
|
-
const cleanedData = parsedData.map(mapJsonParse);
|
34
|
-
const jsonData = cleanedData.map(unflattenObject);
|
35
|
-
resolve(jsonData);
|
36
|
-
};
|
37
|
-
reader.readAsArrayBuffer(file);
|
38
|
-
}
|
39
|
-
});
|
40
|
-
}
|
41
|
-
|
42
|
-
function mapJsonParse(obj: Record<string, any>) {
|
43
|
-
return Object.keys(obj).reduce((acc: Record<string, any>, key) => {
|
44
|
-
try {
|
45
|
-
acc[key] = JSON.parse(obj[key]);
|
46
|
-
} catch (e) {
|
47
|
-
acc[key] = obj[key];
|
48
|
-
}
|
49
|
-
return acc;
|
50
|
-
}, {});
|
51
|
-
}
|
52
|
-
|
53
|
-
/**
|
54
|
-
* Take an object with keys of type `address.street`, `address.city` and
|
55
|
-
* convert it to an object with nested objects like `{ address: { street: ..., city: ... } }`
|
56
|
-
* @param flatObj
|
57
|
-
*/
|
58
|
-
export function unflattenObject(flatObj: { [key: string]: any }) {
|
59
|
-
return Object.keys(flatObj).reduce((nestedObj, key) => {
|
60
|
-
let currentObj = nestedObj;
|
61
|
-
const keyParts = key.split(".");
|
62
|
-
keyParts.forEach((keyPart, i) => {
|
63
|
-
|
64
|
-
if (/^[\w]+\[\d+\]$/.test(keyPart)) {
|
65
|
-
const mainPropertyName = keyPart.slice(0, keyPart.indexOf("["));
|
66
|
-
const index = parseInt(keyPart.slice(keyPart.indexOf("[") + 1, keyPart.indexOf("]")));
|
67
|
-
|
68
|
-
if (!currentObj[mainPropertyName]) {
|
69
|
-
currentObj[mainPropertyName] = []
|
70
|
-
}
|
71
|
-
|
72
|
-
if (i !== keyParts.length - 1) {
|
73
|
-
currentObj[mainPropertyName][index] = currentObj[mainPropertyName][index] || {};
|
74
|
-
currentObj = currentObj[mainPropertyName][index];
|
75
|
-
} else {
|
76
|
-
currentObj[mainPropertyName][index] = flatObj[key];
|
77
|
-
}
|
78
|
-
} else if (i !== keyParts.length - 1) {
|
79
|
-
currentObj[keyPart] = currentObj[keyPart] || {};
|
80
|
-
currentObj = currentObj[keyPart];
|
81
|
-
} else {
|
82
|
-
currentObj[keyPart] = flatObj[key];
|
83
|
-
}
|
84
|
-
|
85
|
-
});
|
86
|
-
return nestedObj;
|
87
|
-
}, {} as { [key: string]: any });
|
88
|
-
}
|
@@ -1,27 +0,0 @@
|
|
1
|
-
import { DataType } from "@firecms/core";
|
2
|
-
|
3
|
-
export function getInferenceType(value: any): DataType {
|
4
|
-
if (typeof value === "number")
|
5
|
-
return "number";
|
6
|
-
else if (typeof value === "string")
|
7
|
-
return "string";
|
8
|
-
else if (typeof value === "boolean")
|
9
|
-
return "boolean";
|
10
|
-
else if (value instanceof Date)
|
11
|
-
return "date";
|
12
|
-
else if (Array.isArray(value))
|
13
|
-
return "array";
|
14
|
-
return "map";
|
15
|
-
}
|
16
|
-
|
17
|
-
|
18
|
-
function isUnixTimestamp(num: number): boolean {
|
19
|
-
const numString = num.toString();
|
20
|
-
// check if the number has 13 digits
|
21
|
-
const isLengthValid = numString.length === 13;
|
22
|
-
|
23
|
-
// check if it falls in the expected Unix timestamp range (from 1970 to 2100)
|
24
|
-
const isInRange = num >= 0 && num <= 4102444800000;
|
25
|
-
|
26
|
-
return isLengthValid && isInRange;
|
27
|
-
}
|
@@ -1,59 +0,0 @@
|
|
1
|
-
import { DataType, getPropertyInPath, Properties, Property } from "@firecms/core";
|
2
|
-
import { DataTypeMapping } from "../types";
|
3
|
-
|
4
|
-
export function getPropertiesMapping(originProperties: Properties, newProperties: Properties): Record<string, DataTypeMapping> {
|
5
|
-
|
6
|
-
function updateMapping(properties: Record<string, Property>, namespace?: string): Record<string, DataTypeMapping> {
|
7
|
-
|
8
|
-
const dataMapping: Record<string, DataTypeMapping> = {};
|
9
|
-
|
10
|
-
Object.keys(properties).forEach((key) => {
|
11
|
-
|
12
|
-
const currentKey = namespace ? `${namespace}.${key}` : key;
|
13
|
-
|
14
|
-
const property = getPropertyInPath(properties, key) as Property;
|
15
|
-
const inferredProperty = getPropertyInPath(originProperties, currentKey) as Property;
|
16
|
-
|
17
|
-
if (property) {
|
18
|
-
if (property.dataType === "map" && property.properties) {
|
19
|
-
const nestedMapping = updateMapping(property.properties as Record<string, Property>, currentKey);
|
20
|
-
Object.keys(nestedMapping).forEach((nestedKey) => {
|
21
|
-
dataMapping[`${currentKey}.${nestedKey}`] = nestedMapping[nestedKey];
|
22
|
-
});
|
23
|
-
return;
|
24
|
-
}
|
25
|
-
|
26
|
-
if (inferredProperty) {
|
27
|
-
|
28
|
-
const from = inferredProperty.dataType;
|
29
|
-
const to = property.dataType;
|
30
|
-
let fromSubtype: DataType | undefined;
|
31
|
-
let toSubtype: DataType | undefined;
|
32
|
-
|
33
|
-
if (property.dataType === "array" && property.of) {
|
34
|
-
toSubtype = (property.of as Property).dataType;
|
35
|
-
}
|
36
|
-
|
37
|
-
if (inferredProperty?.dataType === "array" && inferredProperty?.of) {
|
38
|
-
fromSubtype = (inferredProperty.of as Property).dataType;
|
39
|
-
}
|
40
|
-
|
41
|
-
if (from !== to || fromSubtype !== toSubtype) {
|
42
|
-
dataMapping[key] = {
|
43
|
-
from,
|
44
|
-
to,
|
45
|
-
fromSubtype,
|
46
|
-
toSubtype
|
47
|
-
};
|
48
|
-
}
|
49
|
-
}
|
50
|
-
|
51
|
-
}
|
52
|
-
|
53
|
-
});
|
54
|
-
|
55
|
-
return dataMapping;
|
56
|
-
}
|
57
|
-
|
58
|
-
return updateMapping(newProperties);
|
59
|
-
}
|
package/src/utils/index.ts
DELETED