orchid-orm-test-factory 0.7.66 → 1.0.2

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/dist/index.js CHANGED
@@ -1,27 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var zod = require('zod');
4
3
  var pqb = require('pqb');
5
- var zodMock = require('@anatine/zod-mock');
4
+ var orchidCore = require('orchid-core');
5
+ var faker = require('@faker-js/faker');
6
+ var randexp = require('randexp');
6
7
 
7
- var __defProp = Object.defineProperty;
8
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
- var __hasOwnProp = Object.prototype.hasOwnProperty;
10
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
11
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
- var __spreadValues = (a, b) => {
13
- for (var prop in b || (b = {}))
14
- if (__hasOwnProp.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- if (__getOwnPropSymbols)
17
- for (var prop of __getOwnPropSymbols(b)) {
18
- if (__propIsEnum.call(b, prop))
19
- __defNormalProp(a, prop, b[prop]);
20
- }
21
- return a;
22
- };
23
8
  const omit = (obj, keys) => {
24
- const res = __spreadValues({}, obj);
9
+ const res = { ...obj };
25
10
  Object.keys(keys).forEach((key) => {
26
11
  delete res[key];
27
12
  });
@@ -37,83 +22,39 @@ const pick = (obj, keys) => {
37
22
  });
38
23
  return res;
39
24
  };
40
- const makeUniqueText = (sequence, value) => `${sequence} ${value}`;
41
- const makeUniqueEmail = (sequence, value) => `${sequence}-${value}`;
42
- const makeUniqueUrl = (sequence, value) => value.replace("://", `://${sequence}-`);
43
- const makeUniqueNumber = (sequence) => sequence;
44
- const makeSetUniqueValues = (uniqueFields, data) => {
45
- var _a;
46
- const dataKeys = Object.keys(data);
47
- const fns = {};
48
- for (const field of uniqueFields) {
49
- if (dataKeys.includes(field.key))
50
- continue;
51
- if (field.type === "text") {
52
- const getValue = field.kind === "email" ? makeUniqueEmail : field.kind === "url" ? makeUniqueUrl : makeUniqueText;
53
- let fn;
54
- const max = (_a = field.length) != null ? _a : field.max;
55
- if (max !== void 0) {
56
- fn = (sequence, value) => {
57
- let result = getValue(sequence, value);
58
- if (result.length > max) {
59
- result = result.slice(0, -(result.length - max));
60
- }
61
- return result;
62
- };
63
- } else {
64
- fn = getValue;
65
- }
66
- fns[field.key] = fn;
67
- } else {
68
- let fn;
69
- const { gt, gte } = field;
70
- if (gt) {
71
- fn = (sequence) => sequence + gt;
72
- } else if (gte) {
73
- fn = (sequence) => sequence + gte - 1;
74
- } else {
75
- fn = makeUniqueNumber;
76
- }
77
- fns[field.key] = fn;
78
- }
79
- }
80
- return (record, sequence) => {
81
- for (const key in fns) {
82
- record[key] = fns[key](sequence, record[key]);
83
- }
84
- };
85
- };
86
- const makeBuild = (factory, data, omitValues, pickValues, uniqueFields, arg) => {
87
- let schema = factory.schema;
88
- let allData = arg ? __spreadValues(__spreadValues({}, data), arg) : data;
25
+ const makeBuild = (factory, data, omitValues, pickValues, arg) => {
26
+ let { fns } = factory;
27
+ let allData = arg ? { ...data, ...arg } : data;
89
28
  if (omitValues) {
90
- schema = schema.omit(omitValues);
29
+ fns = omit(fns, omitValues);
91
30
  allData = omit(allData, omitValues);
92
31
  }
93
32
  if (pickValues && Object.keys(pickValues).length) {
94
- schema = schema.pick(pickValues);
33
+ fns = pick(fns, pickValues);
95
34
  allData = pick(allData, pickValues);
96
35
  }
97
- const setUniqueValues = makeSetUniqueValues(uniqueFields, allData);
98
36
  return (arg2) => {
99
- const data2 = arg2 ? __spreadValues(__spreadValues({}, allData), arg2) : allData;
100
- const result = zodMock.generateMock(schema);
37
+ const data2 = arg2 ? { ...allData, ...arg2 } : allData;
38
+ const sequence = factory.sequence++;
39
+ const result = {};
40
+ for (const key in fns) {
41
+ result[key] = fns[key](sequence);
42
+ }
101
43
  for (const key in data2) {
102
44
  const value = data2[key];
103
45
  if (typeof value === "function") {
104
- result[key] = value(factory.sequence);
46
+ result[key] = value(sequence);
105
47
  } else {
106
48
  result[key] = value;
107
49
  }
108
50
  }
109
- setUniqueValues(result, factory.sequence);
110
- factory.sequence++;
111
51
  return result;
112
52
  };
113
53
  };
114
- const processCreateData = (factory, data, uniqueFields, arg) => {
54
+ const processCreateData = (factory, data, arg) => {
55
+ const { fns } = factory;
115
56
  const pick2 = {};
116
- for (const key in factory.table.shape) {
57
+ for (const key in fns) {
117
58
  pick2[key] = true;
118
59
  }
119
60
  for (const key of pqb.getPrimaryKeys(factory.table)) {
@@ -123,8 +64,7 @@ const processCreateData = (factory, data, uniqueFields, arg) => {
123
64
  }
124
65
  }
125
66
  const shared = {};
126
- const fns = {};
127
- const allData = arg ? __spreadValues(__spreadValues({}, data), arg) : data;
67
+ const allData = arg ? { ...data, ...arg } : data;
128
68
  for (const key in allData) {
129
69
  delete pick2[key];
130
70
  const value = allData[key];
@@ -134,12 +74,13 @@ const processCreateData = (factory, data, uniqueFields, arg) => {
134
74
  shared[key] = value;
135
75
  }
136
76
  }
137
- const pickedSchema = factory.schema.pick(pick2);
138
- const setUniqueValues = makeSetUniqueValues(uniqueFields, allData);
139
77
  return async (arg2) => {
140
- const result = Object.assign(__spreadValues({}, shared), zodMock.generateMock(pickedSchema));
141
78
  const { sequence } = factory;
142
79
  factory.sequence++;
80
+ const result = { ...shared };
81
+ for (const key in pick2) {
82
+ result[key] = fns[key](sequence);
83
+ }
143
84
  if (arg2) {
144
85
  for (const key in arg2) {
145
86
  if (typeof arg2[key] === "function") {
@@ -151,6 +92,7 @@ const processCreateData = (factory, data, uniqueFields, arg) => {
151
92
  } else {
152
93
  const promises = [];
153
94
  for (const key in fns) {
95
+ if (key in result) continue;
154
96
  promises.push(
155
97
  new Promise(async (resolve, reject) => {
156
98
  try {
@@ -164,41 +106,37 @@ const processCreateData = (factory, data, uniqueFields, arg) => {
164
106
  }
165
107
  await Promise.all(promises);
166
108
  }
167
- setUniqueValues(result, sequence);
168
109
  return result;
169
110
  };
170
111
  };
171
- const _TestFactory = class {
172
- constructor(table, schema, uniqueFields, data = {}, options = {}) {
112
+ const _TestFactory = class _TestFactory {
113
+ constructor(table, fns, options = {}) {
173
114
  this.table = table;
174
- this.schema = schema;
175
- this.uniqueFields = uniqueFields;
176
- this.data = data;
115
+ this.fns = fns;
177
116
  this.omitValues = {};
178
117
  this.pickValues = {};
179
- var _a;
118
+ this.data = {};
180
119
  if (options.sequence !== void 0) {
181
120
  this.sequence = options.sequence;
182
121
  } else {
183
122
  let workerId = parseInt(process.env.JEST_WORKER_ID);
184
- if (isNaN(workerId))
185
- workerId = 1;
186
- this.sequence = (workerId - 1) * ((_a = options.sequenceDistance) != null ? _a : 1e3) + 1;
123
+ if (isNaN(workerId)) workerId = 1;
124
+ this.sequence = (workerId - 1) * (options.sequenceDistance ?? 1e3) + 1;
187
125
  }
188
126
  }
189
127
  set(data) {
190
128
  return Object.assign(Object.create(this), {
191
- data: __spreadValues(__spreadValues({}, this.data), data)
129
+ data: { ...this.data, ...data }
192
130
  });
193
131
  }
194
132
  omit(keys) {
195
133
  return Object.assign(Object.create(this), {
196
- omitValues: __spreadValues(__spreadValues({}, this.omitValues), keys)
134
+ omitValues: { ...this.omitValues, ...keys }
197
135
  });
198
136
  }
199
137
  pick(keys) {
200
138
  return Object.assign(Object.create(this), {
201
- pickValues: __spreadValues(__spreadValues({}, this.pickValues), keys)
139
+ pickValues: { ...this.pickValues, ...keys }
202
140
  });
203
141
  }
204
142
  build(data) {
@@ -207,7 +145,6 @@ const _TestFactory = class {
207
145
  this.data,
208
146
  this.omitValues,
209
147
  this.pickValues,
210
- this.uniqueFields,
211
148
  data
212
149
  );
213
150
  return build();
@@ -218,118 +155,426 @@ const _TestFactory = class {
218
155
  this.data,
219
156
  this.omitValues,
220
157
  this.pickValues,
221
- this.uniqueFields,
222
158
  data
223
159
  );
224
- return [...Array(qty)].map(build);
160
+ return Array.from({ length: qty }, () => build());
225
161
  }
226
- buildMany(...arr) {
227
- const build = makeBuild(
228
- this,
229
- this.data,
230
- this.omitValues,
231
- this.pickValues,
232
- this.uniqueFields
233
- );
234
- return arr.map(build);
162
+ buildMany(...arr2) {
163
+ const build = makeBuild(this, this.data, this.omitValues, this.pickValues);
164
+ return arr2.map(build);
235
165
  }
236
166
  async create(data) {
237
- const getData = processCreateData(this, this.data, this.uniqueFields, data);
238
- return await this.table.create(await getData());
167
+ const getData = processCreateData(this, this.data, data);
168
+ return await this.table.create(
169
+ await getData()
170
+ );
239
171
  }
240
172
  async createList(qty, data) {
241
- const getData = processCreateData(this, this.data, this.uniqueFields, data);
242
- const arr = await Promise.all([...Array(qty)].map(() => getData()));
173
+ const getData = processCreateData(this, this.data, data);
174
+ const arr2 = await Promise.all([...Array(qty)].map(() => getData()));
243
175
  return await this.table.createMany(
244
- arr
176
+ arr2
245
177
  );
246
178
  }
247
- async createMany(...arr) {
248
- const getData = processCreateData(this, this.data, this.uniqueFields);
249
- const data = await Promise.all(arr.map(getData));
179
+ async createMany(...arr2) {
180
+ const getData = processCreateData(this, this.data);
181
+ const data = await Promise.all(arr2.map(getData));
250
182
  return await this.table.createMany(
251
183
  data
252
184
  );
253
185
  }
254
186
  extend() {
255
- const { table, schema, uniqueFields } = this;
187
+ const { table, fns } = this;
256
188
  return class extends _TestFactory {
257
189
  constructor() {
258
- super(table, schema, uniqueFields);
190
+ super(table, fns);
259
191
  }
260
192
  };
261
193
  }
262
194
  };
263
195
  let TestFactory = _TestFactory;
264
- const nowString = (/* @__PURE__ */ new Date()).toISOString();
265
- const maxPostgresInt = 2147483647;
266
- const tableFactory = (table, options) => {
267
- var _a, _b, _c, _d;
268
- const shape = {};
269
- const columns = table.shape;
270
- for (const key in columns) {
271
- const { inputSchema } = columns[key];
272
- if (inputSchema)
273
- shape[key] = inputSchema;
196
+ let fixedTime;
197
+ let fixedTZ;
198
+ const int = (min, max) => faker.faker.number.int({ min, max });
199
+ const float = (min, max, multipleOf) => faker.faker.number.float({
200
+ min,
201
+ max,
202
+ multipleOf
203
+ });
204
+ const point = () => float(-100, 100, 0.01);
205
+ const isoTime = (c, sequence) => {
206
+ const data = c.data;
207
+ return (data.min || data.max ? faker.faker.date.between({
208
+ from: data.min || /* @__PURE__ */ new Date(-864e13),
209
+ to: data.max || /* @__PURE__ */ new Date(864e13)
210
+ }) : new Date((fixedTime ?? (fixedTime = faker.faker.date.anytime())).getTime() + sequence)).toISOString();
211
+ };
212
+ const bool = () => faker.faker.datatype.boolean();
213
+ const arr = (min, max, fn) => Array.from({ length: int(min, max) }, fn);
214
+ const numOpts = (c, step, min, max, options) => ({
215
+ min: c.data.gt ? c.data.gt + (step || 0) : c.data.gte || min,
216
+ max: c.data.lt ? c.data.lt - (step || 0) : c.data.lte || max,
217
+ ...options
218
+ });
219
+ const num = (uniqueColumns, key, c, method, {
220
+ step,
221
+ min,
222
+ max,
223
+ module = "number",
224
+ ...options
225
+ } = {}) => {
226
+ const opts = numOpts(c, step, min, max, options);
227
+ if (uniqueColumns.has(key)) {
228
+ if (method === "int" || method === "float" || method === "amount") {
229
+ const st = step || 1;
230
+ let min2 = (opts.min ?? 0) - st;
231
+ if (min2 < 0) min2 = 0;
232
+ const { symbol } = options;
233
+ if (symbol) {
234
+ return (sequence) => `${symbol}${min2 + sequence * st}`;
235
+ } else {
236
+ return (sequence) => min2 + sequence * st;
237
+ }
238
+ }
239
+ if (method === "bigInt") {
240
+ const st = step || 1n;
241
+ let min2 = (opts.min ?? 0n) - st;
242
+ if (min2 < 0n) min2 = 0n;
243
+ return (sequence) => min2 + BigInt(sequence) * st;
244
+ }
274
245
  }
275
- const schema = zod.z.object(shape);
276
- const data = {};
277
- const now = Date.now();
278
- const uniqueFields = [];
279
- for (const key in table.shape) {
280
- const column = table.shape[key];
281
- if (column instanceof pqb.DateBaseColumn) {
282
- if (column.data.as instanceof pqb.IntegerBaseColumn) {
283
- data[key] = (sequence) => now + sequence;
284
- } else if (((_b = (_a = column.data).parse) == null ? void 0 : _b.call(_a, nowString)) instanceof Date) {
285
- data[key] = (sequence) => new Date(now + sequence);
246
+ return () => faker.faker[module][method](opts);
247
+ };
248
+ const makeGeneratorForColumn = (config, table, uniqueColumns, key, c) => {
249
+ let fn;
250
+ const custom = config.fakeDataForTypes?.[c.dataType]?.(c);
251
+ if (custom) {
252
+ fn = custom;
253
+ } else if (c instanceof pqb.EnumColumn) {
254
+ fn = () => faker.faker.helpers.arrayElement(c.options);
255
+ } else if (c instanceof pqb.ArrayColumn) {
256
+ fn = () => arr(
257
+ 1,
258
+ 5,
259
+ makeGeneratorForColumn(
260
+ config,
261
+ table,
262
+ uniqueColumns,
263
+ key,
264
+ c.data.item
265
+ )
266
+ );
267
+ } else if (c instanceof pqb.SmallIntColumn || c instanceof pqb.SmallSerialColumn) {
268
+ fn = num(uniqueColumns, key, c, "int", {
269
+ step: 1,
270
+ min: -32768,
271
+ max: 32767
272
+ });
273
+ } else if (c instanceof pqb.IntegerColumn || c instanceof pqb.SerialColumn) {
274
+ fn = num(uniqueColumns, key, c, "int", {
275
+ step: 1,
276
+ min: -2147483648,
277
+ max: 2147483648
278
+ });
279
+ } else if (c instanceof pqb.BigIntColumn || c instanceof pqb.BigSerialColumn) {
280
+ fn = num(uniqueColumns, key, c, "bigInt", {
281
+ step: 1n,
282
+ min: BigInt("-9223372036854775808"),
283
+ max: BigInt("9223372036854775807")
284
+ });
285
+ } else if (c instanceof pqb.DecimalColumn || c instanceof pqb.DoublePrecisionColumn) {
286
+ fn = num(uniqueColumns, key, c, "float", {
287
+ fractionDigits: c.data.numericScale
288
+ });
289
+ } else if (c instanceof pqb.RealColumn) {
290
+ fn = num(uniqueColumns, key, c, "float");
291
+ } else if (c instanceof pqb.MoneyColumn) {
292
+ fn = num(uniqueColumns, key, c, "amount", {
293
+ module: "finance",
294
+ symbol: "$"
295
+ });
296
+ } else if (c instanceof pqb.VarCharColumn || c instanceof pqb.TextColumn || c instanceof pqb.StringColumn || c instanceof pqb.CitextColumn) {
297
+ const data = c.data;
298
+ const lowerKey = key.toLowerCase();
299
+ const strippedKey = lowerKey.replace(/_|-/g, "");
300
+ let gen;
301
+ const min = data.length ?? data.min ?? data.nonEmpty ? 1 : 0;
302
+ const max = Math.min(
303
+ data.length ?? data.max ?? Infinity,
304
+ config.maxTextLength ?? 1e3
305
+ );
306
+ const { includes, startsWith, endsWith, trim, toLowerCase, toUpperCase } = data;
307
+ let isEmail = false;
308
+ let isUrl = false;
309
+ if (data.email) {
310
+ isEmail = true;
311
+ gen = () => faker.faker.internet.email();
312
+ } else if (data.emoji) {
313
+ gen = () => faker.faker.internet.emoji();
314
+ } else if (data.url) {
315
+ isUrl = true;
316
+ gen = () => faker.faker.internet.url();
317
+ } else if (data.uuid) {
318
+ gen = () => faker.faker.string.uuid();
319
+ } else if (data.datetime) {
320
+ gen = (sequence) => isoTime(c, sequence);
321
+ } else if (data.ip) {
322
+ if (data.ip.version === "v4") {
323
+ gen = () => faker.faker.internet.ipv4();
324
+ } else if (data.ip.version === "v6") {
325
+ gen = () => faker.faker.internet.ipv6();
286
326
  } else {
287
- data[key] = (sequence) => new Date(now + sequence).toISOString();
327
+ gen = () => faker.faker.internet.ip();
288
328
  }
289
- } else if (column instanceof pqb.TextBaseColumn) {
290
- const max = (_c = options == null ? void 0 : options.maxTextLength) != null ? _c : 1e3;
291
- const item = schema.shape[key];
292
- const string = item instanceof zod.ZodNullable ? item.unwrap() : item;
293
- const maxCheck = string._def.checks.find(
294
- (check) => check.kind === "max"
295
- );
296
- if (!maxCheck || maxCheck.value > max) {
297
- schema.shape[key] = item instanceof zod.ZodNullable ? string.max(max).nullable() : string.max(max);
329
+ } else if (data.regex) {
330
+ const generator = new randexp(data.regex);
331
+ generator.randInt = (min2, max2) => faker.faker.number.int({ min: min2, max: max2 });
332
+ if (max !== Infinity) {
333
+ generator.max = max;
298
334
  }
299
- } else if (column instanceof pqb.IntegerBaseColumn) {
300
- const item = schema.shape[key];
301
- const num = item instanceof zod.ZodNullable ? item.unwrap() : item;
302
- const maxCheck = num._def.checks.find((check) => check.kind === "max");
303
- if (!maxCheck) {
304
- schema.shape[key] = item instanceof zod.ZodNullable ? num.max(maxPostgresInt).nullable() : num.max(maxPostgresInt);
335
+ gen = () => generator.gen();
336
+ } else if (strippedKey === "name") {
337
+ gen = () => faker.faker.person.fullName();
338
+ } else if (strippedKey === "phonenumber") {
339
+ gen = () => faker.faker.phone.number();
340
+ } else if (strippedKey === "image" || strippedKey === "imageurl") {
341
+ gen = () => faker.faker.image.url();
342
+ } else {
343
+ for (const sectionKey in faker.faker) {
344
+ for (const key2 in faker.faker[sectionKey]) {
345
+ if (key2 === strippedKey) {
346
+ const fn2 = faker.faker[sectionKey][key2];
347
+ gen = () => String(fn2());
348
+ if (key2 === "email") isEmail = true;
349
+ else if (key2 === "url") isUrl = true;
350
+ }
351
+ }
305
352
  }
353
+ if (!gen) gen = () => faker.faker.food.dish();
306
354
  }
307
- if ((_d = column.data.indexes) == null ? void 0 : _d.some((index) => index.options.unique)) {
308
- if (column instanceof pqb.TextBaseColumn) {
309
- uniqueFields.push({
310
- key,
311
- type: "text",
312
- kind: column.data.email ? "email" : column.data.url ? "url" : void 0,
313
- max: column.data.max,
314
- length: column.data.length
315
- });
316
- } else if (column instanceof pqb.NumberBaseColumn) {
317
- uniqueFields.push({
318
- key,
319
- type: "number",
320
- gt: column.data.gt,
321
- gte: column.data.gte
322
- });
355
+ const isUnique = uniqueColumns.has(key);
356
+ fn = (sequence) => {
357
+ const seq = sequence++;
358
+ let s = gen(seq);
359
+ if (isUnique) {
360
+ if (isEmail) s = `${seq}-${s}`;
361
+ else if (isUrl) s = s.replace("://", `://${seq}-`);
362
+ else s = `${seq} ${s}`;
363
+ }
364
+ while (s.length < min) {
365
+ s += gen(seq);
366
+ if (trim) s = s.trim();
367
+ }
368
+ if (s.length > max) {
369
+ s = s.slice(0, max);
370
+ if (trim) {
371
+ s = s.trim();
372
+ while (s.length < min) {
373
+ s += gen(seq);
374
+ if (trim) s = s.trim();
375
+ }
376
+ }
377
+ }
378
+ if (startsWith) {
379
+ s = startsWith + s.slice(startsWith.length);
380
+ }
381
+ if (includes) {
382
+ const start = Math.max(
383
+ 0,
384
+ Math.floor(s.length / 2) - Math.floor(includes.length / 2)
385
+ );
386
+ s = s.slice(0, start) + includes + s.slice(start + includes.length);
387
+ }
388
+ if (endsWith) {
389
+ s = s.slice(0, endsWith.length + 1) + endsWith;
390
+ }
391
+ return toLowerCase ? s.toLocaleLowerCase() : toUpperCase ? s.toLocaleUpperCase() : s;
392
+ };
393
+ } else if (c instanceof pqb.ByteaColumn) {
394
+ fn = () => Buffer.from(arr(1, 10, () => int(0, 255)));
395
+ } else if (c instanceof pqb.DateColumn) {
396
+ fn = (sequence) => isoTime(c, sequence).split("T")[0];
397
+ } else if (c instanceof pqb.TimestampColumn || c instanceof pqb.TimestampTZColumn) {
398
+ const hasTZ = c instanceof pqb.TimestampTZColumn;
399
+ fn = (sequence) => {
400
+ let timestamp = isoTime(c, sequence).replace("T", " ");
401
+ if (hasTZ) {
402
+ if (!fixedTZ) {
403
+ const minOffset = -720;
404
+ const maxOffset = 840;
405
+ const randomOffset = int(minOffset, maxOffset);
406
+ const sign = randomOffset >= 0 ? "+" : "-";
407
+ const absOffset = Math.abs(randomOffset);
408
+ const hours = String(Math.floor(absOffset / 60)).padStart(2, "0");
409
+ const minutes = String(absOffset % 60).padStart(2, "0");
410
+ fixedTZ = `${sign}${hours}:${minutes}`;
411
+ }
412
+ timestamp += fixedTZ;
323
413
  }
414
+ return timestamp;
415
+ };
416
+ } else if (c instanceof pqb.TimeColumn) {
417
+ fn = (sequence) => isoTime(c, sequence).split("T")[1].replace(/\..+/, "");
418
+ } else if (c instanceof pqb.IntervalColumn) {
419
+ fn = () => {
420
+ const years = int(0, 10);
421
+ const months = int(0, 11);
422
+ const days = int(0, 30);
423
+ const hours = int(0, 23);
424
+ const minutes = int(0, 59);
425
+ const seconds = float(0, 59, 0.1);
426
+ return `${years} years ${months} mons ${days} days ${hours} hours ${minutes} mins ${seconds.toFixed(
427
+ 1
428
+ )} secs`;
429
+ };
430
+ } else if (c instanceof pqb.BooleanColumn) {
431
+ fn = bool;
432
+ } else if (c instanceof pqb.PointColumn) {
433
+ fn = () => `(${point()}, ${point()})`;
434
+ } else if (c instanceof pqb.LineColumn) {
435
+ fn = () => `{${point()},${point()},${point()}}`;
436
+ } else if (c instanceof pqb.LsegColumn) {
437
+ fn = () => `((${point()}, ${point()}), (${point()}, ${point()}))`;
438
+ } else if (c instanceof pqb.BoxColumn) {
439
+ fn = () => `((${point()}, ${point()}), (${point()}, ${point()}))`;
440
+ } else if (c instanceof pqb.PathColumn) {
441
+ fn = () => {
442
+ const s = arr(2, 10, () => `(${point()}, ${point()})`).join(", ");
443
+ return bool() ? `[${s}]` : `(${s})`;
444
+ };
445
+ } else if (c instanceof pqb.PolygonColumn) {
446
+ fn = () => `(${arr(2, 10, () => `(${point()}, ${point()})`).join(", ")})`;
447
+ } else if (c instanceof pqb.CircleColumn) {
448
+ fn = () => `<(${point()}, ${point()}), ${float(0, 100, 0.01)}>`;
449
+ } else if (c instanceof pqb.CidrColumn) {
450
+ fn = () => `${faker.faker.internet.ip()}/${int(0, 32)}`;
451
+ } else if (c instanceof pqb.InetColumn) {
452
+ fn = () => bool() ? faker.faker.internet.ip() : faker.faker.internet.ipv6();
453
+ } else if (c instanceof pqb.MacAddrColumn) {
454
+ fn = () => faker.faker.internet.mac();
455
+ } else if (c instanceof pqb.MacAddr8Column) {
456
+ fn = () => Array.from(
457
+ { length: 8 },
458
+ () => faker.faker.string.hexadecimal({ length: 2 })
459
+ ).join(":");
460
+ } else if (c instanceof pqb.BitColumn) {
461
+ const { length } = c.data;
462
+ fn = () => Array.from({ length }, () => bool() ? "1" : "0").join("");
463
+ } else if (c instanceof pqb.BitVaryingColumn) {
464
+ const length = c.data.length;
465
+ fn = () => arr(1, length || 100, () => bool() ? "1" : "0").join("");
466
+ } else if (c instanceof pqb.TsVectorColumn) {
467
+ fn = () => arr(1, 10, () => faker.faker.lorem.word()).join(" ");
468
+ } else if (c instanceof pqb.TsQueryColumn) {
469
+ fn = () => {
470
+ const operators = ["&", "|", "<->"];
471
+ return arr(1, 10, (_, i) => {
472
+ const word = faker.faker.lorem.word();
473
+ return i === 0 ? word : faker.faker.helpers.arrayElement(operators) + " " + word;
474
+ }).join(" ");
475
+ };
476
+ } else if (c instanceof pqb.UUIDColumn) {
477
+ fn = () => faker.faker.string.uuid();
478
+ } else if (c instanceof pqb.XMLColumn) {
479
+ fn = () => "<items>\n" + arr(
480
+ 1,
481
+ 5,
482
+ () => ` <item>
483
+ <id>${faker.faker.string.uuid()}</id>
484
+ <name>${faker.faker.person.firstName()}</name>
485
+ <email>${faker.faker.internet.email()}</email>
486
+ <address>${faker.faker.location.streetAddress()}</address>
487
+ <created_at>${faker.faker.date.past().toISOString()}</created_at>
488
+ </item>
489
+ `
490
+ ).join("") + "</items>";
491
+ } else if (c instanceof pqb.JSONColumn || c instanceof pqb.JSONTextColumn) {
492
+ fn = () => JSON.stringify(
493
+ arr(1, 5, () => ({
494
+ id: faker.faker.string.uuid(),
495
+ name: faker.faker.person.firstName(),
496
+ email: faker.faker.internet.email(),
497
+ address: {
498
+ street: faker.faker.location.streetAddress(),
499
+ city: faker.faker.location.city(),
500
+ state: faker.faker.location.state(),
501
+ zip: faker.faker.location.zipCode()
502
+ },
503
+ createdAt: faker.faker.date.past().toISOString()
504
+ }))
505
+ );
506
+ } else if (c instanceof pqb.VirtualColumn) {
507
+ return;
508
+ } else if (c instanceof pqb.PostgisGeographyPointColumn) {
509
+ fn = () => {
510
+ const lon = faker.faker.location.longitude({ min: -180, max: 180 });
511
+ const lat = faker.faker.location.latitude({ min: -90, max: 90 });
512
+ return pqb.PostgisGeographyPointColumn.encode({ lon, lat });
513
+ };
514
+ } else {
515
+ const as = c.data.as;
516
+ if (!as) {
517
+ throw new Error(
518
+ `Don't know how to generate data for column ${table.table}.${key} that has no \`as\``
519
+ );
324
520
  }
521
+ return makeGeneratorForColumn(config, table, uniqueColumns, key, as);
325
522
  }
326
- return new TestFactory(
327
- table,
328
- schema,
329
- uniqueFields,
330
- data,
331
- options
332
- );
523
+ return fn;
524
+ };
525
+ const tableFactory = (table, config) => {
526
+ const { shape } = table;
527
+ const fns = {
528
+ ...config?.extend
529
+ };
530
+ const uniqueColumns = /* @__PURE__ */ new Set();
531
+ for (const key in shape) {
532
+ if (fns[key]) continue;
533
+ const {
534
+ data: { indexes: indexes2, primaryKey: primaryKey2 }
535
+ } = shape[key];
536
+ if (primaryKey2) {
537
+ uniqueColumns.add(key);
538
+ continue;
539
+ }
540
+ if (!indexes2) continue;
541
+ for (const index of indexes2) {
542
+ if (index.options.unique) {
543
+ uniqueColumns.add(key);
544
+ break;
545
+ }
546
+ }
547
+ }
548
+ const { primaryKey, indexes } = table.internal.tableData;
549
+ if (primaryKey) {
550
+ for (const key of primaryKey.columns) {
551
+ if (fns[key]) continue;
552
+ uniqueColumns.add(key);
553
+ }
554
+ }
555
+ if (indexes) {
556
+ for (const index of indexes) {
557
+ if (index.options.unique) {
558
+ for (const item of index.columns) {
559
+ if ("column" in item) {
560
+ uniqueColumns.add(item.column);
561
+ }
562
+ }
563
+ }
564
+ }
565
+ }
566
+ for (const key in shape) {
567
+ if (fns[key]) continue;
568
+ const fn = makeGeneratorForColumn(
569
+ config || orchidCore.emptyObject,
570
+ table,
571
+ uniqueColumns,
572
+ key,
573
+ shape[key]
574
+ );
575
+ if (fn) fns[key] = fn;
576
+ }
577
+ return new TestFactory(table, fns, config);
333
578
  };
334
579
  const ormFactory = (orm, options) => {
335
580
  const factory = {};
@@ -339,11 +584,13 @@ const ormFactory = (orm, options) => {
339
584
  if (table && typeof table === "object" && "definedAs" in table) {
340
585
  Object.defineProperty(factory, key, {
341
586
  get() {
342
- var _a;
343
- return (_a = defined[key]) != null ? _a : defined[key] = tableFactory(
587
+ return defined[key] ?? (defined[key] = tableFactory(
344
588
  table,
345
- options
346
- );
589
+ {
590
+ ...options,
591
+ extend: options?.extend?.[key]
592
+ }
593
+ ));
347
594
  }
348
595
  });
349
596
  }