@firecms/schema_inference 3.0.0-alpha.15 → 3.0.0-alpha.16

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.
@@ -0,0 +1,3 @@
1
+ import { InferencePropertyBuilderProps } from "../types";
2
+ import { Property } from "@firecms/core";
3
+ export declare function buildReferenceProperty({ totalDocsCount, valuesResult }: InferencePropertyBuilderProps): Property;
@@ -0,0 +1,3 @@
1
+ import { Property } from "@firecms/core";
2
+ import { InferencePropertyBuilderProps } from "../types";
3
+ export declare function buildStringProperty({ totalDocsCount, valuesResult }: InferencePropertyBuilderProps): Property;
@@ -0,0 +1,3 @@
1
+ import { PropertyValidationSchema } from "@firecms/core";
2
+ import { InferencePropertyBuilderProps } from "../types";
3
+ export declare function buildValidation({ totalDocsCount, valuesResult }: InferencePropertyBuilderProps): PropertyValidationSchema | undefined;
@@ -0,0 +1,5 @@
1
+ import { DataType, Properties, Property } from "@firecms/core";
2
+ export type InferenceTypeBuilder = (value: any) => DataType;
3
+ export declare function buildEntityPropertiesFromData(data: object[], getType: InferenceTypeBuilder): Promise<Properties>;
4
+ export declare function buildPropertyFromData(data: any[], property: Property, getType: InferenceTypeBuilder): Property;
5
+ export declare function buildPropertiesOrder(properties: Properties<any>): string[];
@@ -0,0 +1,231 @@
1
+ import { unslugify as y, resolveEnumValues as P, mergeDeep as I } from "@firecms/core";
2
+ import { DocumentReference as S } from "firebase/firestore";
3
+ function d(r) {
4
+ if (!r)
5
+ return;
6
+ function e(o) {
7
+ return typeof o == "string" ? o : o instanceof S ? o.path : void 0;
8
+ }
9
+ const s = r.values.map((o) => e(o)).filter((o) => !!o).find((o) => o.includes("/"));
10
+ if (!s)
11
+ return;
12
+ const n = s.substr(0, s.lastIndexOf("/"));
13
+ return r.values.filter((o) => {
14
+ const a = e(o);
15
+ return a ? a.startsWith(n) : !1;
16
+ }).length > r.values.length / 3 * 2 ? n : void 0;
17
+ }
18
+ function E(r) {
19
+ const e = r.map((t) => ({ id: t, label: y(t) }));
20
+ return e.sort((t, s) => t.label.localeCompare(s.label)), e;
21
+ }
22
+ const M = [".jpg", ".png", ".webp", ".gif"], V = [".mp3", ".ogg", ".opus", ".aac"], x = [".avi", ".mp4"], C = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
23
+ function F({
24
+ totalDocsCount: r,
25
+ valuesResult: e
26
+ }) {
27
+ let t = {
28
+ dataType: "string"
29
+ };
30
+ if (e) {
31
+ const s = e.values.length, n = Array.from(e.valuesCount.keys()).length, i = {}, o = e.values.filter((c) => typeof c == "string" && c.toString().startsWith("http")).length > r / 3 * 2;
32
+ o && (i.url = !0);
33
+ const a = e.values.filter((c) => typeof c == "string" && C.test(c)).length > r / 3 * 2;
34
+ a && (i.email = !0);
35
+ const f = e.values.filter((c) => typeof c == "string" && c.length === 28 && !c.includes(" ")).length > r / 3 * 2;
36
+ if (f && (i.readOnly = !0), !a && !o && !f && !o && n < s / 3) {
37
+ const c = E(Array.from(e.valuesCount.keys()));
38
+ Object.keys(c).length > 1 && (i.enumValues = c);
39
+ }
40
+ if (!a && !o && !f && !o && !i.enumValues) {
41
+ const c = _(e, r);
42
+ c && (i.storage = {
43
+ acceptedFiles: [c],
44
+ storagePath: d(e) ?? "/"
45
+ });
46
+ }
47
+ Object.keys(i).length > 0 && (t = {
48
+ ...t,
49
+ ...i
50
+ });
51
+ }
52
+ return t;
53
+ }
54
+ function _(r, e) {
55
+ const t = r.values.filter((o) => typeof o == "string" && M.some((a) => o.toString().endsWith(a))).length > e / 3 * 2, s = r.values.filter((o) => typeof o == "string" && V.some((a) => o.toString().endsWith(a))).length > e / 3 * 2, n = r.values.filter((o) => typeof o == "string" && x.some((a) => o.toString().endsWith(a))).length > e / 3 * 2;
56
+ return t ? "image/*" : s ? "audio/*" : n ? "video/*" : !1;
57
+ }
58
+ function z({
59
+ totalDocsCount: r,
60
+ valuesResult: e
61
+ }) {
62
+ if (e) {
63
+ const t = e.values.length;
64
+ if (r === t)
65
+ return {
66
+ required: !0
67
+ };
68
+ }
69
+ }
70
+ function W({
71
+ totalDocsCount: r,
72
+ valuesResult: e
73
+ }) {
74
+ return {
75
+ dataType: "reference",
76
+ path: d(e) ?? "!!!FIX_ME!!!"
77
+ };
78
+ }
79
+ async function U(r, e) {
80
+ const t = {}, s = {};
81
+ return r.forEach((n) => {
82
+ n && Object.entries(n).forEach(([i, o]) => {
83
+ O(t, i, o, e), m(s, i, o, e);
84
+ });
85
+ }), T(r.length, t, s);
86
+ }
87
+ function X(r, e, t) {
88
+ const s = {}, n = {};
89
+ r.forEach((a) => {
90
+ p(e.dataType, s, a, t), m(n, "inferred_prop", a, t);
91
+ });
92
+ const i = "enumValues" in e ? P(e.enumValues) : void 0;
93
+ if (i) {
94
+ const a = E(Array.from(n.inferred_prop.valuesCount.keys()));
95
+ return console.log("newEnumValues", a), { ...e, enumValues: [...a, ...i] };
96
+ }
97
+ const o = b("inferred_prop", r.length, e.dataType, s, n.inferred_prop);
98
+ return I(o, e);
99
+ }
100
+ function v(r) {
101
+ function e(s) {
102
+ const n = s.toLowerCase();
103
+ return n === "title" || n === "name" ? 3 : n.includes("title") || n.includes("name") ? 2 : n.includes("image") || n.includes("picture") ? 1 : 0;
104
+ }
105
+ const t = Object.keys(r);
106
+ return t.sort(), t.sort((s, n) => e(n) - e(s)), t;
107
+ }
108
+ function p(r, e, t, s) {
109
+ if (r === "map") {
110
+ if (t) {
111
+ let n = e[r];
112
+ n || (n = {}, e[r] = n), Object.entries(t).forEach(([i, o]) => {
113
+ O(n, i, o, s);
114
+ });
115
+ }
116
+ } else if (r === "array") {
117
+ let n = e[r];
118
+ if (n || (n = {}, e[r] = n), t && Array.isArray(t) && t.length > 0) {
119
+ const i = Z(t, s);
120
+ n[i] ? n[i]++ : n[i] = 1;
121
+ }
122
+ } else
123
+ e[r] ? e[r]++ : e[r] = 1;
124
+ }
125
+ function O(r, e, t, s) {
126
+ let n = r[e];
127
+ if (n || (n = {}, r[e] = n), t != null) {
128
+ const i = s(t);
129
+ p(i, n, t, s);
130
+ }
131
+ }
132
+ function m(r, e, t, s) {
133
+ const n = s(t);
134
+ let i = r[e];
135
+ if (i || (i = {
136
+ values: [],
137
+ valuesCount: /* @__PURE__ */ new Map()
138
+ }, r[e] = i), n === "map") {
139
+ let o = i.map;
140
+ o || (o = {}, i.map = o), t && Object.entries(t).forEach(([a, f]) => m(o, a, f, s));
141
+ } else
142
+ n === "array" ? Array.isArray(t) && t.forEach((o) => {
143
+ i.values.push(o), i.valuesCount.set(o, (i.valuesCount.get(o) ?? 0) + 1);
144
+ }) : t && (i.values.push(t), i.valuesCount.set(t, (i.valuesCount.get(t) ?? 0) + 1));
145
+ }
146
+ function h(r) {
147
+ let e = 0;
148
+ return Object.entries(r).forEach(([t, s]) => {
149
+ let n = 0;
150
+ t === "map" ? n = A(s) : t === "array" ? n = h(s) : n = s, n > e && (e = n);
151
+ }), e;
152
+ }
153
+ function A(r) {
154
+ return Object.entries(r).map(([e, t]) => h(t)).reduce((e, t) => Math.max(e, t), 0);
155
+ }
156
+ function g(r) {
157
+ let e = -1, t = "string";
158
+ return Object.entries(r).forEach(([s, n]) => {
159
+ let i;
160
+ s === "map" ? i = A(n) : s === "array" ? i = h(n) : i = n, i > e && (e = i, t = s);
161
+ }), t;
162
+ }
163
+ function b(r, e, t, s, n) {
164
+ let i;
165
+ if (r && (i = y(r)), t === "map") {
166
+ if (w(s))
167
+ return {
168
+ dataType: "map",
169
+ name: i,
170
+ keyValue: !0,
171
+ properties: {}
172
+ };
173
+ const u = T(e, s.map, n ? n.mapValues : void 0);
174
+ return {
175
+ dataType: "map",
176
+ name: i,
177
+ properties: u
178
+ };
179
+ } else if (t === "array") {
180
+ const c = s.array, u = g(c), j = b(r, e, u, c, n);
181
+ return {
182
+ dataType: "array",
183
+ name: i,
184
+ of: j
185
+ };
186
+ }
187
+ let o;
188
+ const a = {
189
+ name: r,
190
+ totalDocsCount: e,
191
+ valuesResult: n
192
+ };
193
+ t === "string" ? o = F(a) : t === "reference" ? o = W(a) : o = {
194
+ dataType: t
195
+ }, i && (o.name = i);
196
+ const f = z(a);
197
+ return f && (o.validation = f), o;
198
+ }
199
+ function T(r, e, t) {
200
+ const s = {};
201
+ return Object.entries(e).forEach(([n, i]) => {
202
+ const o = g(i);
203
+ s[n] = b(n, r, o, i, t ? t[n] : void 0);
204
+ }), s;
205
+ }
206
+ function l(r) {
207
+ let e = 0;
208
+ return Object.entries(r).forEach(([t, s]) => {
209
+ typeof s == "object" ? e = Math.max(e, l(s)) : e = Math.max(e, s);
210
+ }), e;
211
+ }
212
+ function Z(r, e) {
213
+ let t = {};
214
+ return r.forEach((s) => {
215
+ p(e(s), t, s, e);
216
+ }), g(t);
217
+ }
218
+ function w(r) {
219
+ const e = l(r);
220
+ let t = 0;
221
+ return Object.entries(r.map ?? {}).forEach(([s, n]) => {
222
+ l(n) < e / 3 && t++;
223
+ }), t / Object.entries(r.map ?? {}).length > 0.5;
224
+ }
225
+ export {
226
+ U as buildEntityPropertiesFromData,
227
+ v as buildPropertiesOrder,
228
+ X as buildPropertyFromData,
229
+ E as extractEnumFromValues
230
+ };
231
+ //# sourceMappingURL=index.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.es.js","sources":["../src/strings.ts","../src/util.ts","../src/builders/string_property_builder.ts","../src/builders/validation_builder.ts","../src/builders/reference_property_builder.ts","../src/collection_builder.ts"],"sourcesContent":["import { ValuesCountEntry } from \"./types\";\nimport { DocumentReference } from \"firebase/firestore\";\n\n\nexport function findCommonInitialStringInPath(valuesCount?: ValuesCountEntry) {\n\n if (!valuesCount) return undefined;\n\n function getPath(value: any) {\n if (typeof value === \"string\") return value;\n else if (value instanceof DocumentReference) return value.path;\n else return undefined;\n }\n\n const strings: string[] = valuesCount.values.map((v) => getPath(v)).filter(v => !!v) as string[];\n const pathWithSlash = strings.find((s) => s.includes(\"/\"));\n if (!pathWithSlash)\n return undefined;\n\n const searchedPath = pathWithSlash.substr(0, pathWithSlash.lastIndexOf(\"/\"));\n\n const yep = valuesCount.values\n .filter((value) => {\n const path = getPath(value);\n if (!path) return false;\n return path.startsWith(searchedPath)\n }).length > valuesCount.values.length / 3 * 2;\n\n return yep ? searchedPath : undefined;\n\n}\n\nexport function removeInitialAndTrailingSlashes(s: string): string {\n return removeInitialSlash(removeTrailingSlash(s));\n}\n\nexport function removeInitialSlash(s: string) {\n if (s.startsWith(\"/\"))\n return s.slice(1);\n else return s;\n}\n\nexport function removeTrailingSlash(s: string) {\n if (s.endsWith(\"/\"))\n return s.slice(0, -1);\n else return s;\n}\n","import { unslugify } from \"@firecms/core\";\n\nexport function extractEnumFromValues(values: string[]) {\n const enumValues = values\n .map((value) => ({ id: value, label: unslugify(value) }));\n enumValues.sort((a, b) => a.label.localeCompare(b.label));\n return enumValues;\n}\n","import { FileType, Property, StringProperty, unslugify } from \"@firecms/core\";\nimport { InferencePropertyBuilderProps, ValuesCountEntry } from \"../types\";\nimport { findCommonInitialStringInPath } from \"../strings\";\nimport { extractEnumFromValues } from \"../util\";\n\nconst IMAGE_EXTENSIONS = [\".jpg\", \".png\", \".webp\", \".gif\"];\nconst AUDIO_EXTENSIONS = [\".mp3\", \".ogg\", \".opus\", \".aac\"];\nconst VIDEO_EXTENSIONS = [\".avi\", \".mp4\"];\n\nconst emailRegEx = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n\n\nexport function buildStringProperty({\n totalDocsCount,\n valuesResult\n }: InferencePropertyBuilderProps): Property {\n\n let stringProperty: Property = {\n dataType: \"string\",\n\n };\n\n if (valuesResult) {\n\n const totalEntriesCount = valuesResult.values.length;\n const totalValues = Array.from(valuesResult.valuesCount.keys()).length;\n\n const config: Partial<StringProperty> = {};\n\n const probablyAURL = valuesResult.values\n .filter((value) => typeof value === \"string\" &&\n value.toString().startsWith(\"http\")).length > totalDocsCount / 3 * 2;\n if (probablyAURL) {\n config.url = true;\n }\n\n const probablyAnEmail = valuesResult.values\n .filter((value) => typeof value === \"string\" &&\n emailRegEx.test(value)).length > totalDocsCount / 3 * 2;\n if (probablyAnEmail) {\n config.email = true;\n }\n\n const probablyUserIds = valuesResult.values\n .filter((value) => typeof value === \"string\" && value.length === 28 && !value.includes(\" \"))\n .length > totalDocsCount / 3 * 2;\n if (probablyUserIds)\n config.readOnly = true;\n\n if (!probablyAnEmail &&\n !probablyAURL &&\n !probablyUserIds &&\n !probablyAURL &&\n totalValues < totalEntriesCount / 3\n ) {\n const enumValues = extractEnumFromValues(Array.from(valuesResult.valuesCount.keys()));\n\n if (Object.keys(enumValues).length > 1)\n config.enumValues = enumValues;\n }\n\n // regular string\n if (!probablyAnEmail &&\n !probablyAURL &&\n !probablyUserIds &&\n !probablyAURL &&\n !config.enumValues) {\n const fileType = probableFileType(valuesResult, totalDocsCount);\n if (fileType) {\n config.storage = {\n acceptedFiles: [fileType as FileType],\n storagePath: findCommonInitialStringInPath(valuesResult) ?? \"/\"\n };\n }\n }\n\n if (Object.keys(config).length > 0)\n stringProperty = {\n ...stringProperty,\n ...config\n };\n }\n\n return stringProperty;\n}\n\n// TODO: support returning multiple types\nfunction probableFileType(valuesCount: ValuesCountEntry, totalDocsCount: number): boolean | FileType {\n const probablyAnImage = valuesCount.values\n .filter((value) => typeof value === \"string\" &&\n IMAGE_EXTENSIONS.some((extension) => value.toString().endsWith(extension))).length > totalDocsCount / 3 * 2;\n\n const probablyAudio = valuesCount.values\n .filter((value) => typeof value === \"string\" &&\n AUDIO_EXTENSIONS.some((extension) => value.toString().endsWith(extension))).length > totalDocsCount / 3 * 2;\n\n const probablyVideo = valuesCount.values\n .filter((value) => typeof value === \"string\" &&\n VIDEO_EXTENSIONS.some((extension) => value.toString().endsWith(extension))).length > totalDocsCount / 3 * 2;\n\n const fileType: boolean | FileType = probablyAnImage\n ? \"image/*\"\n : probablyAudio\n ? \"audio/*\"\n : probablyVideo ? \"video/*\" : false;\n return fileType;\n}\n","import { PropertyValidationSchema } from \"@firecms/core\";\nimport { InferencePropertyBuilderProps } from \"../types\";\n\nexport function buildValidation({\n totalDocsCount,\n valuesResult\n }: InferencePropertyBuilderProps): PropertyValidationSchema | undefined {\n\n if (valuesResult) {\n const totalEntriesCount = valuesResult.values.length;\n if (totalDocsCount === totalEntriesCount)\n return {\n required: true\n }\n }\n\n return undefined;\n}\n","import { InferencePropertyBuilderProps } from \"../types\";\nimport { findCommonInitialStringInPath } from \"../strings\";\nimport { Property } from \"@firecms/core\";\n\nexport function buildReferenceProperty({\n totalDocsCount,\n valuesResult\n }: InferencePropertyBuilderProps): Property {\n\n const property: Property = {\n dataType: \"reference\",\n path: findCommonInitialStringInPath(valuesResult) ?? \"!!!FIX_ME!!!\"\n };\n\n return property;\n}\n","import {\n DataType,\n EnumValues,\n mergeDeep,\n Properties,\n Property,\n resolveEnumValues,\n StringProperty,\n unslugify\n} from \"@firecms/core\";\nimport {\n InferencePropertyBuilderProps,\n TypesCount,\n TypesCountRecord,\n ValuesCountEntry,\n ValuesCountRecord\n} from \"./types\";\nimport { buildStringProperty } from \"./builders/string_property_builder\";\nimport { buildValidation } from \"./builders/validation_builder\";\nimport { buildReferenceProperty } from \"./builders/reference_property_builder\";\nimport { extractEnumFromValues } from \"./util\";\n\nexport type InferenceTypeBuilder = (value: any) => DataType;\n\nexport async function buildEntityPropertiesFromData(data: object[], getType: InferenceTypeBuilder): Promise<Properties> {\n const typesCount: TypesCountRecord = {};\n const valuesCount: ValuesCountRecord = {};\n data.forEach((entry) => {\n if (entry) {\n Object.entries(entry).forEach(([key, value]) => {\n increaseMapTypeCount(typesCount, key, value, getType);\n increaseValuesCount(valuesCount, key, value, getType);\n })\n }\n });\n // console.log(util.inspect({ typesCount }, { showHidden: false, depth: null, colors: true }));\n return buildPropertiesFromCount(data.length, typesCount, valuesCount);\n}\n\nexport function buildPropertyFromData(data: any[], property: Property, getType: InferenceTypeBuilder): Property {\n const typesCount = {};\n const valuesCount: ValuesCountRecord = {};\n data.forEach((entry) => {\n increaseTypeCount(property.dataType, typesCount, entry, getType);\n increaseValuesCount(valuesCount, \"inferred_prop\", entry, getType);\n });\n const enumValues = \"enumValues\" in property ? resolveEnumValues(property[\"enumValues\"] as EnumValues) : undefined;\n if (enumValues) {\n const newEnumValues = extractEnumFromValues(Array.from(valuesCount[\"inferred_prop\"].valuesCount.keys()));\n console.log(\"newEnumValues\", newEnumValues);\n return { ...property, enumValues: [...newEnumValues, ...enumValues] } as StringProperty;\n }\n const generatedProperty = buildPropertyFromCount(\"inferred_prop\", data.length, property.dataType, typesCount, valuesCount[\"inferred_prop\"]);\n return mergeDeep(generatedProperty, property);\n}\n\nexport function buildPropertiesOrder(properties: Properties<any>): string [] {\n function propOrder(s: string) {\n const k = s.toLowerCase();\n if (k === \"title\" || k === \"name\") return 3;\n if (k.includes(\"title\") || k.includes(\"name\")) return 2;\n if (k.includes(\"image\") || k.includes(\"picture\")) return 1;\n return 0;\n }\n\n const keys = Object.keys(properties);\n keys.sort(); // alphabetically\n keys.sort((a, b) => {\n return propOrder(b) - propOrder(a);\n });\n return keys;\n}\n\n/**\n * @param type\n * @param typesCount\n * @param fieldValue\n * @param getType\n */\nfunction increaseTypeCount(type: DataType, typesCount: TypesCount, fieldValue: any, getType: InferenceTypeBuilder) {\n if (type === \"map\") {\n if (fieldValue) {\n let mapTypesCount = typesCount[type];\n if (!mapTypesCount) {\n mapTypesCount = {};\n typesCount[type] = mapTypesCount;\n }\n Object.entries(fieldValue).forEach(([key, value]) => {\n increaseMapTypeCount(mapTypesCount as TypesCountRecord, key, value, getType);\n })\n }\n } else if (type === \"array\") {\n let arrayTypesCount = typesCount[type];\n if (!arrayTypesCount) {\n arrayTypesCount = {};\n typesCount[type] = arrayTypesCount;\n }\n if (fieldValue && Array.isArray(fieldValue) && fieldValue.length > 0) {\n const arrayType = getMostProbableTypeInArray(fieldValue, getType); // get type of first element\n if (!arrayTypesCount[arrayType]) (arrayTypesCount[arrayType] as number) = 1;\n else (arrayTypesCount[arrayType] as number)++;\n }\n } else {\n if (!typesCount[type]) typesCount[type] = 1;\n else (typesCount[type] as number)++;\n }\n}\n\nfunction increaseMapTypeCount(\n typesCountRecord: TypesCountRecord,\n key: string,\n fieldValue: any,\n getType: InferenceTypeBuilder\n) {\n let typesCount: TypesCount = typesCountRecord[key];\n if (!typesCount) {\n typesCount = {};\n typesCountRecord[key] = typesCount;\n }\n\n if (fieldValue != null) { // Check that fieldValue is not null or undefined before proceeding\n const type = getType(fieldValue);\n increaseTypeCount(type, typesCount, fieldValue, getType);\n }\n}\n\nfunction increaseValuesCount(\n typeValuesRecord: ValuesCountRecord,\n key: string,\n fieldValue: any,\n getType: InferenceTypeBuilder\n) {\n\n const dataType = getType(fieldValue);\n\n let valuesRecord: {\n values: any[];\n valuesCount: Map<any, number>;\n map?: ValuesCountRecord;\n } = typeValuesRecord[key];\n\n if (!valuesRecord) {\n valuesRecord = {\n values: [],\n valuesCount: new Map()\n };\n typeValuesRecord[key] = valuesRecord;\n }\n\n if (dataType === \"map\") {\n let mapValuesRecord: ValuesCountRecord | undefined = valuesRecord.map;\n if (!mapValuesRecord) {\n mapValuesRecord = {};\n valuesRecord.map = mapValuesRecord;\n }\n if (fieldValue)\n Object.entries(fieldValue).forEach(([key, value]) => increaseValuesCount(mapValuesRecord as ValuesCountRecord, key, value, getType))\n } else if (dataType === \"array\") {\n if (Array.isArray(fieldValue)) {\n fieldValue.forEach((value) => {\n valuesRecord.values.push(value);\n valuesRecord.valuesCount.set(value, (valuesRecord.valuesCount.get(value) ?? 0) + 1);\n })\n }\n } else {\n if (fieldValue) {\n valuesRecord.values.push(fieldValue);\n valuesRecord.valuesCount.set(fieldValue, (valuesRecord.valuesCount.get(fieldValue) ?? 0) + 1);\n }\n }\n\n}\n\nfunction getHighestTypesCount(typesCount: TypesCount): number {\n let highestCount = 0;\n Object.entries(typesCount).forEach(([type, count]) => {\n let countValue = 0;\n if (type === \"map\") {\n countValue = getHighestRecordCount(count as TypesCountRecord);\n } else if (type === \"array\") {\n countValue = getHighestTypesCount(count as TypesCount);\n } else {\n countValue = count as number;\n }\n if (countValue > highestCount) {\n highestCount = countValue;\n }\n });\n\n return highestCount;\n}\n\nfunction getHighestRecordCount(record: TypesCountRecord): number {\n return Object.entries(record)\n .map(([key, typesCount]) => getHighestTypesCount(typesCount))\n .reduce((a, b) => Math.max(a, b), 0);\n}\n\nfunction getMostProbableType(typesCount: TypesCount): DataType {\n let highestCount = -1;\n let probableType: DataType = \"string\"; //default\n Object.entries(typesCount).forEach(([type, count]) => {\n let countValue;\n if (type === \"map\") {\n countValue = getHighestRecordCount(count as TypesCountRecord);\n } else if (type === \"array\") {\n countValue = getHighestTypesCount(count as TypesCount);\n } else {\n countValue = count as number;\n }\n if (countValue > highestCount) {\n highestCount = countValue;\n probableType = type as DataType;\n }\n });\n return probableType;\n}\n\nfunction buildPropertyFromCount(key: string, totalDocsCount: number, mostProbableType: DataType, typesCount: TypesCount, valuesResult?: ValuesCountEntry): Property {\n let title: string | undefined;\n\n if (key) {\n title = unslugify(key);\n }\n\n if (mostProbableType === \"map\") {\n\n const highVariability = checkTypesCountHighVariability(typesCount);\n if (highVariability) {\n return {\n dataType: \"map\",\n name: title,\n keyValue: true,\n properties: {}\n };\n }\n const properties = buildPropertiesFromCount(totalDocsCount, typesCount.map as TypesCountRecord, valuesResult ? valuesResult.mapValues : undefined);\n return {\n dataType: \"map\",\n name: title,\n properties\n };\n } else if (mostProbableType === \"array\") {\n const arrayTypesCount = typesCount.array as TypesCount;\n const arrayMostProbableType = getMostProbableType(arrayTypesCount);\n const of = buildPropertyFromCount(key, totalDocsCount, arrayMostProbableType, arrayTypesCount, valuesResult);\n return {\n dataType: \"array\",\n name: title,\n of\n };\n }\n let result: Property;\n const propertyProps: InferencePropertyBuilderProps = {\n name: key,\n totalDocsCount,\n valuesResult\n };\n if (mostProbableType === \"string\") {\n result = buildStringProperty(propertyProps);\n } else if (mostProbableType === \"reference\") {\n result = buildReferenceProperty(propertyProps);\n } else {\n result = {\n dataType: mostProbableType,\n\n } as Property;\n }\n\n if (title) {\n result.name = title;\n }\n\n const validation = buildValidation(propertyProps);\n if (validation) {\n result.validation = validation;\n }\n\n return result;\n}\n\nfunction buildPropertiesFromCount(totalDocsCount: number, typesCountRecord: TypesCountRecord, valuesCountRecord?: ValuesCountRecord): Properties {\n const res: Properties = {};\n Object.entries(typesCountRecord).forEach(([key, typesCount]) => {\n const mostProbableType = getMostProbableType(typesCount);\n res[key] = buildPropertyFromCount(key, totalDocsCount, mostProbableType, typesCount, valuesCountRecord ? valuesCountRecord[key] : undefined);\n })\n return res;\n}\n\nfunction countMaxDocumentsUnder(typesCount: TypesCount) {\n let count = 0;\n Object.entries(typesCount).forEach(([type, value]) => {\n // console.log(util.inspect({ type, value }, { showHidden: false, depth: null, colors: true }));\n if (typeof value === \"object\") {\n count = Math.max(count, countMaxDocumentsUnder(value as TypesCountRecord));\n } else {\n count = Math.max(count, value as number);\n }\n });\n return count;\n}\n\nfunction getMostProbableTypeInArray(array: any[], getType: InferenceTypeBuilder): DataType {\n let typesCount: TypesCount = {};\n array.forEach((value) => {\n increaseTypeCount(getType(value), typesCount, value, getType);\n });\n return getMostProbableType(typesCount);\n}\n\nfunction checkTypesCountHighVariability(typesCount: TypesCount) {\n const maxCount = countMaxDocumentsUnder(typesCount);\n let keysWithFewValues = 0;\n Object.entries(typesCount.map ?? {})\n .forEach(([key, value]) => {\n const count = countMaxDocumentsUnder(value);\n if (count < maxCount / 3) {\n keysWithFewValues++;\n }\n });\n return keysWithFewValues / Object.entries(typesCount.map ?? {}).length > 0.5;\n}\n\n"],"names":["findCommonInitialStringInPath","valuesCount","getPath","value","DocumentReference","pathWithSlash","v","s","searchedPath","path","extractEnumFromValues","values","enumValues","unslugify","a","b","IMAGE_EXTENSIONS","AUDIO_EXTENSIONS","VIDEO_EXTENSIONS","emailRegEx","buildStringProperty","totalDocsCount","valuesResult","stringProperty","totalEntriesCount","totalValues","config","probablyAURL","probablyAnEmail","probablyUserIds","fileType","probableFileType","probablyAnImage","extension","probablyAudio","probablyVideo","buildValidation","buildReferenceProperty","buildEntityPropertiesFromData","data","getType","typesCount","entry","key","increaseMapTypeCount","increaseValuesCount","buildPropertiesFromCount","buildPropertyFromData","property","increaseTypeCount","resolveEnumValues","newEnumValues","generatedProperty","buildPropertyFromCount","mergeDeep","buildPropertiesOrder","properties","propOrder","k","keys","type","fieldValue","mapTypesCount","arrayTypesCount","arrayType","getMostProbableTypeInArray","typesCountRecord","typeValuesRecord","dataType","valuesRecord","mapValuesRecord","getHighestTypesCount","highestCount","count","countValue","getHighestRecordCount","record","getMostProbableType","probableType","mostProbableType","title","checkTypesCountHighVariability","arrayMostProbableType","of","result","propertyProps","validation","valuesCountRecord","res","countMaxDocumentsUnder","array","maxCount","keysWithFewValues"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ (function(c,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("@firecms/core"),require("firebase/firestore")):typeof define=="function"&&define.amd?define(["exports","@firecms/core","firebase/firestore"],u):(c=typeof globalThis<"u"?globalThis:c||self,u(c.FireCMS={},c.core,c.firestore))})(this,function(c,u,j){"use strict";function O(r){if(!r)return;function e(o){return typeof o=="string"?o:o instanceof j.DocumentReference?o.path:void 0}const s=r.values.map(o=>e(o)).filter(o=>!!o).find(o=>o.includes("/"));if(!s)return;const n=s.substr(0,s.lastIndexOf("/"));return r.values.filter(o=>{const a=e(o);return a?a.startsWith(n):!1}).length>r.values.length/3*2?n:void 0}function p(r){const e=r.map(t=>({id:t,label:u.unslugify(t)}));return e.sort((t,s)=>t.label.localeCompare(s.label)),e}const S=[".jpg",".png",".webp",".gif"],F=[".mp3",".ogg",".opus",".aac"],I=[".avi",".mp4"],M=/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;function V({totalDocsCount:r,valuesResult:e}){let t={dataType:"string"};if(e){const s=e.values.length,n=Array.from(e.valuesCount.keys()).length,i={},o=e.values.filter(f=>typeof f=="string"&&f.toString().startsWith("http")).length>r/3*2;o&&(i.url=!0);const a=e.values.filter(f=>typeof f=="string"&&M.test(f)).length>r/3*2;a&&(i.email=!0);const l=e.values.filter(f=>typeof f=="string"&&f.length===28&&!f.includes(" ")).length>r/3*2;if(l&&(i.readOnly=!0),!a&&!o&&!l&&!o&&n<s/3){const f=p(Array.from(e.valuesCount.keys()));Object.keys(f).length>1&&(i.enumValues=f)}if(!a&&!o&&!l&&!o&&!i.enumValues){const f=C(e,r);f&&(i.storage={acceptedFiles:[f],storagePath:O(e)??"/"})}Object.keys(i).length>0&&(t={...t,...i})}return t}function C(r,e){const t=r.values.filter(o=>typeof o=="string"&&S.some(a=>o.toString().endsWith(a))).length>e/3*2,s=r.values.filter(o=>typeof o=="string"&&F.some(a=>o.toString().endsWith(a))).length>e/3*2,n=r.values.filter(o=>typeof o=="string"&&I.some(a=>o.toString().endsWith(a))).length>e/3*2;return t?"image/*":s?"audio/*":n?"video/*":!1}function _({totalDocsCount:r,valuesResult:e}){if(e){const t=e.values.length;if(r===t)return{required:!0}}}function x({totalDocsCount:r,valuesResult:e}){return{dataType:"reference",path:O(e)??"!!!FIX_ME!!!"}}async function z(r,e){const t={},s={};return r.forEach(n=>{n&&Object.entries(n).forEach(([i,o])=>{T(t,i,o,e),h(s,i,o,e)})}),P(r.length,t,s)}function W(r,e,t){const s={},n={};r.forEach(a=>{m(e.dataType,s,a,t),h(n,"inferred_prop",a,t)});const i="enumValues"in e?u.resolveEnumValues(e.enumValues):void 0;if(i){const a=p(Array.from(n.inferred_prop.valuesCount.keys()));return console.log("newEnumValues",a),{...e,enumValues:[...a,...i]}}const o=b("inferred_prop",r.length,e.dataType,s,n.inferred_prop);return u.mergeDeep(o,e)}function Z(r){function e(s){const n=s.toLowerCase();return n==="title"||n==="name"?3:n.includes("title")||n.includes("name")?2:n.includes("image")||n.includes("picture")?1:0}const t=Object.keys(r);return t.sort(),t.sort((s,n)=>e(n)-e(s)),t}function m(r,e,t,s){if(r==="map"){if(t){let n=e[r];n||(n={},e[r]=n),Object.entries(t).forEach(([i,o])=>{T(n,i,o,s)})}}else if(r==="array"){let n=e[r];if(n||(n={},e[r]=n),t&&Array.isArray(t)&&t.length>0){const i=w(t,s);n[i]?n[i]++:n[i]=1}}else e[r]?e[r]++:e[r]=1}function T(r,e,t,s){let n=r[e];if(n||(n={},r[e]=n),t!=null){const i=s(t);m(i,n,t,s)}}function h(r,e,t,s){const n=s(t);let i=r[e];if(i||(i={values:[],valuesCount:new Map},r[e]=i),n==="map"){let o=i.map;o||(o={},i.map=o),t&&Object.entries(t).forEach(([a,l])=>h(o,a,l,s))}else n==="array"?Array.isArray(t)&&t.forEach(o=>{i.values.push(o),i.valuesCount.set(o,(i.valuesCount.get(o)??0)+1)}):t&&(i.values.push(t),i.valuesCount.set(t,(i.valuesCount.get(t)??0)+1))}function g(r){let e=0;return Object.entries(r).forEach(([t,s])=>{let n=0;t==="map"?n=A(s):t==="array"?n=g(s):n=s,n>e&&(e=n)}),e}function A(r){return Object.entries(r).map(([e,t])=>g(t)).reduce((e,t)=>Math.max(e,t),0)}function d(r){let e=-1,t="string";return Object.entries(r).forEach(([s,n])=>{let i;s==="map"?i=A(n):s==="array"?i=g(n):i=n,i>e&&(e=i,t=s)}),t}function b(r,e,t,s,n){let i;if(r&&(i=u.unslugify(r)),t==="map"){if(N(s))return{dataType:"map",name:i,keyValue:!0,properties:{}};const E=P(e,s.map,n?n.mapValues:void 0);return{dataType:"map",name:i,properties:E}}else if(t==="array"){const f=s.array,E=d(f),k=b(r,e,E,f,n);return{dataType:"array",name:i,of:k}}let o;const a={name:r,totalDocsCount:e,valuesResult:n};t==="string"?o=V(a):t==="reference"?o=x(a):o={dataType:t},i&&(o.name=i);const l=_(a);return l&&(o.validation=l),o}function P(r,e,t){const s={};return Object.entries(e).forEach(([n,i])=>{const o=d(i);s[n]=b(n,r,o,i,t?t[n]:void 0)}),s}function y(r){let e=0;return Object.entries(r).forEach(([t,s])=>{typeof s=="object"?e=Math.max(e,y(s)):e=Math.max(e,s)}),e}function w(r,e){let t={};return r.forEach(s=>{m(e(s),t,s,e)}),d(t)}function N(r){const e=y(r);let t=0;return Object.entries(r.map??{}).forEach(([s,n])=>{y(n)<e/3&&t++}),t/Object.entries(r.map??{}).length>.5}c.buildEntityPropertiesFromData=z,c.buildPropertiesOrder=Z,c.buildPropertyFromData=W,c.extractEnumFromValues=p,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})});
2
+ //# sourceMappingURL=index.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/strings.ts","../src/util.ts","../src/builders/string_property_builder.ts","../src/builders/validation_builder.ts","../src/builders/reference_property_builder.ts","../src/collection_builder.ts"],"sourcesContent":["import { ValuesCountEntry } from \"./types\";\nimport { DocumentReference } from \"firebase/firestore\";\n\n\nexport function findCommonInitialStringInPath(valuesCount?: ValuesCountEntry) {\n\n if (!valuesCount) return undefined;\n\n function getPath(value: any) {\n if (typeof value === \"string\") return value;\n else if (value instanceof DocumentReference) return value.path;\n else return undefined;\n }\n\n const strings: string[] = valuesCount.values.map((v) => getPath(v)).filter(v => !!v) as string[];\n const pathWithSlash = strings.find((s) => s.includes(\"/\"));\n if (!pathWithSlash)\n return undefined;\n\n const searchedPath = pathWithSlash.substr(0, pathWithSlash.lastIndexOf(\"/\"));\n\n const yep = valuesCount.values\n .filter((value) => {\n const path = getPath(value);\n if (!path) return false;\n return path.startsWith(searchedPath)\n }).length > valuesCount.values.length / 3 * 2;\n\n return yep ? searchedPath : undefined;\n\n}\n\nexport function removeInitialAndTrailingSlashes(s: string): string {\n return removeInitialSlash(removeTrailingSlash(s));\n}\n\nexport function removeInitialSlash(s: string) {\n if (s.startsWith(\"/\"))\n return s.slice(1);\n else return s;\n}\n\nexport function removeTrailingSlash(s: string) {\n if (s.endsWith(\"/\"))\n return s.slice(0, -1);\n else return s;\n}\n","import { unslugify } from \"@firecms/core\";\n\nexport function extractEnumFromValues(values: string[]) {\n const enumValues = values\n .map((value) => ({ id: value, label: unslugify(value) }));\n enumValues.sort((a, b) => a.label.localeCompare(b.label));\n return enumValues;\n}\n","import { FileType, Property, StringProperty, unslugify } from \"@firecms/core\";\nimport { InferencePropertyBuilderProps, ValuesCountEntry } from \"../types\";\nimport { findCommonInitialStringInPath } from \"../strings\";\nimport { extractEnumFromValues } from \"../util\";\n\nconst IMAGE_EXTENSIONS = [\".jpg\", \".png\", \".webp\", \".gif\"];\nconst AUDIO_EXTENSIONS = [\".mp3\", \".ogg\", \".opus\", \".aac\"];\nconst VIDEO_EXTENSIONS = [\".avi\", \".mp4\"];\n\nconst emailRegEx = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n\n\nexport function buildStringProperty({\n totalDocsCount,\n valuesResult\n }: InferencePropertyBuilderProps): Property {\n\n let stringProperty: Property = {\n dataType: \"string\",\n\n };\n\n if (valuesResult) {\n\n const totalEntriesCount = valuesResult.values.length;\n const totalValues = Array.from(valuesResult.valuesCount.keys()).length;\n\n const config: Partial<StringProperty> = {};\n\n const probablyAURL = valuesResult.values\n .filter((value) => typeof value === \"string\" &&\n value.toString().startsWith(\"http\")).length > totalDocsCount / 3 * 2;\n if (probablyAURL) {\n config.url = true;\n }\n\n const probablyAnEmail = valuesResult.values\n .filter((value) => typeof value === \"string\" &&\n emailRegEx.test(value)).length > totalDocsCount / 3 * 2;\n if (probablyAnEmail) {\n config.email = true;\n }\n\n const probablyUserIds = valuesResult.values\n .filter((value) => typeof value === \"string\" && value.length === 28 && !value.includes(\" \"))\n .length > totalDocsCount / 3 * 2;\n if (probablyUserIds)\n config.readOnly = true;\n\n if (!probablyAnEmail &&\n !probablyAURL &&\n !probablyUserIds &&\n !probablyAURL &&\n totalValues < totalEntriesCount / 3\n ) {\n const enumValues = extractEnumFromValues(Array.from(valuesResult.valuesCount.keys()));\n\n if (Object.keys(enumValues).length > 1)\n config.enumValues = enumValues;\n }\n\n // regular string\n if (!probablyAnEmail &&\n !probablyAURL &&\n !probablyUserIds &&\n !probablyAURL &&\n !config.enumValues) {\n const fileType = probableFileType(valuesResult, totalDocsCount);\n if (fileType) {\n config.storage = {\n acceptedFiles: [fileType as FileType],\n storagePath: findCommonInitialStringInPath(valuesResult) ?? \"/\"\n };\n }\n }\n\n if (Object.keys(config).length > 0)\n stringProperty = {\n ...stringProperty,\n ...config\n };\n }\n\n return stringProperty;\n}\n\n// TODO: support returning multiple types\nfunction probableFileType(valuesCount: ValuesCountEntry, totalDocsCount: number): boolean | FileType {\n const probablyAnImage = valuesCount.values\n .filter((value) => typeof value === \"string\" &&\n IMAGE_EXTENSIONS.some((extension) => value.toString().endsWith(extension))).length > totalDocsCount / 3 * 2;\n\n const probablyAudio = valuesCount.values\n .filter((value) => typeof value === \"string\" &&\n AUDIO_EXTENSIONS.some((extension) => value.toString().endsWith(extension))).length > totalDocsCount / 3 * 2;\n\n const probablyVideo = valuesCount.values\n .filter((value) => typeof value === \"string\" &&\n VIDEO_EXTENSIONS.some((extension) => value.toString().endsWith(extension))).length > totalDocsCount / 3 * 2;\n\n const fileType: boolean | FileType = probablyAnImage\n ? \"image/*\"\n : probablyAudio\n ? \"audio/*\"\n : probablyVideo ? \"video/*\" : false;\n return fileType;\n}\n","import { PropertyValidationSchema } from \"@firecms/core\";\nimport { InferencePropertyBuilderProps } from \"../types\";\n\nexport function buildValidation({\n totalDocsCount,\n valuesResult\n }: InferencePropertyBuilderProps): PropertyValidationSchema | undefined {\n\n if (valuesResult) {\n const totalEntriesCount = valuesResult.values.length;\n if (totalDocsCount === totalEntriesCount)\n return {\n required: true\n }\n }\n\n return undefined;\n}\n","import { InferencePropertyBuilderProps } from \"../types\";\nimport { findCommonInitialStringInPath } from \"../strings\";\nimport { Property } from \"@firecms/core\";\n\nexport function buildReferenceProperty({\n totalDocsCount,\n valuesResult\n }: InferencePropertyBuilderProps): Property {\n\n const property: Property = {\n dataType: \"reference\",\n path: findCommonInitialStringInPath(valuesResult) ?? \"!!!FIX_ME!!!\"\n };\n\n return property;\n}\n","import {\n DataType,\n EnumValues,\n mergeDeep,\n Properties,\n Property,\n resolveEnumValues,\n StringProperty,\n unslugify\n} from \"@firecms/core\";\nimport {\n InferencePropertyBuilderProps,\n TypesCount,\n TypesCountRecord,\n ValuesCountEntry,\n ValuesCountRecord\n} from \"./types\";\nimport { buildStringProperty } from \"./builders/string_property_builder\";\nimport { buildValidation } from \"./builders/validation_builder\";\nimport { buildReferenceProperty } from \"./builders/reference_property_builder\";\nimport { extractEnumFromValues } from \"./util\";\n\nexport type InferenceTypeBuilder = (value: any) => DataType;\n\nexport async function buildEntityPropertiesFromData(data: object[], getType: InferenceTypeBuilder): Promise<Properties> {\n const typesCount: TypesCountRecord = {};\n const valuesCount: ValuesCountRecord = {};\n data.forEach((entry) => {\n if (entry) {\n Object.entries(entry).forEach(([key, value]) => {\n increaseMapTypeCount(typesCount, key, value, getType);\n increaseValuesCount(valuesCount, key, value, getType);\n })\n }\n });\n // console.log(util.inspect({ typesCount }, { showHidden: false, depth: null, colors: true }));\n return buildPropertiesFromCount(data.length, typesCount, valuesCount);\n}\n\nexport function buildPropertyFromData(data: any[], property: Property, getType: InferenceTypeBuilder): Property {\n const typesCount = {};\n const valuesCount: ValuesCountRecord = {};\n data.forEach((entry) => {\n increaseTypeCount(property.dataType, typesCount, entry, getType);\n increaseValuesCount(valuesCount, \"inferred_prop\", entry, getType);\n });\n const enumValues = \"enumValues\" in property ? resolveEnumValues(property[\"enumValues\"] as EnumValues) : undefined;\n if (enumValues) {\n const newEnumValues = extractEnumFromValues(Array.from(valuesCount[\"inferred_prop\"].valuesCount.keys()));\n console.log(\"newEnumValues\", newEnumValues);\n return { ...property, enumValues: [...newEnumValues, ...enumValues] } as StringProperty;\n }\n const generatedProperty = buildPropertyFromCount(\"inferred_prop\", data.length, property.dataType, typesCount, valuesCount[\"inferred_prop\"]);\n return mergeDeep(generatedProperty, property);\n}\n\nexport function buildPropertiesOrder(properties: Properties<any>): string [] {\n function propOrder(s: string) {\n const k = s.toLowerCase();\n if (k === \"title\" || k === \"name\") return 3;\n if (k.includes(\"title\") || k.includes(\"name\")) return 2;\n if (k.includes(\"image\") || k.includes(\"picture\")) return 1;\n return 0;\n }\n\n const keys = Object.keys(properties);\n keys.sort(); // alphabetically\n keys.sort((a, b) => {\n return propOrder(b) - propOrder(a);\n });\n return keys;\n}\n\n/**\n * @param type\n * @param typesCount\n * @param fieldValue\n * @param getType\n */\nfunction increaseTypeCount(type: DataType, typesCount: TypesCount, fieldValue: any, getType: InferenceTypeBuilder) {\n if (type === \"map\") {\n if (fieldValue) {\n let mapTypesCount = typesCount[type];\n if (!mapTypesCount) {\n mapTypesCount = {};\n typesCount[type] = mapTypesCount;\n }\n Object.entries(fieldValue).forEach(([key, value]) => {\n increaseMapTypeCount(mapTypesCount as TypesCountRecord, key, value, getType);\n })\n }\n } else if (type === \"array\") {\n let arrayTypesCount = typesCount[type];\n if (!arrayTypesCount) {\n arrayTypesCount = {};\n typesCount[type] = arrayTypesCount;\n }\n if (fieldValue && Array.isArray(fieldValue) && fieldValue.length > 0) {\n const arrayType = getMostProbableTypeInArray(fieldValue, getType); // get type of first element\n if (!arrayTypesCount[arrayType]) (arrayTypesCount[arrayType] as number) = 1;\n else (arrayTypesCount[arrayType] as number)++;\n }\n } else {\n if (!typesCount[type]) typesCount[type] = 1;\n else (typesCount[type] as number)++;\n }\n}\n\nfunction increaseMapTypeCount(\n typesCountRecord: TypesCountRecord,\n key: string,\n fieldValue: any,\n getType: InferenceTypeBuilder\n) {\n let typesCount: TypesCount = typesCountRecord[key];\n if (!typesCount) {\n typesCount = {};\n typesCountRecord[key] = typesCount;\n }\n\n if (fieldValue != null) { // Check that fieldValue is not null or undefined before proceeding\n const type = getType(fieldValue);\n increaseTypeCount(type, typesCount, fieldValue, getType);\n }\n}\n\nfunction increaseValuesCount(\n typeValuesRecord: ValuesCountRecord,\n key: string,\n fieldValue: any,\n getType: InferenceTypeBuilder\n) {\n\n const dataType = getType(fieldValue);\n\n let valuesRecord: {\n values: any[];\n valuesCount: Map<any, number>;\n map?: ValuesCountRecord;\n } = typeValuesRecord[key];\n\n if (!valuesRecord) {\n valuesRecord = {\n values: [],\n valuesCount: new Map()\n };\n typeValuesRecord[key] = valuesRecord;\n }\n\n if (dataType === \"map\") {\n let mapValuesRecord: ValuesCountRecord | undefined = valuesRecord.map;\n if (!mapValuesRecord) {\n mapValuesRecord = {};\n valuesRecord.map = mapValuesRecord;\n }\n if (fieldValue)\n Object.entries(fieldValue).forEach(([key, value]) => increaseValuesCount(mapValuesRecord as ValuesCountRecord, key, value, getType))\n } else if (dataType === \"array\") {\n if (Array.isArray(fieldValue)) {\n fieldValue.forEach((value) => {\n valuesRecord.values.push(value);\n valuesRecord.valuesCount.set(value, (valuesRecord.valuesCount.get(value) ?? 0) + 1);\n })\n }\n } else {\n if (fieldValue) {\n valuesRecord.values.push(fieldValue);\n valuesRecord.valuesCount.set(fieldValue, (valuesRecord.valuesCount.get(fieldValue) ?? 0) + 1);\n }\n }\n\n}\n\nfunction getHighestTypesCount(typesCount: TypesCount): number {\n let highestCount = 0;\n Object.entries(typesCount).forEach(([type, count]) => {\n let countValue = 0;\n if (type === \"map\") {\n countValue = getHighestRecordCount(count as TypesCountRecord);\n } else if (type === \"array\") {\n countValue = getHighestTypesCount(count as TypesCount);\n } else {\n countValue = count as number;\n }\n if (countValue > highestCount) {\n highestCount = countValue;\n }\n });\n\n return highestCount;\n}\n\nfunction getHighestRecordCount(record: TypesCountRecord): number {\n return Object.entries(record)\n .map(([key, typesCount]) => getHighestTypesCount(typesCount))\n .reduce((a, b) => Math.max(a, b), 0);\n}\n\nfunction getMostProbableType(typesCount: TypesCount): DataType {\n let highestCount = -1;\n let probableType: DataType = \"string\"; //default\n Object.entries(typesCount).forEach(([type, count]) => {\n let countValue;\n if (type === \"map\") {\n countValue = getHighestRecordCount(count as TypesCountRecord);\n } else if (type === \"array\") {\n countValue = getHighestTypesCount(count as TypesCount);\n } else {\n countValue = count as number;\n }\n if (countValue > highestCount) {\n highestCount = countValue;\n probableType = type as DataType;\n }\n });\n return probableType;\n}\n\nfunction buildPropertyFromCount(key: string, totalDocsCount: number, mostProbableType: DataType, typesCount: TypesCount, valuesResult?: ValuesCountEntry): Property {\n let title: string | undefined;\n\n if (key) {\n title = unslugify(key);\n }\n\n if (mostProbableType === \"map\") {\n\n const highVariability = checkTypesCountHighVariability(typesCount);\n if (highVariability) {\n return {\n dataType: \"map\",\n name: title,\n keyValue: true,\n properties: {}\n };\n }\n const properties = buildPropertiesFromCount(totalDocsCount, typesCount.map as TypesCountRecord, valuesResult ? valuesResult.mapValues : undefined);\n return {\n dataType: \"map\",\n name: title,\n properties\n };\n } else if (mostProbableType === \"array\") {\n const arrayTypesCount = typesCount.array as TypesCount;\n const arrayMostProbableType = getMostProbableType(arrayTypesCount);\n const of = buildPropertyFromCount(key, totalDocsCount, arrayMostProbableType, arrayTypesCount, valuesResult);\n return {\n dataType: \"array\",\n name: title,\n of\n };\n }\n let result: Property;\n const propertyProps: InferencePropertyBuilderProps = {\n name: key,\n totalDocsCount,\n valuesResult\n };\n if (mostProbableType === \"string\") {\n result = buildStringProperty(propertyProps);\n } else if (mostProbableType === \"reference\") {\n result = buildReferenceProperty(propertyProps);\n } else {\n result = {\n dataType: mostProbableType,\n\n } as Property;\n }\n\n if (title) {\n result.name = title;\n }\n\n const validation = buildValidation(propertyProps);\n if (validation) {\n result.validation = validation;\n }\n\n return result;\n}\n\nfunction buildPropertiesFromCount(totalDocsCount: number, typesCountRecord: TypesCountRecord, valuesCountRecord?: ValuesCountRecord): Properties {\n const res: Properties = {};\n Object.entries(typesCountRecord).forEach(([key, typesCount]) => {\n const mostProbableType = getMostProbableType(typesCount);\n res[key] = buildPropertyFromCount(key, totalDocsCount, mostProbableType, typesCount, valuesCountRecord ? valuesCountRecord[key] : undefined);\n })\n return res;\n}\n\nfunction countMaxDocumentsUnder(typesCount: TypesCount) {\n let count = 0;\n Object.entries(typesCount).forEach(([type, value]) => {\n // console.log(util.inspect({ type, value }, { showHidden: false, depth: null, colors: true }));\n if (typeof value === \"object\") {\n count = Math.max(count, countMaxDocumentsUnder(value as TypesCountRecord));\n } else {\n count = Math.max(count, value as number);\n }\n });\n return count;\n}\n\nfunction getMostProbableTypeInArray(array: any[], getType: InferenceTypeBuilder): DataType {\n let typesCount: TypesCount = {};\n array.forEach((value) => {\n increaseTypeCount(getType(value), typesCount, value, getType);\n });\n return getMostProbableType(typesCount);\n}\n\nfunction checkTypesCountHighVariability(typesCount: TypesCount) {\n const maxCount = countMaxDocumentsUnder(typesCount);\n let keysWithFewValues = 0;\n Object.entries(typesCount.map ?? {})\n .forEach(([key, value]) => {\n const count = countMaxDocumentsUnder(value);\n if (count < maxCount / 3) {\n keysWithFewValues++;\n }\n });\n return keysWithFewValues / Object.entries(typesCount.map ?? {}).length > 0.5;\n}\n\n"],"names":["findCommonInitialStringInPath","valuesCount","getPath","value","DocumentReference","pathWithSlash","v","s","searchedPath","path","extractEnumFromValues","values","enumValues","unslugify","a","b","IMAGE_EXTENSIONS","AUDIO_EXTENSIONS","VIDEO_EXTENSIONS","emailRegEx","buildStringProperty","totalDocsCount","valuesResult","stringProperty","totalEntriesCount","totalValues","config","probablyAURL","probablyAnEmail","probablyUserIds","fileType","probableFileType","probablyAnImage","extension","probablyAudio","probablyVideo","buildValidation","buildReferenceProperty","buildEntityPropertiesFromData","data","getType","typesCount","entry","key","increaseMapTypeCount","increaseValuesCount","buildPropertiesFromCount","buildPropertyFromData","property","increaseTypeCount","resolveEnumValues","newEnumValues","generatedProperty","buildPropertyFromCount","mergeDeep","buildPropertiesOrder","properties","propOrder","k","keys","type","fieldValue","mapTypesCount","arrayTypesCount","arrayType","getMostProbableTypeInArray","typesCountRecord","typeValuesRecord","dataType","valuesRecord","mapValuesRecord","getHighestTypesCount","highestCount","count","countValue","getHighestRecordCount","record","getMostProbableType","probableType","mostProbableType","title","checkTypesCountHighVariability","arrayMostProbableType","of","result","propertyProps","validation","valuesCountRecord","res","countMaxDocumentsUnder","array","maxCount","keysWithFewValues"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { ValuesCountEntry } from "./types";
2
+ export declare function findCommonInitialStringInPath(valuesCount?: ValuesCountEntry): string | undefined;
3
+ export declare function removeInitialAndTrailingSlashes(s: string): string;
4
+ export declare function removeInitialSlash(s: string): string;
5
+ export declare function removeTrailingSlash(s: string): string;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,40 +1,32 @@
1
1
  import { DataType } from "@firecms/core";
2
-
3
2
  export type TypesCount = {
4
- number?: number,
5
- string?: number,
6
- boolean?: number,
7
- map?: TypesCountRecord,
8
- array?: TypesCount,
9
- date?: number,
10
- geopoint?: number,
11
- reference?: number
3
+ number?: number;
4
+ string?: number;
5
+ boolean?: number;
6
+ map?: TypesCountRecord;
7
+ array?: TypesCount;
8
+ date?: number;
9
+ geopoint?: number;
10
+ reference?: number;
12
11
  };
13
-
14
12
  export type TypesCountRecord<K extends keyof DataType = any> = {
15
- [P in K]: TypesCount
13
+ [P in K]: TypesCount;
16
14
  };
17
-
18
15
  export type ValuesCountEntry = {
19
16
  values: any[];
20
17
  valuesCount: Map<any, number>;
21
18
  mapValues?: ValuesCountRecord;
22
19
  };
23
-
24
20
  export type ValuesCountRecord = Record<string, ValuesCountEntry>;
25
-
26
21
  export type InferencePropertyBuilderProps = {
27
-
28
22
  /**
29
23
  * Name of the property
30
24
  */
31
25
  name: string;
32
-
33
26
  /**
34
27
  * Total documents this props are built from
35
28
  */
36
29
  totalDocsCount: number;
37
-
38
30
  /**
39
31
  * How many times does each value show up
40
32
  */
package/dist/util.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare function extractEnumFromValues(values: string[]): {
2
+ id: string;
3
+ label: string;
4
+ }[];
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.0.0-alpha.15",
2
+ "version": "3.0.0-alpha.16",
3
3
  "name": "@firecms/schema_inference",
4
4
  "access": "public",
5
5
  "packageManager": "yarn@3.2.3",
@@ -15,13 +15,16 @@
15
15
  }
16
16
  },
17
17
  "dependencies": {
18
- "@firecms/core": "^3.0.0-alpha.15",
18
+ "@firecms/core": "^3.0.0-alpha.16",
19
19
  "@types/node": "^20.8.9",
20
20
  "typescript": "^5.2.2"
21
21
  },
22
+ "files": [
23
+ "dist"
24
+ ],
22
25
  "scripts": {
23
26
  "dev": "vite",
24
27
  "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json"
25
28
  },
26
- "gitHead": "f94cd1f1f796c317827ca3afdbcf504a40647986"
29
+ "gitHead": "d9e03bdd4b54f0ff2f5a221d03ffbe84dc4ca97f"
27
30
  }
@@ -1,16 +0,0 @@
1
- import { InferencePropertyBuilderProps } from "../types";
2
- import { findCommonInitialStringInPath } from "../strings";
3
- import { Property } from "@firecms/core";
4
-
5
- export function buildReferenceProperty({
6
- totalDocsCount,
7
- valuesResult
8
- }: InferencePropertyBuilderProps): Property {
9
-
10
- const property: Property = {
11
- dataType: "reference",
12
- path: findCommonInitialStringInPath(valuesResult) ?? "!!!FIX_ME!!!"
13
- };
14
-
15
- return property;
16
- }
@@ -1,107 +0,0 @@
1
- import { FileType, Property, StringProperty, unslugify } from "@firecms/core";
2
- import { InferencePropertyBuilderProps, ValuesCountEntry } from "../types";
3
- import { findCommonInitialStringInPath } from "../strings";
4
- import { extractEnumFromValues } from "../util";
5
-
6
- const IMAGE_EXTENSIONS = [".jpg", ".png", ".webp", ".gif"];
7
- const AUDIO_EXTENSIONS = [".mp3", ".ogg", ".opus", ".aac"];
8
- const VIDEO_EXTENSIONS = [".avi", ".mp4"];
9
-
10
- const emailRegEx = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
11
-
12
-
13
- export function buildStringProperty({
14
- totalDocsCount,
15
- valuesResult
16
- }: InferencePropertyBuilderProps): Property {
17
-
18
- let stringProperty: Property = {
19
- dataType: "string",
20
-
21
- };
22
-
23
- if (valuesResult) {
24
-
25
- const totalEntriesCount = valuesResult.values.length;
26
- const totalValues = Array.from(valuesResult.valuesCount.keys()).length;
27
-
28
- const config: Partial<StringProperty> = {};
29
-
30
- const probablyAURL = valuesResult.values
31
- .filter((value) => typeof value === "string" &&
32
- value.toString().startsWith("http")).length > totalDocsCount / 3 * 2;
33
- if (probablyAURL) {
34
- config.url = true;
35
- }
36
-
37
- const probablyAnEmail = valuesResult.values
38
- .filter((value) => typeof value === "string" &&
39
- emailRegEx.test(value)).length > totalDocsCount / 3 * 2;
40
- if (probablyAnEmail) {
41
- config.email = true;
42
- }
43
-
44
- const probablyUserIds = valuesResult.values
45
- .filter((value) => typeof value === "string" && value.length === 28 && !value.includes(" "))
46
- .length > totalDocsCount / 3 * 2;
47
- if (probablyUserIds)
48
- config.readOnly = true;
49
-
50
- if (!probablyAnEmail &&
51
- !probablyAURL &&
52
- !probablyUserIds &&
53
- !probablyAURL &&
54
- totalValues < totalEntriesCount / 3
55
- ) {
56
- const enumValues = extractEnumFromValues(Array.from(valuesResult.valuesCount.keys()));
57
-
58
- if (Object.keys(enumValues).length > 1)
59
- config.enumValues = enumValues;
60
- }
61
-
62
- // regular string
63
- if (!probablyAnEmail &&
64
- !probablyAURL &&
65
- !probablyUserIds &&
66
- !probablyAURL &&
67
- !config.enumValues) {
68
- const fileType = probableFileType(valuesResult, totalDocsCount);
69
- if (fileType) {
70
- config.storage = {
71
- acceptedFiles: [fileType as FileType],
72
- storagePath: findCommonInitialStringInPath(valuesResult) ?? "/"
73
- };
74
- }
75
- }
76
-
77
- if (Object.keys(config).length > 0)
78
- stringProperty = {
79
- ...stringProperty,
80
- ...config
81
- };
82
- }
83
-
84
- return stringProperty;
85
- }
86
-
87
- // TODO: support returning multiple types
88
- function probableFileType(valuesCount: ValuesCountEntry, totalDocsCount: number): boolean | FileType {
89
- const probablyAnImage = valuesCount.values
90
- .filter((value) => typeof value === "string" &&
91
- IMAGE_EXTENSIONS.some((extension) => value.toString().endsWith(extension))).length > totalDocsCount / 3 * 2;
92
-
93
- const probablyAudio = valuesCount.values
94
- .filter((value) => typeof value === "string" &&
95
- AUDIO_EXTENSIONS.some((extension) => value.toString().endsWith(extension))).length > totalDocsCount / 3 * 2;
96
-
97
- const probablyVideo = valuesCount.values
98
- .filter((value) => typeof value === "string" &&
99
- VIDEO_EXTENSIONS.some((extension) => value.toString().endsWith(extension))).length > totalDocsCount / 3 * 2;
100
-
101
- const fileType: boolean | FileType = probablyAnImage
102
- ? "image/*"
103
- : probablyAudio
104
- ? "audio/*"
105
- : probablyVideo ? "video/*" : false;
106
- return fileType;
107
- }
@@ -1,18 +0,0 @@
1
- import { PropertyValidationSchema } from "@firecms/core";
2
- import { InferencePropertyBuilderProps } from "../types";
3
-
4
- export function buildValidation({
5
- totalDocsCount,
6
- valuesResult
7
- }: InferencePropertyBuilderProps): PropertyValidationSchema | undefined {
8
-
9
- if (valuesResult) {
10
- const totalEntriesCount = valuesResult.values.length;
11
- if (totalDocsCount === totalEntriesCount)
12
- return {
13
- required: true
14
- }
15
- }
16
-
17
- return undefined;
18
- }