firestore-dart-generator 1.0.0-beta.1
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/CONFIG_FILE_GUIDE.md +445 -0
- package/IMPLEMENTATION_SUMMARY.md +305 -0
- package/LICENSE +22 -0
- package/QUICK_START.md +241 -0
- package/README.md +590 -0
- package/dist/config-file-loader.d.ts +35 -0
- package/dist/config-file-loader.d.ts.map +1 -0
- package/dist/config-file-loader.js +130 -0
- package/dist/config-file-loader.js.map +1 -0
- package/dist/config-loader.d.ts +21 -0
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/config-loader.js +125 -0
- package/dist/config-loader.js.map +1 -0
- package/dist/dart-generator.d.ts +35 -0
- package/dist/dart-generator.d.ts.map +1 -0
- package/dist/dart-generator.js +167 -0
- package/dist/dart-generator.js.map +1 -0
- package/dist/firestore-client.d.ts +49 -0
- package/dist/firestore-client.d.ts.map +1 -0
- package/dist/firestore-client.js +227 -0
- package/dist/firestore-client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive-cli.d.ts +5 -0
- package/dist/interactive-cli.d.ts.map +1 -0
- package/dist/interactive-cli.js +310 -0
- package/dist/interactive-cli.js.map +1 -0
- package/dist/schema-analyzer.d.ts +38 -0
- package/dist/schema-analyzer.d.ts.map +1 -0
- package/dist/schema-analyzer.js +350 -0
- package/dist/schema-analyzer.js.map +1 -0
- package/dist/templates/model.hbs +39 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/firestore-dart-gen.example.yaml +28 -0
- package/package.json +61 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as admin from 'firebase-admin';
|
|
2
|
+
import { SchemaInfo } from './types';
|
|
3
|
+
export declare class SchemaAnalyzer {
|
|
4
|
+
private nestedClassCounter;
|
|
5
|
+
/**
|
|
6
|
+
* Analyze documents and extract schema information
|
|
7
|
+
*/
|
|
8
|
+
analyzeDocuments(collectionName: string, documents: admin.firestore.DocumentSnapshot[]): SchemaInfo;
|
|
9
|
+
/**
|
|
10
|
+
* Analyze nested objects and extract their schema
|
|
11
|
+
*/
|
|
12
|
+
private analyzeNestedObjects;
|
|
13
|
+
/**
|
|
14
|
+
* Detect Dart type from JavaScript value
|
|
15
|
+
*/
|
|
16
|
+
private detectDartType;
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the final Dart type when multiple types are detected
|
|
19
|
+
*/
|
|
20
|
+
private resolveDartType;
|
|
21
|
+
/**
|
|
22
|
+
* Convert collection name to PascalCase class name with DTO suffix
|
|
23
|
+
*/
|
|
24
|
+
private toClassName;
|
|
25
|
+
/**
|
|
26
|
+
* Convert field name to PascalCase for nested class naming
|
|
27
|
+
*/
|
|
28
|
+
private toPascalCase;
|
|
29
|
+
/**
|
|
30
|
+
* Generate nested class name
|
|
31
|
+
*/
|
|
32
|
+
private toNestedClassName;
|
|
33
|
+
/**
|
|
34
|
+
* Convert plural to singular (basic implementation)
|
|
35
|
+
*/
|
|
36
|
+
private toSingular;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=schema-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-analyzer.d.ts","sourceRoot":"","sources":["../src/schema-analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAuB,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1D,qBAAa,cAAc;IACzB,OAAO,CAAC,kBAAkB,CAAK;IAE/B;;OAEG;IACH,gBAAgB,CACd,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,EAAE,GAC5C,UAAU;IAsIb;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAsG5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAyCtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAsBvB;;OAEG;IACH,OAAO,CAAC,WAAW;IAiBnB;;OAEG;IACH,OAAO,CAAC,YAAY;IAOpB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;OAEG;IACH,OAAO,CAAC,UAAU;CAYnB"}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.SchemaAnalyzer = void 0;
|
|
40
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
41
|
+
const admin = __importStar(require("firebase-admin"));
|
|
42
|
+
class SchemaAnalyzer {
|
|
43
|
+
constructor() {
|
|
44
|
+
this.nestedClassCounter = 0;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Analyze documents and extract schema information
|
|
48
|
+
*/
|
|
49
|
+
analyzeDocuments(collectionName, documents) {
|
|
50
|
+
console.log(chalk_1.default.blue(`Analyzing schema for ${collectionName}...`));
|
|
51
|
+
if (documents.length === 0) {
|
|
52
|
+
throw new Error(`No documents to analyze for collection: ${collectionName}`);
|
|
53
|
+
}
|
|
54
|
+
// Reset nested class counter for each collection
|
|
55
|
+
this.nestedClassCounter = 0;
|
|
56
|
+
// Collect all fields across all documents with their actual values
|
|
57
|
+
const fieldOccurrences = new Map();
|
|
58
|
+
const totalDocs = documents.length;
|
|
59
|
+
for (const doc of documents) {
|
|
60
|
+
const data = doc.data();
|
|
61
|
+
if (!data)
|
|
62
|
+
continue;
|
|
63
|
+
for (const [fieldName, fieldValue] of Object.entries(data)) {
|
|
64
|
+
if (!fieldOccurrences.has(fieldName)) {
|
|
65
|
+
fieldOccurrences.set(fieldName, { types: new Set(), count: 0, values: [] });
|
|
66
|
+
}
|
|
67
|
+
const field = fieldOccurrences.get(fieldName);
|
|
68
|
+
field.count++;
|
|
69
|
+
field.types.add(this.detectDartType(fieldValue));
|
|
70
|
+
field.values.push(fieldValue);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Build fields array with nested schema analysis
|
|
74
|
+
const fields = [];
|
|
75
|
+
const nestedClasses = [];
|
|
76
|
+
for (const [fieldName, { types, count, values }] of fieldOccurrences.entries()) {
|
|
77
|
+
// Field is optional if it doesn't appear in all documents
|
|
78
|
+
const isOptional = count < totalDocs;
|
|
79
|
+
// If field has multiple types or null, it's nullable
|
|
80
|
+
const hasMultipleTypes = types.size > 1;
|
|
81
|
+
const dartType = this.resolveDartType(types);
|
|
82
|
+
const fieldInfo = {
|
|
83
|
+
name: fieldName,
|
|
84
|
+
type: dartType,
|
|
85
|
+
isOptional,
|
|
86
|
+
isNullable: isOptional || hasMultipleTypes,
|
|
87
|
+
};
|
|
88
|
+
// Analyze nested objects
|
|
89
|
+
if (dartType === 'Map<String, dynamic>') {
|
|
90
|
+
const nestedObjects = values.filter(v => v != null && typeof v === 'object' && !Array.isArray(v));
|
|
91
|
+
if (nestedObjects.length > 0) {
|
|
92
|
+
const nestedClassName = this.toNestedClassName(collectionName, fieldName);
|
|
93
|
+
const nestedSchema = this.analyzeNestedObjects(nestedClassName, nestedObjects);
|
|
94
|
+
fieldInfo.type = nestedClassName;
|
|
95
|
+
fieldInfo.nestedSchema = nestedSchema;
|
|
96
|
+
nestedClasses.push(nestedSchema);
|
|
97
|
+
if (nestedSchema.nestedClasses) {
|
|
98
|
+
nestedClasses.push(...nestedSchema.nestedClasses);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Analyze arrays
|
|
103
|
+
if (dartType === 'List<dynamic>') {
|
|
104
|
+
const arrays = values.filter(v => Array.isArray(v) && v.length > 0);
|
|
105
|
+
if (arrays.length > 0) {
|
|
106
|
+
const allItems = arrays.flat();
|
|
107
|
+
const itemTypes = new Set(allItems.map(item => this.detectDartType(item)));
|
|
108
|
+
// Check if all items are objects
|
|
109
|
+
const objectItems = allItems.filter(item => item != null && typeof item === 'object' && !Array.isArray(item));
|
|
110
|
+
if (objectItems.length > 0 && objectItems.length === allItems.length) {
|
|
111
|
+
// All items are objects, create a nested class
|
|
112
|
+
const itemClassName = this.toNestedClassName(collectionName, this.toSingular(fieldName));
|
|
113
|
+
const listItemSchema = this.analyzeNestedObjects(itemClassName, objectItems);
|
|
114
|
+
fieldInfo.type = `List<${itemClassName}>`;
|
|
115
|
+
fieldInfo.listItemSchema = listItemSchema;
|
|
116
|
+
nestedClasses.push(listItemSchema);
|
|
117
|
+
if (listItemSchema.nestedClasses) {
|
|
118
|
+
nestedClasses.push(...listItemSchema.nestedClasses);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else if (itemTypes.size === 1) {
|
|
122
|
+
// Homogeneous array of primitives
|
|
123
|
+
const itemType = Array.from(itemTypes)[0];
|
|
124
|
+
if (itemType !== 'dynamic') {
|
|
125
|
+
fieldInfo.type = `List<${itemType}>`;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
fields.push(fieldInfo);
|
|
131
|
+
}
|
|
132
|
+
// Sort fields: required first, then alphabetically
|
|
133
|
+
fields.sort((a, b) => {
|
|
134
|
+
if (a.isOptional !== b.isOptional) {
|
|
135
|
+
return a.isOptional ? 1 : -1;
|
|
136
|
+
}
|
|
137
|
+
return a.name.localeCompare(b.name);
|
|
138
|
+
});
|
|
139
|
+
const className = this.toClassName(collectionName);
|
|
140
|
+
console.log(chalk_1.default.green(`✓ Detected ${fields.length} fields`));
|
|
141
|
+
// Log field summary
|
|
142
|
+
fields.forEach(field => {
|
|
143
|
+
const optional = field.isOptional ? '?' : '';
|
|
144
|
+
const nullable = field.isNullable && !field.isOptional ? '?' : '';
|
|
145
|
+
console.log(chalk_1.default.gray(` - ${field.name}: ${field.type}${nullable}${optional}`));
|
|
146
|
+
});
|
|
147
|
+
if (nestedClasses.length > 0) {
|
|
148
|
+
console.log(chalk_1.default.green(`✓ Detected ${nestedClasses.length} nested classes`));
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
collectionName,
|
|
152
|
+
className,
|
|
153
|
+
fields,
|
|
154
|
+
nestedClasses: nestedClasses.length > 0 ? nestedClasses : undefined,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Analyze nested objects and extract their schema
|
|
159
|
+
*/
|
|
160
|
+
analyzeNestedObjects(className, objects) {
|
|
161
|
+
const fieldOccurrences = new Map();
|
|
162
|
+
const totalObjects = objects.length;
|
|
163
|
+
for (const obj of objects) {
|
|
164
|
+
if (obj == null)
|
|
165
|
+
continue;
|
|
166
|
+
for (const [fieldName, fieldValue] of Object.entries(obj)) {
|
|
167
|
+
if (!fieldOccurrences.has(fieldName)) {
|
|
168
|
+
fieldOccurrences.set(fieldName, { types: new Set(), count: 0, values: [] });
|
|
169
|
+
}
|
|
170
|
+
const field = fieldOccurrences.get(fieldName);
|
|
171
|
+
field.count++;
|
|
172
|
+
field.types.add(this.detectDartType(fieldValue));
|
|
173
|
+
field.values.push(fieldValue);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const fields = [];
|
|
177
|
+
const nestedClasses = [];
|
|
178
|
+
for (const [fieldName, { types, count, values }] of fieldOccurrences.entries()) {
|
|
179
|
+
const isOptional = count < totalObjects;
|
|
180
|
+
const hasMultipleTypes = types.size > 1;
|
|
181
|
+
const dartType = this.resolveDartType(types);
|
|
182
|
+
const fieldInfo = {
|
|
183
|
+
name: fieldName,
|
|
184
|
+
type: dartType,
|
|
185
|
+
isOptional,
|
|
186
|
+
isNullable: isOptional || hasMultipleTypes,
|
|
187
|
+
};
|
|
188
|
+
// Recursively analyze nested objects
|
|
189
|
+
if (dartType === 'Map<String, dynamic>') {
|
|
190
|
+
const nestedObjects = values.filter(v => v != null && typeof v === 'object' && !Array.isArray(v));
|
|
191
|
+
if (nestedObjects.length > 0) {
|
|
192
|
+
const nestedClassName = `${className}${this.toPascalCase(fieldName)}`;
|
|
193
|
+
const nestedSchema = this.analyzeNestedObjects(nestedClassName, nestedObjects);
|
|
194
|
+
fieldInfo.type = nestedClassName;
|
|
195
|
+
fieldInfo.nestedSchema = nestedSchema;
|
|
196
|
+
nestedClasses.push(nestedSchema);
|
|
197
|
+
if (nestedSchema.nestedClasses) {
|
|
198
|
+
nestedClasses.push(...nestedSchema.nestedClasses);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Recursively analyze arrays
|
|
203
|
+
if (dartType === 'List<dynamic>') {
|
|
204
|
+
const arrays = values.filter(v => Array.isArray(v) && v.length > 0);
|
|
205
|
+
if (arrays.length > 0) {
|
|
206
|
+
const allItems = arrays.flat();
|
|
207
|
+
const objectItems = allItems.filter(item => item != null && typeof item === 'object' && !Array.isArray(item));
|
|
208
|
+
if (objectItems.length > 0 && objectItems.length === allItems.length) {
|
|
209
|
+
const itemClassName = `${className}${this.toPascalCase(this.toSingular(fieldName))}`;
|
|
210
|
+
const listItemSchema = this.analyzeNestedObjects(itemClassName, objectItems);
|
|
211
|
+
fieldInfo.type = `List<${itemClassName}>`;
|
|
212
|
+
fieldInfo.listItemSchema = listItemSchema;
|
|
213
|
+
nestedClasses.push(listItemSchema);
|
|
214
|
+
if (listItemSchema.nestedClasses) {
|
|
215
|
+
nestedClasses.push(...listItemSchema.nestedClasses);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
const itemTypes = new Set(allItems.map(item => this.detectDartType(item)));
|
|
220
|
+
if (itemTypes.size === 1) {
|
|
221
|
+
const itemType = Array.from(itemTypes)[0];
|
|
222
|
+
if (itemType !== 'dynamic') {
|
|
223
|
+
fieldInfo.type = `List<${itemType}>`;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
fields.push(fieldInfo);
|
|
230
|
+
}
|
|
231
|
+
// Sort fields
|
|
232
|
+
fields.sort((a, b) => {
|
|
233
|
+
if (a.isOptional !== b.isOptional) {
|
|
234
|
+
return a.isOptional ? 1 : -1;
|
|
235
|
+
}
|
|
236
|
+
return a.name.localeCompare(b.name);
|
|
237
|
+
});
|
|
238
|
+
return {
|
|
239
|
+
collectionName: className.toLowerCase(),
|
|
240
|
+
className,
|
|
241
|
+
fields,
|
|
242
|
+
nestedClasses: nestedClasses.length > 0 ? nestedClasses : undefined,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Detect Dart type from JavaScript value
|
|
247
|
+
*/
|
|
248
|
+
detectDartType(value) {
|
|
249
|
+
if (value === null || value === undefined) {
|
|
250
|
+
return 'dynamic';
|
|
251
|
+
}
|
|
252
|
+
const jsType = typeof value;
|
|
253
|
+
switch (jsType) {
|
|
254
|
+
case 'string':
|
|
255
|
+
return 'String';
|
|
256
|
+
case 'number':
|
|
257
|
+
return Number.isInteger(value) ? 'int' : 'double';
|
|
258
|
+
case 'boolean':
|
|
259
|
+
return 'bool';
|
|
260
|
+
case 'object':
|
|
261
|
+
// Check for Firestore Timestamp
|
|
262
|
+
if (value instanceof admin.firestore.Timestamp) {
|
|
263
|
+
return 'DateTime';
|
|
264
|
+
}
|
|
265
|
+
// Check for Date
|
|
266
|
+
if (value instanceof Date) {
|
|
267
|
+
return 'DateTime';
|
|
268
|
+
}
|
|
269
|
+
// Check for Array
|
|
270
|
+
if (Array.isArray(value)) {
|
|
271
|
+
return 'List<dynamic>';
|
|
272
|
+
}
|
|
273
|
+
// Default to Map
|
|
274
|
+
return 'Map<String, dynamic>';
|
|
275
|
+
default:
|
|
276
|
+
return 'dynamic';
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Resolve the final Dart type when multiple types are detected
|
|
281
|
+
*/
|
|
282
|
+
resolveDartType(types) {
|
|
283
|
+
// Remove dynamic if there are other types
|
|
284
|
+
const filteredTypes = Array.from(types).filter(t => t !== 'dynamic');
|
|
285
|
+
if (filteredTypes.length === 0) {
|
|
286
|
+
return 'dynamic';
|
|
287
|
+
}
|
|
288
|
+
if (filteredTypes.length === 1) {
|
|
289
|
+
return filteredTypes[0];
|
|
290
|
+
}
|
|
291
|
+
// If we have both int and double, prefer double
|
|
292
|
+
if (filteredTypes.includes('int') && filteredTypes.includes('double')) {
|
|
293
|
+
return 'double';
|
|
294
|
+
}
|
|
295
|
+
// For mixed types, fall back to dynamic
|
|
296
|
+
console.log(chalk_1.default.yellow(`⚠ Multiple types detected: ${filteredTypes.join(', ')}. Using 'dynamic'`));
|
|
297
|
+
return 'dynamic';
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Convert collection name to PascalCase class name with DTO suffix
|
|
301
|
+
*/
|
|
302
|
+
toClassName(collectionName) {
|
|
303
|
+
// Remove trailing 's' if plural (users -> User)
|
|
304
|
+
let singular = collectionName;
|
|
305
|
+
if (collectionName.endsWith('s') && collectionName.length > 1) {
|
|
306
|
+
singular = collectionName.slice(0, -1);
|
|
307
|
+
}
|
|
308
|
+
// Convert to PascalCase
|
|
309
|
+
const className = singular
|
|
310
|
+
.split(/[-_]/)
|
|
311
|
+
.map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
312
|
+
.join('');
|
|
313
|
+
// Append DTO suffix
|
|
314
|
+
return `${className}DTO`;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Convert field name to PascalCase for nested class naming
|
|
318
|
+
*/
|
|
319
|
+
toPascalCase(fieldName) {
|
|
320
|
+
return fieldName
|
|
321
|
+
.split(/[-_]/)
|
|
322
|
+
.map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
323
|
+
.join('');
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Generate nested class name
|
|
327
|
+
*/
|
|
328
|
+
toNestedClassName(parentName, fieldName) {
|
|
329
|
+
const parentClass = this.toClassName(parentName).replace('DTO', '');
|
|
330
|
+
const fieldPascal = this.toPascalCase(fieldName);
|
|
331
|
+
return `${parentClass}${fieldPascal}`;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Convert plural to singular (basic implementation)
|
|
335
|
+
*/
|
|
336
|
+
toSingular(word) {
|
|
337
|
+
if (word.endsWith('ies')) {
|
|
338
|
+
return word.slice(0, -3) + 'y';
|
|
339
|
+
}
|
|
340
|
+
if (word.endsWith('es')) {
|
|
341
|
+
return word.slice(0, -2);
|
|
342
|
+
}
|
|
343
|
+
if (word.endsWith('s') && word.length > 1) {
|
|
344
|
+
return word.slice(0, -1);
|
|
345
|
+
}
|
|
346
|
+
return word;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
exports.SchemaAnalyzer = SchemaAnalyzer;
|
|
350
|
+
//# sourceMappingURL=schema-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-analyzer.js","sourceRoot":"","sources":["../src/schema-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/// A model representing a {{collectionName}} document from Firestore.
|
|
2
|
+
class {{className}} extends Equatable {
|
|
3
|
+
/// Creates a new [{{className}}] instance.
|
|
4
|
+
const {{className}}({{#if fields.length}}{
|
|
5
|
+
{{#each fields}}
|
|
6
|
+
{{#unless isOptional}}required {{/unless}}this.{{name}},
|
|
7
|
+
{{/each}}
|
|
8
|
+
}{{/if}});
|
|
9
|
+
|
|
10
|
+
/// Creates a [{{className}}] from a JSON map.
|
|
11
|
+
factory {{className}}.fromJson(Map<String, dynamic> json) {
|
|
12
|
+
return {{className}}({{#if fields.length}}
|
|
13
|
+
{{#each fields}}
|
|
14
|
+
{{name}}: {{#if (eq type "DateTime")}}{{#if isNullable}}json['{{name}}'] != null ? DateTime.parse(json['{{name}}'] as String) : null{{else}}DateTime.parse(json['{{name}}'] as String){{/if}}{{else}}{{#if nestedSchema}}{{#if isNullable}}json['{{name}}'] != null ? {{type}}.fromJson(json['{{name}}'] as Map<String, dynamic>) : null{{else}}{{type}}.fromJson(json['{{name}}'] as Map<String, dynamic>){{/if}}{{else if listItemSchema}}{{#if isNullable}}json['{{name}}'] != null ? (json['{{name}}'] as List<dynamic>).map((e) => {{listItemSchema.className}}.fromJson(e as Map<String, dynamic>)).toList() : null{{else}}(json['{{name}}'] as List<dynamic>).map((e) => {{listItemSchema.className}}.fromJson(e as Map<String, dynamic>)).toList(){{/if}}{{else}}{{#if isNullable}}json['{{name}}'] as {{{type}}}?{{else}}json['{{name}}'] as {{{type}}}{{/if}}{{/if}}{{/if}},
|
|
15
|
+
{{/each}}{{/if}}
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
{{#each fields}}
|
|
20
|
+
/// The {{name}} field.
|
|
21
|
+
final {{{type}}}{{#if isNullable}}?{{/if}} {{name}};
|
|
22
|
+
|
|
23
|
+
{{/each}}
|
|
24
|
+
@override
|
|
25
|
+
List<Object?> get props => [
|
|
26
|
+
{{#each fields}}
|
|
27
|
+
{{name}},
|
|
28
|
+
{{/each}}
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
/// Converts this [{{className}}] to a JSON map.
|
|
32
|
+
Map<String, dynamic> toJson() {
|
|
33
|
+
return {
|
|
34
|
+
{{#each fields}}
|
|
35
|
+
{{#if isOptional}}if ({{name}} != null) {{/if}}'{{name}}': {{#if (eq type "DateTime")}}{{name}}{{#if isNullable}}?{{/if}}.toIso8601String(){{else if nestedSchema}}{{name}}{{#if isNullable}}?{{/if}}.toJson(){{else if listItemSchema}}{{name}}{{#if isNullable}}?{{/if}}.map((e) => e.toJson()).toList(){{else}}{{name}}{{/if}},
|
|
36
|
+
{{/each}}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export interface FieldInfo {
|
|
2
|
+
name: string;
|
|
3
|
+
type: DartType | string;
|
|
4
|
+
isOptional: boolean;
|
|
5
|
+
isNullable: boolean;
|
|
6
|
+
nestedSchema?: SchemaInfo;
|
|
7
|
+
listItemSchema?: SchemaInfo;
|
|
8
|
+
}
|
|
9
|
+
export interface SchemaInfo {
|
|
10
|
+
collectionName: string;
|
|
11
|
+
className: string;
|
|
12
|
+
fields: FieldInfo[];
|
|
13
|
+
nestedClasses?: SchemaInfo[];
|
|
14
|
+
}
|
|
15
|
+
export type DartType = 'String' | 'int' | 'double' | 'bool' | 'DateTime' | 'List<dynamic>' | 'Map<String, dynamic>' | 'dynamic';
|
|
16
|
+
export interface ExtractOptions {
|
|
17
|
+
collection: string;
|
|
18
|
+
output: string;
|
|
19
|
+
subcollections?: string;
|
|
20
|
+
serviceAccount?: string;
|
|
21
|
+
projectId?: string;
|
|
22
|
+
sampleSize?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface BatchExtractOptions {
|
|
25
|
+
config?: string;
|
|
26
|
+
serviceAccount?: string;
|
|
27
|
+
projectId?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface CollectionConfig {
|
|
30
|
+
name: string;
|
|
31
|
+
output: string;
|
|
32
|
+
sampleSize?: number;
|
|
33
|
+
subcollections?: string[];
|
|
34
|
+
}
|
|
35
|
+
export interface ConfigFile {
|
|
36
|
+
collections: CollectionConfig[];
|
|
37
|
+
}
|
|
38
|
+
export interface InteractiveOptions {
|
|
39
|
+
serviceAccount?: string;
|
|
40
|
+
projectId?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface CollectionSelection {
|
|
43
|
+
name: string;
|
|
44
|
+
includeSubcollections: boolean;
|
|
45
|
+
subcollections: string[];
|
|
46
|
+
}
|
|
47
|
+
export interface CLIConfig {
|
|
48
|
+
firebase?: {
|
|
49
|
+
serviceAccount?: string;
|
|
50
|
+
projectId?: string;
|
|
51
|
+
};
|
|
52
|
+
collections?: string[];
|
|
53
|
+
output?: {
|
|
54
|
+
directory?: string;
|
|
55
|
+
sampleSize?: number;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,cAAc,CAAC,EAAE,UAAU,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,aAAa,CAAC,EAAE,UAAU,EAAE,CAAC;CAC9B;AAED,MAAM,MAAM,QAAQ,GAChB,QAAQ,GACR,KAAK,GACL,QAAQ,GACR,MAAM,GACN,UAAU,GACV,eAAe,GACf,sBAAsB,GACtB,SAAS,CAAC;AAEd,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,gBAAgB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB,EAAE,OAAO,CAAC;IAC/B,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Firestore Dart Generator Configuration
|
|
2
|
+
# Copy this file to firestore-dart-gen.yaml and customize
|
|
3
|
+
|
|
4
|
+
# Firebase Configuration
|
|
5
|
+
firebase:
|
|
6
|
+
# Path to your Firebase service account JSON file
|
|
7
|
+
serviceAccount: ./firebase_service_account.json
|
|
8
|
+
|
|
9
|
+
# Optional: Firebase project ID (if not in service account)
|
|
10
|
+
# projectId: my-project-id
|
|
11
|
+
|
|
12
|
+
# Collections Configuration (optional)
|
|
13
|
+
# These collections will be pre-selected in the interactive CLI
|
|
14
|
+
collections:
|
|
15
|
+
- users
|
|
16
|
+
- products
|
|
17
|
+
- orders
|
|
18
|
+
# - reviews
|
|
19
|
+
# - settings
|
|
20
|
+
|
|
21
|
+
# Output Configuration (optional)
|
|
22
|
+
output:
|
|
23
|
+
# Directory where Dart models will be generated
|
|
24
|
+
directory: ./lib/src/models
|
|
25
|
+
|
|
26
|
+
# Number of documents to sample per collection
|
|
27
|
+
sampleSize: 20
|
|
28
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "firestore-dart-generator",
|
|
3
|
+
"version": "1.0.0-beta.1",
|
|
4
|
+
"description": "Generate Dart models from Firestore collections by analyzing real document schemas",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"firestore-dart-gen": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc && npm run copy-templates",
|
|
11
|
+
"copy-templates": "mkdir -p dist/templates && cp src/templates/*.hbs dist/templates/",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"dev": "ts-node src/index.ts",
|
|
14
|
+
"test": "jest",
|
|
15
|
+
"test:watch": "jest --watch",
|
|
16
|
+
"test:coverage": "jest --coverage",
|
|
17
|
+
"test:update-goldens": "UPDATE_GOLDENS=true jest",
|
|
18
|
+
"prepublishOnly": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"firestore",
|
|
22
|
+
"dart",
|
|
23
|
+
"flutter",
|
|
24
|
+
"code-generation",
|
|
25
|
+
"firebase",
|
|
26
|
+
"schema",
|
|
27
|
+
"models",
|
|
28
|
+
"typescript",
|
|
29
|
+
"generator",
|
|
30
|
+
"cli"
|
|
31
|
+
],
|
|
32
|
+
"author": "Marcos Tort",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/TU_USUARIO/firestore-dart-generator.git"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/TU_USUARIO/firestore-dart-generator#readme",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/TU_USUARIO/firestore-dart-generator/issues"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"chalk": "^4.1.2",
|
|
44
|
+
"commander": "^12.0.0",
|
|
45
|
+
"dotenv": "^16.4.0",
|
|
46
|
+
"firebase-admin": "^12.0.0",
|
|
47
|
+
"handlebars": "^4.7.8",
|
|
48
|
+
"inquirer": "^13.1.0",
|
|
49
|
+
"js-yaml": "^4.1.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/inquirer": "^9.0.9",
|
|
53
|
+
"@types/jest": "^30.0.0",
|
|
54
|
+
"@types/js-yaml": "^4.0.9",
|
|
55
|
+
"@types/node": "^20.19.27",
|
|
56
|
+
"jest": "^30.2.0",
|
|
57
|
+
"ts-jest": "^29.4.6",
|
|
58
|
+
"ts-node": "^10.9.2",
|
|
59
|
+
"typescript": "^5.3.3"
|
|
60
|
+
}
|
|
61
|
+
}
|