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