@forzalabs/remora 1.0.21 → 1.1.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.
Files changed (111) hide show
  1. package/actions/automap.js +26 -42
  2. package/actions/compile.js +27 -43
  3. package/actions/create_consumer.js +24 -40
  4. package/actions/create_producer.js +16 -32
  5. package/actions/debug.js +18 -34
  6. package/actions/deploy.js +30 -46
  7. package/actions/discover.js +13 -29
  8. package/actions/init.js +29 -45
  9. package/actions/mock.js +16 -32
  10. package/actions/run.js +34 -52
  11. package/actions/sample.js +42 -58
  12. package/index.js +38 -43
  13. package/package.json +4 -4
  14. package/workers/ExecutorWorker.js +18 -32
  15. package/Constants.js +0 -34
  16. package/core/Affirm.js +0 -42
  17. package/core/Algo.js +0 -160
  18. package/core/dste/DSTE.js +0 -113
  19. package/core/logger/DebugLogService.js +0 -48
  20. package/core/logger/DevelopmentLogService.js +0 -70
  21. package/core/logger/LocalLogService.js +0 -70
  22. package/core/logger/Logger.js +0 -54
  23. package/database/DatabaseEngine.js +0 -149
  24. package/database/DatabaseStructure.js +0 -27
  25. package/definitions/DatasetDefinitions.js +0 -2
  26. package/definitions/ExecutorDefinitions.js +0 -2
  27. package/definitions/ProcessENV.js +0 -2
  28. package/definitions/agents/DestinationDriver.js +0 -2
  29. package/definitions/agents/SourceDriver.js +0 -2
  30. package/definitions/cli.js +0 -2
  31. package/definitions/database/ApiKeys.js +0 -2
  32. package/definitions/database/Stored.js +0 -7
  33. package/definitions/database/UsageStat.js +0 -2
  34. package/definitions/database/User.js +0 -2
  35. package/definitions/json_schemas/consumer-schema.json +0 -1226
  36. package/definitions/json_schemas/producer-schema.json +0 -308
  37. package/definitions/json_schemas/project-schema.json +0 -100
  38. package/definitions/json_schemas/source-schema.json +0 -249
  39. package/definitions/requests/ConsumerRequest.js +0 -2
  40. package/definitions/requests/Developer.js +0 -2
  41. package/definitions/requests/Mapping.js +0 -2
  42. package/definitions/requests/ProducerRequest.js +0 -2
  43. package/definitions/requests/Request.js +0 -2
  44. package/definitions/resources/Compiled.js +0 -2
  45. package/definitions/resources/Consumer.js +0 -2
  46. package/definitions/resources/Environment.js +0 -2
  47. package/definitions/resources/Library.js +0 -2
  48. package/definitions/resources/Producer.js +0 -2
  49. package/definitions/resources/Project.js +0 -2
  50. package/definitions/resources/Schema.js +0 -2
  51. package/definitions/resources/Source.js +0 -2
  52. package/definitions/temp.js +0 -2
  53. package/definitions/transform/Transformations.js +0 -2
  54. package/drivers/DeltaShareDriver.js +0 -186
  55. package/drivers/DriverFactory.js +0 -72
  56. package/drivers/DriverHelper.js +0 -248
  57. package/drivers/HttpApiDriver.js +0 -208
  58. package/drivers/RedshiftDriver.js +0 -184
  59. package/drivers/files/LocalDestinationDriver.js +0 -146
  60. package/drivers/files/LocalSourceDriver.js +0 -405
  61. package/drivers/s3/S3DestinationDriver.js +0 -197
  62. package/drivers/s3/S3SourceDriver.js +0 -495
  63. package/engines/CryptoEngine.js +0 -75
  64. package/engines/Environment.js +0 -170
  65. package/engines/ProcessENVManager.js +0 -83
  66. package/engines/RandomEngine.js +0 -47
  67. package/engines/SecretManager.js +0 -23
  68. package/engines/UserManager.js +0 -66
  69. package/engines/ai/AutoMapperEngine.js +0 -37
  70. package/engines/ai/DeveloperEngine.js +0 -497
  71. package/engines/ai/LLM.js +0 -255
  72. package/engines/consumer/ConsumerManager.js +0 -218
  73. package/engines/consumer/ConsumerOnFinishManager.js +0 -202
  74. package/engines/dataset/Dataset.js +0 -824
  75. package/engines/dataset/DatasetManager.js +0 -211
  76. package/engines/dataset/DatasetRecord.js +0 -120
  77. package/engines/dataset/DatasetRecordPool.js +0 -77
  78. package/engines/execution/RequestExecutor.js +0 -67
  79. package/engines/parsing/CSVParser.js +0 -60
  80. package/engines/parsing/LineParser.js +0 -71
  81. package/engines/parsing/ParseCompression.js +0 -101
  82. package/engines/parsing/ParseHelper.js +0 -18
  83. package/engines/parsing/ParseManager.js +0 -54
  84. package/engines/parsing/XLSParser.js +0 -87
  85. package/engines/parsing/XMLParser.js +0 -115
  86. package/engines/producer/ProducerEngine.js +0 -127
  87. package/engines/producer/ProducerManager.js +0 -43
  88. package/engines/scheduler/CronScheduler.js +0 -222
  89. package/engines/scheduler/QueueManager.js +0 -314
  90. package/engines/schema/SchemaValidator.js +0 -67
  91. package/engines/transform/JoinEngine.js +0 -232
  92. package/engines/transform/TransformationEngine.js +0 -277
  93. package/engines/transform/TypeCaster.js +0 -59
  94. package/engines/usage/DataframeManager.js +0 -55
  95. package/engines/usage/UsageDataManager.js +0 -151
  96. package/engines/usage/UsageManager.js +0 -65
  97. package/engines/validation/Validator.js +0 -216
  98. package/executors/ConsumerExecutor.js +0 -280
  99. package/executors/Executor.js +0 -177
  100. package/executors/ExecutorOrchestrator.js +0 -331
  101. package/executors/ExecutorPerformance.js +0 -17
  102. package/executors/ExecutorProgress.js +0 -54
  103. package/executors/ExecutorScope.js +0 -52
  104. package/executors/OutputExecutor.js +0 -118
  105. package/executors/ProducerExecutor.js +0 -108
  106. package/helper/Helper.js +0 -149
  107. package/helper/Logger.js +0 -84
  108. package/helper/Runtime.js +0 -20
  109. package/helper/Settings.js +0 -13
  110. package/licencing/LicenceManager.js +0 -64
  111. package/settings.js +0 -12
@@ -1,497 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- const Affirm_1 = __importDefault(require("../../core/Affirm"));
16
- const ProducerEngine_1 = __importDefault(require("../producer/ProducerEngine"));
17
- const Environment_1 = __importDefault(require("../Environment"));
18
- const path_1 = __importDefault(require("path"));
19
- const promises_1 = __importDefault(require("fs/promises"));
20
- const dayjs_1 = __importDefault(require("dayjs"));
21
- const customParseFormat_1 = __importDefault(require("dayjs/plugin/customParseFormat"));
22
- dayjs_1.default.extend(customParseFormat_1.default);
23
- class DeveloperEngineClass {
24
- constructor() {
25
- this.discover = (producer) => __awaiter(this, void 0, void 0, function* () {
26
- var _a;
27
- (0, Affirm_1.default)(producer, 'Invalid producer');
28
- const sampleData = yield ProducerEngine_1.default.readSampleData(producer, 10, true);
29
- (0, Affirm_1.default)(sampleData, 'Discover process failed: no result found');
30
- const typeDefinitions = this.extractFieldTypes(sampleData);
31
- const mappedProducer = {
32
- name: producer.name,
33
- description: producer.description,
34
- source: producer.source,
35
- settings: Object.assign({}, producer.settings),
36
- dimensions: typeDefinitions.map(field => {
37
- var _a;
38
- return ({
39
- name: field.name,
40
- type: this.mapFieldTypeToProducerType(field.type),
41
- description: `Auto-mapped field: ${field.name}`,
42
- classification: ((_a = this.extractFieldClassification(field)) === null || _a === void 0 ? void 0 : _a.isPHI) ? ['PHI'] : undefined
43
- });
44
- }),
45
- measures: [],
46
- _version: (_a = producer._version) !== null && _a !== void 0 ? _a : 1
47
- };
48
- mappedProducer['$schema'] = producer['$schema'];
49
- // Save the mapped producer to file
50
- const producerPath = path_1.default.join(process.cwd(), 'remora', 'producers', `${producer.name}.json`);
51
- yield promises_1.default.writeFile(producerPath, JSON.stringify(mappedProducer, null, 4), 'utf-8');
52
- return { producer: mappedProducer, fields: typeDefinitions };
53
- });
54
- this.mapFieldTypeToProducerType = (fieldType) => {
55
- switch (fieldType) {
56
- case 'number':
57
- return 'number';
58
- case 'string':
59
- return 'string';
60
- case 'date':
61
- case 'datetime':
62
- return 'datetime';
63
- default:
64
- return 'string';
65
- }
66
- };
67
- // Infer the most likely type from a single JS value
68
- // Returns one of: 'number' | 'boolean' | 'date' | 'datetime' | 'string' | 'array' | 'object' | 'null'
69
- this.inferType = (value) => {
70
- if (value === null || value === undefined)
71
- return 'string';
72
- // Arrays
73
- if (Array.isArray(value))
74
- return 'array';
75
- // Booleans (including common string representations)
76
- if (typeof value === 'boolean')
77
- return 'boolean';
78
- if (typeof value === 'string') {
79
- const trimmed = value.trim();
80
- const lower = trimmed.toLowerCase();
81
- if (lower === 'true' || lower === 'false')
82
- return 'boolean';
83
- // Numbers (numeric strings)
84
- const numericRegex = /^-?\d+(?:\.\d+)?$/;
85
- if (numericRegex.test(trimmed))
86
- return 'number';
87
- // Timestamps (10 or 13 digits)
88
- const tsRegex = /^-?\d{10}(?:\d{3})?$/;
89
- if (tsRegex.test(trimmed)) {
90
- const n = Number(trimmed.length === 10 ? `${trimmed}000` : trimmed);
91
- const d = new Date(n);
92
- if (!isNaN(d.getTime()))
93
- return 'datetime';
94
- }
95
- // Dates with common formats
96
- const dateFormats = [
97
- 'YYYY-MM-DD',
98
- 'YYYY/MM/DD',
99
- 'DD/MM/YYYY',
100
- 'MM/DD/YYYY',
101
- 'YYYYMMDD',
102
- 'DD-MMM-YYYY',
103
- 'YYYY-MM-DD HH:mm',
104
- 'YYYY-MM-DD HH:mm:ss',
105
- 'YYYY-MM-DDTHH:mm',
106
- 'YYYY-MM-DDTHH:mmZ',
107
- 'YYYY-MM-DDTHH:mm:ss',
108
- 'YYYY-MM-DDTHH:mm:ssZ',
109
- 'YYYY-MM-DDTHH:mm:ss.SSSZ'
110
- ];
111
- for (const fmt of dateFormats) {
112
- const d = (0, dayjs_1.default)(trimmed, fmt, true);
113
- if (d.isValid()) {
114
- // If time components likely present, classify as datetime
115
- if (/T|\d+:\d+/.test(trimmed))
116
- return 'datetime';
117
- return 'date';
118
- }
119
- }
120
- // ISO 8601 without specifying format
121
- const iso = (0, dayjs_1.default)(trimmed);
122
- if (iso.isValid() && /\d{4}-\d{2}-\d{2}/.test(trimmed)) {
123
- if (/T|\d+:\d+/.test(trimmed))
124
- return 'datetime';
125
- return 'date';
126
- }
127
- return 'string';
128
- }
129
- if (typeof value === 'number')
130
- return 'number';
131
- if (typeof value === 'object') {
132
- // Date instance
133
- if (value instanceof Date && !isNaN(value.getTime()))
134
- return 'datetime';
135
- return 'object';
136
- }
137
- // Fallback for bigint, symbol, function -> string
138
- return 'string';
139
- };
140
- this.inferDimensionType = (value) => {
141
- const type = this.inferType(value);
142
- switch (type) {
143
- case 'array':
144
- case 'object': return 'string';
145
- case 'boolean': return 'boolean';
146
- case 'date':
147
- case 'datetime': return 'datetime';
148
- case 'number': return 'number';
149
- case 'string': return 'string';
150
- default: return 'string';
151
- }
152
- };
153
- this.extractFieldTypes = (records) => {
154
- if (!records || records.length === 0)
155
- return [];
156
- const sample = records[0];
157
- return Object.entries(sample._value).map(([key, value]) => ({
158
- name: key,
159
- type: this.inferType(value)
160
- }));
161
- };
162
- this.extractFieldClassification = (field) => {
163
- (0, Affirm_1.default)(field, 'Invalid field');
164
- const { name, type } = field;
165
- const fieldNameLower = name.toLowerCase();
166
- // Rule 1: Names
167
- const namePatterns = [
168
- /\b(first|last|middle|full|given|family|sur|maiden|nick|display)[\s_-]?name\b/,
169
- /\b(fname|lname|mname|fullname|givenname|familyname|surname)\b/,
170
- /\b(patient|person|individual|customer|client|user)[\s_-]?name\b/,
171
- /\bname\b/
172
- ];
173
- // Rule 2: Geographic subdivisions (excluding state level)
174
- const geoPatterns = [
175
- /\b(address|addr|street|st|avenue|ave|road|rd|lane|ln|drive|dr|blvd|boulevard)\b/,
176
- /\b(city|town|village|municipality)\b/,
177
- /\b(county|parish|borough)\b/,
178
- /\b(zip|postal|zipcode|postalcode)\b/,
179
- /\b(precinct|district|ward)\b/,
180
- /\b(geocode|coordinates|coord|latitude|longitude|lat|lng)\b/,
181
- /\b(location|place|residence|home)\b/
182
- ];
183
- // Rule 3: Dates related to individuals
184
- const datePatterns = [
185
- /\b(birth|born|dob|birthdate|date[\s_-]?of[\s_-]?birth)\b/,
186
- /\b(admission|admit|admitdate|admission[\s_-]?date)\b/,
187
- /\b(discharge|discharged|dischargedate|discharge[\s_-]?date)\b/,
188
- /\b(death|died|dod|date[\s_-]?of[\s_-]?death|deceased)\b/,
189
- /\b(age|years[\s_-]?old|yrs[\s_-]?old)\b/,
190
- /\b(visit|appointment|appt|service)[\s_-]?date\b/,
191
- /\b(created|updated|modified|last[\s_-]?seen)[\s_-]?date\b/
192
- ];
193
- // Rule 4: Phone numbers
194
- const phonePatterns = [
195
- /\b(phone|tel|telephone|mobile|cell|cellular)\b/,
196
- /\b(home|work|office|emergency)[\s_-]?phone\b/,
197
- /\b(contact|phone)[\s_-]?number\b/
198
- ];
199
- // Rule 5: Fax numbers
200
- const faxPatterns = [
201
- /\b(fax|facsimile)\b/,
202
- /\bfax[\s_-]?number\b/
203
- ];
204
- // Rule 6: Email addresses
205
- const emailPatterns = [
206
- /\b(email|e[\s_-]?mail|mail)\b/,
207
- /\b(email|mail)[\s_-]?address\b/,
208
- /\b(contact|personal|work)[\s_-]?email\b/
209
- ];
210
- // Rule 7: Social Security numbers
211
- const ssnPatterns = [
212
- /\b(ssn|social[\s_-]?security)\b/,
213
- /\bsocial[\s_-]?security[\s_-]?number\b/,
214
- /\btax[\s_-]?id\b/
215
- ];
216
- // Rule 8: Medical record numbers
217
- const medicalRecordPatterns = [
218
- /\b(mrn|medical[\s_-]?record)\b/,
219
- /\bmedical[\s_-]?record[\s_-]?number\b/,
220
- /\b(patient|chart)[\s_-]?number\b/,
221
- /\b(patient|medical)[\s_-]?id\b/
222
- ];
223
- // Rule 9: Health plan beneficiary numbers
224
- const healthPlanPatterns = [
225
- /\b(member|subscriber|beneficiary)[\s_-]?id\b/,
226
- /\b(insurance|health[\s_-]?plan)[\s_-]?number\b/,
227
- /\b(policy|plan)[\s_-]?number\b/,
228
- /\b(medicaid|medicare)[\s_-]?number\b/
229
- ];
230
- // Rule 10: Account numbers
231
- const accountPatterns = [
232
- /\b(account|acct)[\s_-]?number\b/,
233
- /\b(account|acct)[\s_-]?id\b/,
234
- /\b(billing|financial)[\s_-]?account\b/
235
- ];
236
- // Rule 11: Certificate/license numbers
237
- const licensePatterns = [
238
- /\b(license|licence|cert|certificate)[\s_-]?number\b/,
239
- /\b(driver|drivers)[\s_-]?license\b/,
240
- /\b(professional|medical)[\s_-]?license\b/,
241
- /\b(permit|registration)[\s_-]?number\b/
242
- ];
243
- // Rule 12: Vehicle identifiers
244
- const vehiclePatterns = [
245
- /\b(vehicle|car|auto)[\s_-]?id\b/,
246
- /\b(license[\s_-]?plate|plate[\s_-]?number)\b/,
247
- /\b(vin|vehicle[\s_-]?identification)\b/,
248
- /\bserial[\s_-]?number\b/
249
- ];
250
- // Rule 13: Device identifiers
251
- const devicePatterns = [
252
- /\b(device|equipment)[\s_-]?id\b/,
253
- /\b(serial|model)[\s_-]?number\b/,
254
- /\b(imei|mac[\s_-]?address|uuid)\b/
255
- ];
256
- // Rule 14: URLs
257
- const urlPatterns = [
258
- /\b(url|web[\s_-]?address|website)\b/,
259
- /\b(link|hyperlink)\b/,
260
- /\b(homepage|web[\s_-]?page)\b/
261
- ];
262
- // Rule 15: IP addresses
263
- const ipPatterns = [
264
- /\b(ip|ip[\s_-]?address)\b/,
265
- /\b(internet[\s_-]?protocol)\b/,
266
- /\b(network[\s_-]?address)\b/
267
- ];
268
- // Rule 16: Biometric identifiers
269
- const biometricPatterns = [
270
- /\b(biometric|fingerprint|voiceprint)\b/,
271
- /\b(finger|thumb)[\s_-]?print\b/,
272
- /\b(voice|speech)[\s_-]?recognition\b/,
273
- /\b(retina|iris)[\s_-]?scan\b/
274
- ];
275
- // Rule 17: Photographic images
276
- const imagePatterns = [
277
- /\b(photo|photograph|image|picture)\b/,
278
- /\b(face|facial)[\s_-]?image\b/,
279
- /\b(avatar|profile[\s_-]?picture)\b/
280
- ];
281
- // Rule 18: Other unique identifiers
282
- const uniqueIdPatterns = [
283
- /\b(unique|universal)[\s_-]?id\b/,
284
- /\b(id|identifier|tracking)[\s_-]?code\b/,
285
- /\b(reference|ref)[\s_-]?number\b/,
286
- /\b(token|key|hash)\b/,
287
- /\b(guid|uuid)\b/
288
- ];
289
- // Check each pattern category
290
- const patternCategories = [
291
- { patterns: namePatterns, category: 'Names' },
292
- { patterns: geoPatterns, category: 'Geographic Information' },
293
- { patterns: datePatterns, category: 'Dates' },
294
- { patterns: phonePatterns, category: 'Phone Numbers' },
295
- { patterns: faxPatterns, category: 'Fax Numbers' },
296
- { patterns: emailPatterns, category: 'Email Addresses' },
297
- { patterns: ssnPatterns, category: 'Social Security Numbers' },
298
- { patterns: medicalRecordPatterns, category: 'Medical Record Numbers' },
299
- { patterns: healthPlanPatterns, category: 'Health Plan Beneficiary Numbers' },
300
- { patterns: accountPatterns, category: 'Account Numbers' },
301
- { patterns: licensePatterns, category: 'Certificate/License Numbers' },
302
- { patterns: vehiclePatterns, category: 'Vehicle Identifiers' },
303
- { patterns: devicePatterns, category: 'Device Identifiers' },
304
- { patterns: urlPatterns, category: 'URLs' },
305
- { patterns: ipPatterns, category: 'IP Addresses' },
306
- { patterns: biometricPatterns, category: 'Biometric Identifiers' },
307
- { patterns: imagePatterns, category: 'Photographic Images' },
308
- { patterns: uniqueIdPatterns, category: 'Unique Identifiers' }
309
- ];
310
- for (const { patterns, category } of patternCategories) {
311
- for (const pattern of patterns) {
312
- if (pattern.test(fieldNameLower)) {
313
- return {
314
- isPHI: true,
315
- category,
316
- fieldName: name,
317
- fieldType: type,
318
- reason: `Field name matches pattern for ${category}`
319
- };
320
- }
321
- }
322
- }
323
- return {
324
- isPHI: false,
325
- category: null,
326
- fieldName: name,
327
- fieldType: type,
328
- reason: 'No PHI/PII patterns detected'
329
- };
330
- };
331
- this.createMockData = (producer, records) => __awaiter(this, void 0, void 0, function* () {
332
- (0, Affirm_1.default)(producer, 'Invalid producer');
333
- (0, Affirm_1.default)(records > 0, 'Record count must be greater than 0');
334
- const source = Environment_1.default.getSource(producer.source);
335
- (0, Affirm_1.default)(source, `No source found for producer "${producer.name}" with name "${producer.source}"`);
336
- (0, Affirm_1.default)(source.engine === 'local', `Mock data generation only supports local file-based producers. Source engine "${source.engine}" is not supported.`);
337
- const { fileKey, fileType, delimiter } = producer.settings;
338
- (0, Affirm_1.default)(fileKey, 'Producer must have a fileKey setting for mock data generation');
339
- (0, Affirm_1.default)(fileType, 'Producer must have a fileType setting for mock data generation');
340
- // Generate mock records
341
- const mockRecords = this.generateMockRecords(producer.dimensions, records);
342
- // Get the file path
343
- const basePath = source.authentication.path || process.cwd();
344
- const filePath = path_1.default.join(basePath, fileKey.replace('%', 'mock'));
345
- // Ensure directory exists
346
- yield promises_1.default.mkdir(path_1.default.dirname(filePath), { recursive: true });
347
- // Write to file based on type
348
- const content = this.formatMockData(mockRecords, fileType, delimiter);
349
- yield promises_1.default.writeFile(filePath, content, 'utf-8');
350
- return { filePath, recordCount: records };
351
- });
352
- this.generateMockRecords = (dimensions, count) => {
353
- const records = [];
354
- for (let i = 0; i < count; i++) {
355
- const record = {};
356
- for (const dimension of dimensions) {
357
- // Skip sourceFilename dimensions as they are auto-populated
358
- if (dimension.sourceFilename)
359
- continue;
360
- record[dimension.name] = this.generateMockValue(dimension, i);
361
- }
362
- records.push(record);
363
- }
364
- return records;
365
- };
366
- this.generateMockValue = (dimension, index) => {
367
- const { name, type } = dimension;
368
- const nameLower = name.toLowerCase();
369
- // Generate contextual mock data based on field name patterns
370
- if (this.matchesPattern(nameLower, ['id', 'identifier', 'key', 'pk'])) {
371
- return `${index + 1}`;
372
- }
373
- if (this.matchesPattern(nameLower, ['first_name', 'firstname', 'fname', 'given_name'])) {
374
- return this.pickRandom(['John', 'Jane', 'Michael', 'Sarah', 'David', 'Emily', 'Robert', 'Lisa', 'James', 'Mary']);
375
- }
376
- if (this.matchesPattern(nameLower, ['last_name', 'lastname', 'lname', 'surname', 'family_name'])) {
377
- return this.pickRandom(['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', 'Martinez', 'Wilson']);
378
- }
379
- if (this.matchesPattern(nameLower, ['name', 'full_name', 'fullname'])) {
380
- const firstNames = ['John', 'Jane', 'Michael', 'Sarah', 'David', 'Emily'];
381
- const lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia'];
382
- return `${this.pickRandom(firstNames)} ${this.pickRandom(lastNames)}`;
383
- }
384
- if (this.matchesPattern(nameLower, ['email', 'mail'])) {
385
- return `user${index + 1}@example.com`;
386
- }
387
- if (this.matchesPattern(nameLower, ['phone', 'telephone', 'mobile', 'cell'])) {
388
- return `555-${String(Math.floor(Math.random() * 900) + 100).padStart(3, '0')}-${String(Math.floor(Math.random() * 9000) + 1000).padStart(4, '0')}`;
389
- }
390
- if (this.matchesPattern(nameLower, ['address', 'street', 'addr'])) {
391
- const streets = ['Main St', 'Oak Ave', 'Elm Dr', 'Pine Rd', 'Maple Ln', 'Cedar Blvd'];
392
- return `${Math.floor(Math.random() * 9999) + 1} ${this.pickRandom(streets)}`;
393
- }
394
- if (this.matchesPattern(nameLower, ['city', 'town'])) {
395
- return this.pickRandom(['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix', 'Philadelphia', 'San Antonio', 'San Diego']);
396
- }
397
- if (this.matchesPattern(nameLower, ['state', 'province'])) {
398
- return this.pickRandom(['CA', 'TX', 'FL', 'NY', 'PA', 'IL', 'OH', 'GA', 'NC', 'MI']);
399
- }
400
- if (this.matchesPattern(nameLower, ['zip', 'postal', 'zipcode'])) {
401
- return String(Math.floor(Math.random() * 90000) + 10000);
402
- }
403
- if (this.matchesPattern(nameLower, ['country'])) {
404
- return this.pickRandom(['USA', 'Canada', 'UK', 'Germany', 'France', 'Australia']);
405
- }
406
- if (this.matchesPattern(nameLower, ['age', 'years'])) {
407
- return Math.floor(Math.random() * 80) + 18;
408
- }
409
- if (this.matchesPattern(nameLower, ['sex', 'gender'])) {
410
- return this.pickRandom(['M', 'F', 'Male', 'Female']);
411
- }
412
- if (this.matchesPattern(nameLower, ['birth', 'dob', 'birthdate'])) {
413
- const year = Math.floor(Math.random() * 60) + 1940;
414
- const month = String(Math.floor(Math.random() * 12) + 1).padStart(2, '0');
415
- const day = String(Math.floor(Math.random() * 28) + 1).padStart(2, '0');
416
- return `${year}-${month}-${day}`;
417
- }
418
- if (this.matchesPattern(nameLower, ['date', 'created', 'updated', 'timestamp'])) {
419
- const year = Math.floor(Math.random() * 5) + 2020;
420
- const month = String(Math.floor(Math.random() * 12) + 1).padStart(2, '0');
421
- const day = String(Math.floor(Math.random() * 28) + 1).padStart(2, '0');
422
- return `${year}-${month}-${day}`;
423
- }
424
- if (this.matchesPattern(nameLower, ['amount', 'price', 'cost', 'total', 'balance'])) {
425
- return (Math.random() * 1000).toFixed(2);
426
- }
427
- if (this.matchesPattern(nameLower, ['quantity', 'count', 'qty'])) {
428
- return Math.floor(Math.random() * 100) + 1;
429
- }
430
- if (this.matchesPattern(nameLower, ['status'])) {
431
- return this.pickRandom(['active', 'inactive', 'pending', 'completed', 'cancelled']);
432
- }
433
- if (this.matchesPattern(nameLower, ['type', 'category'])) {
434
- return this.pickRandom(['TypeA', 'TypeB', 'TypeC', 'TypeD']);
435
- }
436
- if (this.matchesPattern(nameLower, ['description', 'desc', 'notes', 'comment'])) {
437
- return `Sample description for record ${index + 1}`;
438
- }
439
- // Fall back to type-based generation
440
- return this.generateValueByType(type, index);
441
- };
442
- this.matchesPattern = (fieldName, patterns) => {
443
- return patterns.some(pattern => fieldName.includes(pattern));
444
- };
445
- this.pickRandom = (arr) => {
446
- return arr[Math.floor(Math.random() * arr.length)];
447
- };
448
- this.generateValueByType = (type, index) => {
449
- switch (type) {
450
- case 'string':
451
- return `value_${index + 1}`;
452
- case 'number':
453
- return Math.floor(Math.random() * 1000);
454
- case 'boolean':
455
- return Math.random() > 0.5;
456
- case 'datetime': {
457
- const year = Math.floor(Math.random() * 5) + 2020;
458
- const month = String(Math.floor(Math.random() * 12) + 1).padStart(2, '0');
459
- const day = String(Math.floor(Math.random() * 28) + 1).padStart(2, '0');
460
- return `${year}-${month}-${day}`;
461
- }
462
- default:
463
- return `value_${index + 1}`;
464
- }
465
- };
466
- this.formatMockData = (records, fileType, delimiter) => {
467
- switch (fileType) {
468
- case 'JSON':
469
- return JSON.stringify(records, null, 2);
470
- case 'JSONL':
471
- return records.map(r => JSON.stringify(r)).join('\n');
472
- case 'CSV':
473
- case 'TXT': {
474
- const delim = delimiter || ',';
475
- if (records.length === 0)
476
- return '';
477
- const headers = Object.keys(records[0]);
478
- const headerLine = headers.join(delim);
479
- const dataLines = records.map(record => headers.map(h => {
480
- const val = record[h];
481
- const strVal = val === null || val === undefined ? '' : String(val);
482
- // Escape delimiter and quotes in values
483
- if (strVal.includes(delim) || strVal.includes('"') || strVal.includes('\n')) {
484
- return `"${strVal.replace(/"/g, '""')}"`;
485
- }
486
- return strVal;
487
- }).join(delim));
488
- return [headerLine, ...dataLines].join('\n');
489
- }
490
- default:
491
- throw new Error(`Unsupported file type for mock data generation: ${fileType}`);
492
- }
493
- };
494
- }
495
- }
496
- const DeveloperEngine = new DeveloperEngineClass();
497
- exports.default = DeveloperEngine;