realitydb 1.3.1 → 1.4.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.
Files changed (2) hide show
  1. package/dist/index.js +643 -43
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4075,6 +4075,11 @@ function generateCompanyName(ctx) {
4075
4075
  return truncate(`${name} ${suffix}`, ctx.maxLength);
4076
4076
  }
4077
4077
  function generateText(ctx, mode) {
4078
+ if (ctx.isUnique && mode === "short") {
4079
+ const prefix = ctx.columnName.toUpperCase().slice(0, 3);
4080
+ const seq = String(ctx.rowIndex + 1).padStart(6, "0");
4081
+ return truncate(`${prefix}-${seq}`, ctx.maxLength);
4082
+ }
4078
4083
  const lengthMap = { short: 3, medium: 8, long: 20 };
4079
4084
  const wordCount = lengthMap[mode];
4080
4085
  const words = [];
@@ -4083,6 +4088,9 @@ function generateText(ctx, mode) {
4083
4088
  }
4084
4089
  let text = words.join(" ");
4085
4090
  text = text.charAt(0).toUpperCase() + text.slice(1);
4091
+ if (ctx.isUnique) {
4092
+ text = `${text} ${ctx.rowIndex + 1}`;
4093
+ }
4086
4094
  return truncate(text, ctx.maxLength);
4087
4095
  }
4088
4096
  function truncate(value, maxLength) {
@@ -4160,6 +4168,10 @@ function generateSku(ctx) {
4160
4168
  }
4161
4169
  return `SKU-${suffix}`;
4162
4170
  }
4171
+ function generateSequential(ctx, prefix, padLength) {
4172
+ const seq = String(ctx.rowIndex + 1).padStart(padLength, "0");
4173
+ return `${prefix}${seq}`;
4174
+ }
4163
4175
 
4164
4176
  // ../../packages/generators/dist/registry.js
4165
4177
  function createGeneratorRegistry() {
@@ -4212,6 +4224,11 @@ function createGeneratorRegistry() {
4212
4224
  if (name === "sku") {
4213
4225
  return (ctx) => generateSku(ctx);
4214
4226
  }
4227
+ if (name === "sequential") {
4228
+ const prefix = strategy.options?.["prefix"] ?? "";
4229
+ const padLength = strategy.options?.["padLength"] ?? 6;
4230
+ return (ctx) => generateSequential(ctx, prefix, padLength);
4231
+ }
4215
4232
  console.warn(`[databox] Unknown custom generator "${name}", falling back to text.`);
4216
4233
  return (ctx) => generateText(ctx, "short");
4217
4234
  }
@@ -4292,27 +4309,34 @@ function generateDataset(plan) {
4292
4309
  }
4293
4310
  const columnGenerators = tablePlan.columns.map((colPlan) => {
4294
4311
  if (colPlan.strategy.kind === "foreign_key" && colPlan.foreignKeyRef) {
4312
+ const isSelfRef = colPlan.foreignKeyRef.referencedTable === tableName;
4295
4313
  return {
4296
4314
  columnName: colPlan.columnName,
4297
4315
  generator: null,
4298
4316
  isForeignKey: true,
4317
+ isSelfReference: isSelfRef,
4299
4318
  foreignKeyRef: colPlan.foreignKeyRef,
4300
4319
  defaultValueMode: colPlan.defaultValueMode,
4301
4320
  fixedValue: colPlan.fixedValue,
4302
- maxLength: colPlan.maxLength
4321
+ maxLength: colPlan.maxLength,
4322
+ isUnique: colPlan.isUnique,
4323
+ nullable: colPlan.nullable
4303
4324
  };
4304
4325
  }
4305
4326
  return {
4306
4327
  columnName: colPlan.columnName,
4307
4328
  generator: registry.getGenerator(colPlan.strategy),
4308
4329
  isForeignKey: false,
4330
+ isSelfReference: false,
4309
4331
  defaultValueMode: colPlan.defaultValueMode,
4310
4332
  fixedValue: colPlan.fixedValue,
4311
- maxLength: colPlan.maxLength
4333
+ maxLength: colPlan.maxLength,
4334
+ isUnique: colPlan.isUnique
4312
4335
  };
4313
4336
  });
4314
4337
  const columns = tablePlan.columns.map((c) => c.columnName);
4315
4338
  const rows = [];
4339
+ const selfRefNullFraction = 0.3;
4316
4340
  for (let rowIndex = 0; rowIndex < tablePlan.rowCount; rowIndex++) {
4317
4341
  const row = {};
4318
4342
  for (const colGen of columnGenerators) {
@@ -4322,13 +4346,22 @@ function generateDataset(plan) {
4322
4346
  tableName,
4323
4347
  columnName: colGen.columnName,
4324
4348
  allGeneratedTables,
4325
- maxLength: colGen.maxLength
4349
+ maxLength: colGen.maxLength,
4350
+ isUnique: colGen.isUnique,
4351
+ currentTableRows: rows
4326
4352
  };
4327
4353
  if (colGen.defaultValueMode === "db_default" || colGen.defaultValueMode === "fixed") {
4328
4354
  row[colGen.columnName] = colGen.fixedValue ?? null;
4329
4355
  continue;
4330
4356
  }
4331
- if (colGen.isForeignKey && colGen.foreignKeyRef) {
4357
+ if (colGen.isSelfReference && colGen.foreignKeyRef) {
4358
+ if (rows.length === 0 || rowIndex < tablePlan.rowCount * selfRefNullFraction) {
4359
+ row[colGen.columnName] = null;
4360
+ } else {
4361
+ const parentRow = seed.pick(rows);
4362
+ row[colGen.columnName] = parentRow[colGen.foreignKeyRef.referencedColumn];
4363
+ }
4364
+ } else if (colGen.isForeignKey && colGen.foreignKeyRef) {
4332
4365
  row[colGen.columnName] = resolveForeignKey(ctx, colGen.foreignKeyRef);
4333
4366
  } else if (colGen.generator) {
4334
4367
  row[colGen.columnName] = colGen.generator(ctx);
@@ -8676,13 +8709,47 @@ function getSimulationProfile(name) {
8676
8709
  // ../../packages/templates/dist/domains/saas.js
8677
8710
  var saasTemplate = {
8678
8711
  name: "saas",
8679
- version: "1.0",
8680
- description: "SaaS subscription business with users, plans, and payments",
8681
- targetTables: ["users", "plans", "subscriptions", "payments"],
8712
+ version: "2.0",
8713
+ description: "SaaS subscription business with organizations, users, plans, invoices, and payments",
8714
+ targetTables: ["organizations", "users", "plans", "subscriptions", "invoices", "payments"],
8682
8715
  tableConfigs: /* @__PURE__ */ new Map([
8716
+ ["organizations", {
8717
+ tableName: "organizations",
8718
+ matchPattern: ["organizations", "*org*", "teams", "companies", "*team*", "*company*"],
8719
+ rowCountMultiplier: 0.3,
8720
+ columnOverrides: [
8721
+ {
8722
+ columnName: "name",
8723
+ strategy: { kind: "company_name" }
8724
+ },
8725
+ {
8726
+ columnName: "slug",
8727
+ strategy: { kind: "text", options: { mode: "short" } }
8728
+ },
8729
+ {
8730
+ columnName: "industry",
8731
+ strategy: {
8732
+ kind: "enum",
8733
+ options: {
8734
+ values: ["Technology", "Healthcare", "Finance", "Education", "Retail", "Media", "Manufacturing", "Other"],
8735
+ weights: [0.25, 0.12, 0.12, 0.1, 0.1, 0.08, 0.08, 0.15]
8736
+ }
8737
+ }
8738
+ },
8739
+ {
8740
+ columnName: "employee_count",
8741
+ strategy: { kind: "integer", options: { min: 1, max: 5e3 } }
8742
+ },
8743
+ {
8744
+ columnName: "created_at",
8745
+ strategy: { kind: "timestamp", options: { mode: "past" } }
8746
+ }
8747
+ ]
8748
+ }],
8683
8749
  ["users", {
8684
8750
  tableName: "users",
8685
- matchPattern: ["users", "accounts", "*user*", "*account*"],
8751
+ matchPattern: ["users", "*user*"],
8752
+ rowCountMultiplier: 1,
8686
8753
  columnOverrides: [
8687
8754
  { columnName: "email", strategy: { kind: "email" } },
8688
8755
  {
@@ -8690,6 +8757,30 @@ var saasTemplate = {
8690
8757
  matchPattern: ["full_name", "name", "display_name"],
8691
8758
  strategy: { kind: "full_name" }
8692
8759
  },
8760
+ {
8761
+ columnName: "role",
8762
+ strategy: {
8763
+ kind: "enum",
8764
+ options: {
8765
+ values: ["owner", "admin", "member", "viewer"],
8766
+ weights: [0.05, 0.1, 0.7, 0.15]
8767
+ }
8768
+ }
8769
+ },
8770
+ {
8771
+ columnName: "status",
8772
+ strategy: {
8773
+ kind: "enum",
8774
+ options: {
8775
+ values: ["active", "inactive", "suspended", "invited"],
8776
+ weights: [0.8, 0.08, 0.02, 0.1]
8777
+ }
8778
+ }
8779
+ },
8780
+ {
8781
+ columnName: "last_login_at",
8782
+ strategy: { kind: "timestamp", options: { mode: "recent" } }
8783
+ },
8693
8784
  {
8694
8785
  columnName: "created_at",
8695
8786
  strategy: { kind: "timestamp", options: { mode: "past" } }
@@ -8699,14 +8790,25 @@ var saasTemplate = {
8699
8790
  ["plans", {
8700
8791
  tableName: "plans",
8701
8792
  matchPattern: ["plans", "tiers", "pricing", "*plan*", "*tier*", "*pricing*"],
8793
+ rowCountMultiplier: 0.1,
8702
8794
  columnOverrides: [
8703
8795
  {
8704
8796
  columnName: "name",
8705
8797
  strategy: {
8706
8798
  kind: "enum",
8707
8799
  options: {
8708
- values: ["Starter", "Professional", "Business", "Enterprise"],
8709
- weights: [0.35, 0.35, 0.2, 0.1]
8800
+ values: ["Free", "Starter", "Professional", "Business", "Enterprise"],
8801
+ weights: [0.1, 0.3, 0.3, 0.2, 0.1]
8802
+ }
8803
+ }
8804
+ },
8805
+ {
8806
+ columnName: "tier",
8807
+ strategy: {
8808
+ kind: "enum",
8809
+ options: {
8810
+ values: ["free", "starter", "professional", "business", "enterprise"],
8811
+ weights: [0.1, 0.3, 0.3, 0.2, 0.1]
8710
8812
  }
8711
8813
  }
8712
8814
  },
@@ -8731,23 +8833,56 @@ var saasTemplate = {
8731
8833
  weights: [0.65, 0.35]
8732
8834
  }
8733
8835
  }
8836
+ },
8837
+ {
8838
+ columnName: "trial_days",
8839
+ strategy: {
8840
+ kind: "enum",
8841
+ options: {
8842
+ values: [0, 7, 14, 30],
8843
+ weights: [0.2, 0.15, 0.45, 0.2]
8844
+ }
8845
+ }
8846
+ },
8847
+ {
8848
+ columnName: "is_active",
8849
+ strategy: { kind: "boolean", options: { trueWeight: 0.9 } }
8734
8850
  }
8735
8851
  ]
8736
8852
  }],
8737
8853
  ["subscriptions", {
8738
8854
  tableName: "subscriptions",
8739
8855
  matchPattern: ["subscriptions", "*subscription*"],
8856
+ rowCountMultiplier: 1.2,
8740
8857
  columnOverrides: [
8741
8858
  {
8742
8859
  columnName: "status",
8743
8860
  strategy: {
8744
8861
  kind: "enum",
8745
8862
  options: {
8746
- values: ["active", "trialing", "canceled", "past_due", "paused"],
8747
- weights: [0.65, 0.12, 0.1, 0.08, 0.05]
8863
+ values: ["active", "trialing", "past_due", "canceled", "paused"],
8864
+ weights: [0.6, 0.12, 0.08, 0.15, 0.05]
8748
8865
  }
8749
8866
  }
8750
8867
  },
8868
+ {
8869
+ columnName: "trial_ends_at",
8870
+ strategy: { kind: "timestamp", options: { mode: "past" } },
8871
+ description: "Nullable \u2014 null for non-trial subscriptions"
8872
+ },
8873
+ {
8874
+ columnName: "current_period_start",
8875
+ strategy: { kind: "timestamp", options: { mode: "past" } }
8876
+ },
8877
+ {
8878
+ columnName: "current_period_end",
8879
+ strategy: { kind: "timestamp", options: { mode: "past" } }
8880
+ },
8881
+ {
8882
+ columnName: "started_at",
8883
+ matchPattern: ["started_at", "start_date", "begins_at"],
8884
+ strategy: { kind: "timestamp", options: { mode: "past" } }
8885
+ },
8751
8886
  {
8752
8887
  columnName: "canceled_at",
8753
8888
  strategy: { kind: "timestamp", options: { mode: "past" } },
@@ -8755,20 +8890,61 @@ var saasTemplate = {
8755
8890
  }
8756
8891
  ]
8757
8892
  }],
8758
- ["payments", {
8759
- tableName: "payments",
8760
- matchPattern: ["payments", "invoices", "charges", "*payment*", "*invoice*", "*charge*"],
8893
+ ["invoices", {
8894
+ tableName: "invoices",
8895
+ matchPattern: ["invoices", "*invoice*"],
8896
+ rowCountMultiplier: 3,
8761
8897
  columnOverrides: [
8898
+ {
8899
+ columnName: "amount_cents",
8900
+ matchPattern: ["amount_cents", "amount", "total", "total_cents"],
8901
+ strategy: { kind: "money", options: { min: 0, max: 5e5 } }
8902
+ },
8903
+ {
8904
+ columnName: "currency",
8905
+ strategy: {
8906
+ kind: "enum",
8907
+ options: {
8908
+ values: ["USD", "EUR", "GBP", "CAD"],
8909
+ weights: [0.6, 0.2, 0.12, 0.08]
8910
+ }
8911
+ }
8912
+ },
8762
8913
  {
8763
8914
  columnName: "status",
8764
8915
  strategy: {
8765
8916
  kind: "enum",
8766
8917
  options: {
8767
- values: ["succeeded", "pending", "failed", "refunded"],
8768
- weights: [0.85, 0.05, 0.05, 0.05]
8918
+ values: ["paid", "open", "past_due", "void", "uncollectible"],
8919
+ weights: [0.7, 0.1, 0.08, 0.07, 0.05]
8769
8920
  }
8770
8921
  }
8771
8922
  },
8923
+ {
8924
+ columnName: "due_date",
8925
+ strategy: { kind: "timestamp", options: { mode: "past" } }
8926
+ },
8927
+ {
8928
+ columnName: "paid_at",
8929
+ strategy: { kind: "timestamp", options: { mode: "past" } },
8930
+ description: "Nullable \u2014 null for unpaid invoices"
8931
+ },
8932
+ {
8933
+ columnName: "created_at",
8934
+ strategy: { kind: "timestamp", options: { mode: "past" } }
8935
+ }
8936
+ ]
8937
+ }],
8938
+ ["payments", {
8939
+ tableName: "payments",
8940
+ matchPattern: ["payments", "*payment*"],
8941
+ rowCountMultiplier: 3,
8942
+ columnOverrides: [
8943
+ {
8944
+ columnName: "amount_cents",
8945
+ matchPattern: ["amount_cents", "amount", "total", "total_cents"],
8946
+ strategy: { kind: "money", options: { min: 999, max: 49999 } }
8947
+ },
8772
8948
  {
8773
8949
  columnName: "currency",
8774
8950
  strategy: {
@@ -8780,9 +8956,40 @@ var saasTemplate = {
8780
8956
  }
8781
8957
  },
8782
8958
  {
8783
- columnName: "amount_cents",
8784
- matchPattern: ["amount_cents", "amount", "total", "total_cents"],
8785
- strategy: { kind: "money", options: { min: 999, max: 49999 } }
8959
+ columnName: "payment_method",
8960
+ strategy: {
8961
+ kind: "enum",
8962
+ options: {
8963
+ values: ["card", "bank_transfer", "paypal", "wire"],
8964
+ weights: [0.65, 0.15, 0.12, 0.08]
8965
+ }
8966
+ }
8967
+ },
8968
+ {
8969
+ columnName: "status",
8970
+ strategy: {
8971
+ kind: "enum",
8972
+ options: {
8973
+ values: ["succeeded", "failed", "pending", "refunded"],
8974
+ weights: [0.82, 0.08, 0.05, 0.05]
8975
+ }
8976
+ }
8977
+ },
8978
+ {
8979
+ columnName: "failure_reason",
8980
+ strategy: {
8981
+ kind: "enum",
8982
+ options: {
8983
+ values: ["card_declined", "insufficient_funds", "expired_card", "processing_error"],
8984
+ weights: [0.35, 0.3, 0.2, 0.15]
8985
+ }
8986
+ },
8987
+ description: "Nullable \u2014 null for successful payments"
8988
+ },
8989
+ {
8990
+ columnName: "paid_at",
8991
+ matchPattern: ["paid_at", "payment_date", "charged_at"],
8992
+ strategy: { kind: "timestamp", options: { mode: "past" } }
8786
8993
  }
8787
8994
  ]
8788
8995
  }]
@@ -8792,23 +8999,74 @@ var saasTemplate = {
8792
8999
  // ../../packages/templates/dist/domains/ecommerce.js
8793
9000
  var ecommerceTemplate = {
8794
9001
  name: "ecommerce",
8795
- version: "1.0",
8796
- description: "E-commerce store with products, orders, and customers",
8797
- targetTables: ["customers", "products", "orders", "order_items"],
9002
+ version: "2.0",
9003
+ description: "E-commerce store with categories, products, orders, and reviews",
9004
+ targetTables: ["customers", "categories", "products", "orders", "order_items", "reviews"],
8798
9005
  tableConfigs: /* @__PURE__ */ new Map([
8799
9006
  ["customers", {
8800
9007
  tableName: "customers",
8801
9008
  matchPattern: ["customers", "*customer*"],
9009
+ rowCountMultiplier: 1,
8802
9010
  columnOverrides: [
8803
9011
  { columnName: "email", strategy: { kind: "email" } },
8804
9012
  { columnName: "first_name", strategy: { kind: "first_name" } },
8805
9013
  { columnName: "last_name", strategy: { kind: "last_name" } },
8806
- { columnName: "phone", strategy: { kind: "phone" } }
9014
+ { columnName: "phone", strategy: { kind: "phone" } },
9015
+ {
9016
+ columnName: "city",
9017
+ strategy: {
9018
+ kind: "enum",
9019
+ options: {
9020
+ values: ["New York", "Los Angeles", "London", "Toronto", "Berlin", "Sydney", "Tokyo", "San Francisco", "Chicago", "Austin"]
9021
+ }
9022
+ }
9023
+ },
9024
+ {
9025
+ columnName: "country",
9026
+ strategy: {
9027
+ kind: "enum",
9028
+ options: {
9029
+ values: ["US", "CA", "UK", "DE", "FR", "AU", "JP", "BR", "IN", "Other"],
9030
+ weights: [0.4, 0.08, 0.1, 0.08, 0.06, 0.05, 0.05, 0.04, 0.04, 0.1]
9031
+ }
9032
+ }
9033
+ },
9034
+ {
9035
+ columnName: "lifetime_value_cents",
9036
+ strategy: { kind: "money", options: { min: 0, max: 2e6 } }
9037
+ },
9038
+ {
9039
+ columnName: "created_at",
9040
+ matchPattern: ["created_at", "registered_at", "signed_up_at"],
9041
+ strategy: { kind: "timestamp", options: { mode: "past" } }
9042
+ }
9043
+ ]
9044
+ }],
9045
+ ["categories", {
9046
+ tableName: "categories",
9047
+ matchPattern: ["categories", "*categor*"],
9048
+ rowCountMultiplier: 0.2,
9049
+ columnOverrides: [
9050
+ {
9051
+ columnName: "name",
9052
+ strategy: {
9053
+ kind: "enum",
9054
+ options: {
9055
+ values: ["Electronics", "Clothing", "Home & Garden", "Sports", "Books", "Toys", "Beauty", "Food & Drink", "Automotive", "Office"],
9056
+ weights: [0.18, 0.16, 0.12, 0.1, 0.1, 0.08, 0.08, 0.06, 0.06, 0.06]
9057
+ }
9058
+ }
9059
+ },
9060
+ {
9061
+ columnName: "slug",
9062
+ strategy: { kind: "text", options: { mode: "short" } }
9063
+ }
8807
9064
  ]
8808
9065
  }],
8809
9066
  ["products", {
8810
9067
  tableName: "products",
8811
9068
  matchPattern: ["products", "items", "catalog", "*product*", "*item*", "*catalog*"],
9069
+ rowCountMultiplier: 0.5,
8812
9070
  columnOverrides: [
8813
9071
  {
8814
9072
  columnName: "name",
@@ -8849,6 +9107,20 @@ var ecommerceTemplate = {
8849
9107
  matchPattern: ["price_cents", "price"],
8850
9108
  strategy: { kind: "money", options: { min: 499, max: 29999 } }
8851
9109
  },
9110
+ {
9111
+ columnName: "compare_at_price_cents",
9112
+ strategy: { kind: "money", options: { min: 0, max: 2e5 } },
9113
+ description: "Nullable \u2014 original price before discount"
9114
+ },
9115
+ {
9116
+ columnName: "brand",
9117
+ strategy: {
9118
+ kind: "enum",
9119
+ options: {
9120
+ values: ["Acme", "NovaCore", "PeakGear", "CraftLine", "TrueForm", "EverBright", "Nexus", "Primewave", "Solidcraft", "Zenith"]
9121
+ }
9122
+ }
9123
+ },
8852
9124
  {
8853
9125
  columnName: "category",
8854
9126
  strategy: {
@@ -8863,15 +9135,28 @@ var ecommerceTemplate = {
8863
9135
  columnName: "sku",
8864
9136
  strategy: { kind: "custom", options: { name: "sku" } }
8865
9137
  },
9138
+ {
9139
+ columnName: "rating",
9140
+ strategy: { kind: "float", options: { min: 1, max: 5 } }
9141
+ },
9142
+ {
9143
+ columnName: "review_count",
9144
+ strategy: { kind: "integer", options: { min: 0, max: 500 } }
9145
+ },
8866
9146
  {
8867
9147
  columnName: "in_stock",
8868
9148
  strategy: { kind: "boolean", options: { trueWeight: 0.85 } }
9149
+ },
9150
+ {
9151
+ columnName: "created_at",
9152
+ strategy: { kind: "timestamp", options: { mode: "past" } }
8869
9153
  }
8870
9154
  ]
8871
9155
  }],
8872
9156
  ["orders", {
8873
9157
  tableName: "orders",
8874
9158
  matchPattern: ["orders", "purchases", "*order*", "*purchase*"],
9159
+ rowCountMultiplier: 2.5,
8875
9160
  columnOverrides: [
8876
9161
  {
8877
9162
  columnName: "status",
@@ -8879,7 +9164,7 @@ var ecommerceTemplate = {
8879
9164
  kind: "enum",
8880
9165
  options: {
8881
9166
  values: ["delivered", "shipped", "processing", "pending", "canceled", "returned"],
8882
- weights: [0.45, 0.15, 0.12, 0.1, 0.1, 0.08]
9167
+ weights: [0.4, 0.15, 0.12, 0.1, 0.13, 0.1]
8883
9168
  }
8884
9169
  }
8885
9170
  },
@@ -8888,6 +9173,10 @@ var ecommerceTemplate = {
8888
9173
  matchPattern: ["total_cents", "total", "amount"],
8889
9174
  strategy: { kind: "money", options: { min: 499, max: 99999 } }
8890
9175
  },
9176
+ {
9177
+ columnName: "discount_cents",
9178
+ strategy: { kind: "money", options: { min: 0, max: 5e4 } }
9179
+ },
8891
9180
  {
8892
9181
  columnName: "currency",
8893
9182
  strategy: {
@@ -8897,12 +9186,30 @@ var ecommerceTemplate = {
8897
9186
  weights: [0.65, 0.22, 0.13]
8898
9187
  }
8899
9188
  }
9189
+ },
9190
+ {
9191
+ columnName: "ordered_at",
9192
+ matchPattern: ["ordered_at", "order_date", "placed_at"],
9193
+ strategy: { kind: "timestamp", options: { mode: "past" } }
9194
+ },
9195
+ {
9196
+ columnName: "shipped_at",
9197
+ matchPattern: ["shipped_at", "ship_date"],
9198
+ strategy: { kind: "timestamp", options: { mode: "past" } },
9199
+ description: "Nullable \u2014 null for pending/processing orders"
9200
+ },
9201
+ {
9202
+ columnName: "delivered_at",
9203
+ matchPattern: ["delivered_at", "delivery_date"],
9204
+ strategy: { kind: "timestamp", options: { mode: "past" } },
9205
+ description: "Nullable \u2014 null for non-delivered orders"
8900
9206
  }
8901
9207
  ]
8902
9208
  }],
8903
9209
  ["order_items", {
8904
9210
  tableName: "order_items",
8905
9211
  matchPattern: ["order_items", "line_items", "cart_items", "*order_item*", "*line_item*"],
9212
+ rowCountMultiplier: 3.5,
8906
9213
  columnOverrides: [
8907
9214
  {
8908
9215
  columnName: "quantity",
@@ -8914,6 +9221,39 @@ var ecommerceTemplate = {
8914
9221
  strategy: { kind: "money", options: { min: 499, max: 29999 } }
8915
9222
  }
8916
9223
  ]
9224
+ }],
9225
+ ["reviews", {
9226
+ tableName: "reviews",
9227
+ matchPattern: ["reviews", "*review*", "ratings", "*rating*"],
9228
+ rowCountMultiplier: 2,
9229
+ columnOverrides: [
9230
+ {
9231
+ columnName: "rating",
9232
+ strategy: {
9233
+ kind: "enum",
9234
+ options: {
9235
+ values: [5, 4, 3, 2, 1],
9236
+ weights: [0.35, 0.3, 0.15, 0.1, 0.1]
9237
+ }
9238
+ }
9239
+ },
9240
+ {
9241
+ columnName: "title",
9242
+ strategy: { kind: "text", options: { mode: "short" } }
9243
+ },
9244
+ {
9245
+ columnName: "body",
9246
+ strategy: { kind: "text", options: { mode: "medium" } }
9247
+ },
9248
+ {
9249
+ columnName: "verified_purchase",
9250
+ strategy: { kind: "boolean", options: { trueWeight: 0.75 } }
9251
+ },
9252
+ {
9253
+ columnName: "created_at",
9254
+ strategy: { kind: "timestamp", options: { mode: "past" } }
9255
+ }
9256
+ ]
8917
9257
  }]
8918
9258
  ])
8919
9259
  };
@@ -8921,17 +9261,19 @@ var ecommerceTemplate = {
8921
9261
  // ../../packages/templates/dist/domains/education.js
8922
9262
  var educationTemplate = {
8923
9263
  name: "education",
8924
- version: "1.0",
8925
- description: "K-12 school system with teachers, classes, students, and grades",
9264
+ version: "2.0",
9265
+ description: "K-12 school system with teachers, classes, students, grades, and attendance",
8926
9266
  targetTables: ["teachers", "classes", "students", "enrollments", "grades", "attendance"],
8927
9267
  tableConfigs: /* @__PURE__ */ new Map([
8928
9268
  ["teachers", {
8929
9269
  tableName: "teachers",
8930
9270
  matchPattern: ["teachers", "instructors", "faculty", "*teacher*", "*instructor*", "*faculty*"],
9271
+ rowCountMultiplier: 0.2,
8931
9272
  columnOverrides: [
8932
9273
  { columnName: "email", strategy: { kind: "email" } },
8933
9274
  { columnName: "first_name", strategy: { kind: "first_name" } },
8934
9275
  { columnName: "last_name", strategy: { kind: "last_name" } },
9276
+ { columnName: "phone", strategy: { kind: "phone" } },
8935
9277
  {
8936
9278
  columnName: "department",
8937
9279
  strategy: {
@@ -8941,12 +9283,17 @@ var educationTemplate = {
8941
9283
  weights: [0.18, 0.16, 0.16, 0.12, 0.1, 0.1, 0.1, 0.08]
8942
9284
  }
8943
9285
  }
9286
+ },
9287
+ {
9288
+ columnName: "hire_date",
9289
+ strategy: { kind: "timestamp", options: { mode: "past" } }
8944
9290
  }
8945
9291
  ]
8946
9292
  }],
8947
9293
  ["classes", {
8948
9294
  tableName: "classes",
8949
9295
  matchPattern: ["classes", "courses", "sections", "*class*", "*course*", "*section*"],
9296
+ rowCountMultiplier: 0.5,
8950
9297
  columnOverrides: [
8951
9298
  {
8952
9299
  columnName: "name",
@@ -8979,7 +9326,7 @@ var educationTemplate = {
8979
9326
  weights: [
8980
9327
  0.06,
8981
9328
  0.05,
8982
- 0.05,
9329
+ 0.06,
8983
9330
  0.04,
8984
9331
  0.06,
8985
9332
  0.05,
@@ -8987,7 +9334,7 @@ var educationTemplate = {
8987
9334
  0.04,
8988
9335
  0.06,
8989
9336
  0.05,
8990
- 0.04,
9337
+ 0.05,
8991
9338
  0.03,
8992
9339
  0.05,
8993
9340
  0.05,
@@ -8997,7 +9344,7 @@ var educationTemplate = {
8997
9344
  0.05,
8998
9345
  0.04,
8999
9346
  0.04,
9000
- 0.04
9347
+ 0.06
9001
9348
  ]
9002
9349
  }
9003
9350
  }
@@ -9035,6 +9382,7 @@ var educationTemplate = {
9035
9382
  ["students", {
9036
9383
  tableName: "students",
9037
9384
  matchPattern: ["students", "pupils", "learners", "*student*", "*pupil*", "*learner*"],
9385
+ rowCountMultiplier: 1,
9038
9386
  columnOverrides: [
9039
9387
  { columnName: "email", strategy: { kind: "email" } },
9040
9388
  { columnName: "first_name", strategy: { kind: "first_name" } },
@@ -9042,12 +9390,31 @@ var educationTemplate = {
9042
9390
  {
9043
9391
  columnName: "grade_level",
9044
9392
  strategy: { kind: "integer", options: { min: 6, max: 12 } }
9393
+ },
9394
+ {
9395
+ columnName: "date_of_birth",
9396
+ strategy: { kind: "timestamp", options: { mode: "past" } }
9397
+ },
9398
+ {
9399
+ columnName: "gender",
9400
+ strategy: {
9401
+ kind: "enum",
9402
+ options: {
9403
+ values: ["Male", "Female", "Non-binary"],
9404
+ weights: [0.49, 0.49, 0.02]
9405
+ }
9406
+ }
9407
+ },
9408
+ {
9409
+ columnName: "enrolled_at",
9410
+ strategy: { kind: "timestamp", options: { mode: "past" } }
9045
9411
  }
9046
9412
  ]
9047
9413
  }],
9048
9414
  ["enrollments", {
9049
9415
  tableName: "enrollments",
9050
9416
  matchPattern: ["enrollments", "registrations", "*enrollment*", "*registration*"],
9417
+ rowCountMultiplier: 3,
9051
9418
  columnOverrides: [
9052
9419
  {
9053
9420
  columnName: "status",
@@ -9058,12 +9425,17 @@ var educationTemplate = {
9058
9425
  weights: [0.75, 0.05, 0.15, 0.05]
9059
9426
  }
9060
9427
  }
9428
+ },
9429
+ {
9430
+ columnName: "enrolled_at",
9431
+ strategy: { kind: "timestamp", options: { mode: "past" } }
9061
9432
  }
9062
9433
  ]
9063
9434
  }],
9064
9435
  ["grades", {
9065
9436
  tableName: "grades",
9066
9437
  matchPattern: ["grades", "scores", "assessments", "marks", "*grade*", "*score*", "*assessment*", "*mark*"],
9438
+ rowCountMultiplier: 5,
9067
9439
  columnOverrides: [
9068
9440
  {
9069
9441
  columnName: "assignment_name",
@@ -9102,6 +9474,16 @@ var educationTemplate = {
9102
9474
  }
9103
9475
  }
9104
9476
  },
9477
+ {
9478
+ columnName: "assignment_type",
9479
+ strategy: {
9480
+ kind: "enum",
9481
+ options: {
9482
+ values: ["homework", "quiz", "test", "project", "participation", "final_exam"],
9483
+ weights: [0.25, 0.2, 0.2, 0.15, 0.1, 0.1]
9484
+ }
9485
+ }
9486
+ },
9105
9487
  {
9106
9488
  columnName: "score",
9107
9489
  strategy: { kind: "float", options: { min: 40, max: 100 } }
@@ -9115,12 +9497,17 @@ var educationTemplate = {
9115
9497
  weights: [0.6, 0.2, 0.15, 0.05]
9116
9498
  }
9117
9499
  }
9500
+ },
9501
+ {
9502
+ columnName: "graded_at",
9503
+ strategy: { kind: "timestamp", options: { mode: "past" } }
9118
9504
  }
9119
9505
  ]
9120
9506
  }],
9121
9507
  ["attendance", {
9122
9508
  tableName: "attendance",
9123
9509
  matchPattern: ["attendance", "*attendance*"],
9510
+ rowCountMultiplier: 8,
9124
9511
  columnOverrides: [
9125
9512
  {
9126
9513
  columnName: "status",
@@ -9144,13 +9531,14 @@ var educationTemplate = {
9144
9531
  // ../../packages/templates/dist/domains/fintech.js
9145
9532
  var fintechTemplate = {
9146
9533
  name: "fintech",
9147
- version: "1.0",
9148
- description: "Financial services with accounts, transactions, fraud alerts, and settlements",
9534
+ version: "2.0",
9535
+ description: "Financial services with accounts, transactions, fraud alerts, settlements, and chargebacks",
9149
9536
  targetTables: ["accounts", "transactions", "fraud_alerts", "settlements", "chargebacks"],
9150
9537
  tableConfigs: /* @__PURE__ */ new Map([
9151
9538
  ["accounts", {
9152
9539
  tableName: "accounts",
9153
9540
  matchPattern: ["accounts", "*account*"],
9541
+ rowCountMultiplier: 1,
9154
9542
  columnOverrides: [
9155
9543
  {
9156
9544
  columnName: "account_type",
@@ -9194,19 +9582,33 @@ var fintechTemplate = {
9194
9582
  columnName: "email",
9195
9583
  strategy: { kind: "email" }
9196
9584
  },
9585
+ {
9586
+ columnName: "phone",
9587
+ strategy: { kind: "phone" }
9588
+ },
9197
9589
  {
9198
9590
  columnName: "account_number",
9199
9591
  strategy: { kind: "text", options: { mode: "short" } }
9200
9592
  },
9593
+ {
9594
+ columnName: "routing_number",
9595
+ strategy: { kind: "text", options: { mode: "short" } }
9596
+ },
9201
9597
  {
9202
9598
  columnName: "opened_at",
9203
9599
  strategy: { kind: "timestamp", options: { mode: "past" } }
9600
+ },
9601
+ {
9602
+ columnName: "closed_at",
9603
+ strategy: { kind: "timestamp", options: { mode: "past" } },
9604
+ description: "Nullable \u2014 null for active accounts"
9204
9605
  }
9205
9606
  ]
9206
9607
  }],
9207
9608
  ["transactions", {
9208
9609
  tableName: "transactions",
9209
9610
  matchPattern: ["transactions", "*transaction*", "*transfer*"],
9611
+ rowCountMultiplier: 5,
9210
9612
  columnOverrides: [
9211
9613
  {
9212
9614
  columnName: "transaction_type",
@@ -9222,6 +9624,10 @@ var fintechTemplate = {
9222
9624
  columnName: "amount_cents",
9223
9625
  strategy: { kind: "money", options: { min: 100, max: 5e5 } }
9224
9626
  },
9627
+ {
9628
+ columnName: "fee_cents",
9629
+ strategy: { kind: "money", options: { min: 0, max: 5e3 } }
9630
+ },
9225
9631
  {
9226
9632
  columnName: "currency",
9227
9633
  strategy: {
@@ -9246,6 +9652,24 @@ var fintechTemplate = {
9246
9652
  columnName: "description",
9247
9653
  strategy: { kind: "text", options: { mode: "short" } }
9248
9654
  },
9655
+ {
9656
+ columnName: "counterparty_name",
9657
+ strategy: { kind: "company_name" }
9658
+ },
9659
+ {
9660
+ columnName: "category",
9661
+ strategy: {
9662
+ kind: "enum",
9663
+ options: {
9664
+ values: ["groceries", "restaurants", "transportation", "entertainment", "utilities", "healthcare", "shopping", "travel", "education", "transfer", "salary", "investment"],
9665
+ weights: [0.12, 0.1, 0.08, 0.08, 0.07, 0.06, 0.1, 0.05, 0.04, 0.12, 0.1, 0.08]
9666
+ }
9667
+ }
9668
+ },
9669
+ {
9670
+ columnName: "reference_id",
9671
+ strategy: { kind: "text", options: { mode: "short" } }
9672
+ },
9249
9673
  {
9250
9674
  columnName: "created_at",
9251
9675
  strategy: { kind: "timestamp", options: { mode: "past" } }
@@ -9255,6 +9679,7 @@ var fintechTemplate = {
9255
9679
  ["fraud_alerts", {
9256
9680
  tableName: "fraud_alerts",
9257
9681
  matchPattern: ["fraud_alerts", "*fraud*", "*alert*"],
9682
+ rowCountMultiplier: 0.3,
9258
9683
  columnOverrides: [
9259
9684
  {
9260
9685
  columnName: "alert_type",
@@ -9293,12 +9718,18 @@ var fintechTemplate = {
9293
9718
  {
9294
9719
  columnName: "created_at",
9295
9720
  strategy: { kind: "timestamp", options: { mode: "past" } }
9721
+ },
9722
+ {
9723
+ columnName: "resolved_at",
9724
+ strategy: { kind: "timestamp", options: { mode: "past" } },
9725
+ description: "Nullable \u2014 null for open/investigating alerts"
9296
9726
  }
9297
9727
  ]
9298
9728
  }],
9299
9729
  ["settlements", {
9300
9730
  tableName: "settlements",
9301
9731
  matchPattern: ["settlements", "*settlement*"],
9732
+ rowCountMultiplier: 1.5,
9302
9733
  columnOverrides: [
9303
9734
  {
9304
9735
  columnName: "settlement_type",
@@ -9324,6 +9755,11 @@ var fintechTemplate = {
9324
9755
  }
9325
9756
  }
9326
9757
  },
9758
+ {
9759
+ columnName: "settled_at",
9760
+ strategy: { kind: "timestamp", options: { mode: "past" } },
9761
+ description: "Nullable \u2014 null for pending settlements"
9762
+ },
9327
9763
  {
9328
9764
  columnName: "created_at",
9329
9765
  strategy: { kind: "timestamp", options: { mode: "past" } }
@@ -9333,6 +9769,7 @@ var fintechTemplate = {
9333
9769
  ["chargebacks", {
9334
9770
  tableName: "chargebacks",
9335
9771
  matchPattern: ["chargebacks", "*chargeback*", "*dispute*"],
9772
+ rowCountMultiplier: 0.2,
9336
9773
  columnOverrides: [
9337
9774
  {
9338
9775
  columnName: "reason",
@@ -9361,6 +9798,11 @@ var fintechTemplate = {
9361
9798
  {
9362
9799
  columnName: "filed_at",
9363
9800
  strategy: { kind: "timestamp", options: { mode: "past" } }
9801
+ },
9802
+ {
9803
+ columnName: "resolved_at",
9804
+ strategy: { kind: "timestamp", options: { mode: "past" } },
9805
+ description: "Nullable \u2014 null for open/under_review chargebacks"
9364
9806
  }
9365
9807
  ]
9366
9808
  }]
@@ -9370,13 +9812,14 @@ var fintechTemplate = {
9370
9812
  // ../../packages/templates/dist/domains/healthcare.js
9371
9813
  var healthcareTemplate = {
9372
9814
  name: "healthcare",
9373
- version: "1.0",
9374
- description: "Healthcare system with patients, providers, encounters, diagnoses, and billing",
9375
- targetTables: ["patients", "providers", "encounters", "diagnoses", "billing"],
9815
+ version: "2.0",
9816
+ description: "Healthcare system with patients, providers, encounters, diagnoses, billing, medications, and vitals",
9817
+ targetTables: ["patients", "providers", "encounters", "diagnoses", "billing", "medications", "vitals"],
9376
9818
  tableConfigs: /* @__PURE__ */ new Map([
9377
9819
  ["patients", {
9378
9820
  tableName: "patients",
9379
9821
  matchPattern: ["patients", "*patient*"],
9822
+ rowCountMultiplier: 1,
9380
9823
  columnOverrides: [
9381
9824
  {
9382
9825
  columnName: "first_name",
@@ -9404,6 +9847,16 @@ var healthcareTemplate = {
9404
9847
  }
9405
9848
  }
9406
9849
  },
9850
+ {
9851
+ columnName: "blood_type",
9852
+ strategy: {
9853
+ kind: "enum",
9854
+ options: {
9855
+ values: ["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"],
9856
+ weights: [0.34, 0.06, 0.09, 0.02, 0.03, 0.01, 0.38, 0.07]
9857
+ }
9858
+ }
9859
+ },
9407
9860
  {
9408
9861
  columnName: "insurance_provider",
9409
9862
  strategy: {
@@ -9416,7 +9869,7 @@ var healthcareTemplate = {
9416
9869
  },
9417
9870
  {
9418
9871
  columnName: "mrn",
9419
- strategy: { kind: "text", options: { mode: "short" } }
9872
+ strategy: { kind: "custom", options: { name: "sequential", prefix: "MRN-", padLength: 6 } }
9420
9873
  },
9421
9874
  {
9422
9875
  columnName: "date_of_birth",
@@ -9431,6 +9884,7 @@ var healthcareTemplate = {
9431
9884
  ["providers", {
9432
9885
  tableName: "providers",
9433
9886
  matchPattern: ["providers", "doctors", "physicians", "*provider*"],
9887
+ rowCountMultiplier: 0.2,
9434
9888
  columnOverrides: [
9435
9889
  {
9436
9890
  columnName: "first_name",
@@ -9466,7 +9920,7 @@ var healthcareTemplate = {
9466
9920
  },
9467
9921
  {
9468
9922
  columnName: "npi",
9469
- strategy: { kind: "text", options: { mode: "short" } }
9923
+ strategy: { kind: "custom", options: { name: "sequential", prefix: "NPI-", padLength: 6 } }
9470
9924
  },
9471
9925
  {
9472
9926
  columnName: "active",
@@ -9477,6 +9931,7 @@ var healthcareTemplate = {
9477
9931
  ["encounters", {
9478
9932
  tableName: "encounters",
9479
9933
  matchPattern: ["encounters", "visits", "appointments", "*encounter*", "*visit*"],
9934
+ rowCountMultiplier: 2,
9480
9935
  columnOverrides: [
9481
9936
  {
9482
9937
  columnName: "encounter_type",
@@ -9508,15 +9963,30 @@ var healthcareTemplate = {
9508
9963
  }
9509
9964
  }
9510
9965
  },
9966
+ {
9967
+ columnName: "notes",
9968
+ strategy: { kind: "text", options: { mode: "medium" } }
9969
+ },
9511
9970
  {
9512
9971
  columnName: "scheduled_at",
9513
9972
  strategy: { kind: "timestamp", options: { mode: "past" } }
9973
+ },
9974
+ {
9975
+ columnName: "checked_in_at",
9976
+ strategy: { kind: "timestamp", options: { mode: "past" } },
9977
+ description: "Nullable \u2014 null for scheduled/canceled encounters"
9978
+ },
9979
+ {
9980
+ columnName: "discharged_at",
9981
+ strategy: { kind: "timestamp", options: { mode: "past" } },
9982
+ description: "Nullable \u2014 null for non-completed encounters"
9514
9983
  }
9515
9984
  ]
9516
9985
  }],
9517
9986
  ["diagnoses", {
9518
9987
  tableName: "diagnoses",
9519
9988
  matchPattern: ["diagnoses", "*diagnosis*", "*diagnos*"],
9989
+ rowCountMultiplier: 2.5,
9520
9990
  columnOverrides: [
9521
9991
  {
9522
9992
  columnName: "icd_code",
@@ -9556,7 +10026,8 @@ var healthcareTemplate = {
9556
10026
  }],
9557
10027
  ["billing", {
9558
10028
  tableName: "billing",
9559
- matchPattern: ["billing", "claims", "charges", "*bill*", "*claim*"],
10029
+ matchPattern: ["billing", "claims", "*claim*"],
10030
+ rowCountMultiplier: 2,
9560
10031
  columnOverrides: [
9561
10032
  {
9562
10033
  columnName: "cpt_code",
@@ -9603,6 +10074,111 @@ var healthcareTemplate = {
9603
10074
  {
9604
10075
  columnName: "billed_at",
9605
10076
  strategy: { kind: "timestamp", options: { mode: "past" } }
10077
+ },
10078
+ {
10079
+ columnName: "paid_at",
10080
+ strategy: { kind: "timestamp", options: { mode: "past" } },
10081
+ description: "Nullable \u2014 null for unpaid bills"
10082
+ }
10083
+ ]
10084
+ }],
10085
+ ["medications", {
10086
+ tableName: "medications",
10087
+ matchPattern: ["medications", "*medic*", "*prescription*", "*rx*"],
10088
+ rowCountMultiplier: 2.5,
10089
+ columnOverrides: [
10090
+ {
10091
+ columnName: "medication_name",
10092
+ strategy: {
10093
+ kind: "enum",
10094
+ options: {
10095
+ values: ["Lisinopril", "Metformin", "Amlodipine", "Omeprazole", "Atorvastatin", "Levothyroxine", "Metoprolol", "Albuterol", "Gabapentin", "Sertraline", "Amoxicillin", "Ibuprofen"],
10096
+ weights: [0.1, 0.1, 0.09, 0.09, 0.1, 0.08, 0.08, 0.08, 0.07, 0.07, 0.07, 0.07]
10097
+ }
10098
+ }
10099
+ },
10100
+ {
10101
+ columnName: "dosage",
10102
+ strategy: {
10103
+ kind: "enum",
10104
+ options: {
10105
+ values: ["5mg", "10mg", "20mg", "25mg", "40mg", "50mg", "100mg", "250mg", "500mg"]
10106
+ }
10107
+ }
10108
+ },
10109
+ {
10110
+ columnName: "frequency",
10111
+ strategy: {
10112
+ kind: "enum",
10113
+ options: {
10114
+ values: ["once daily", "twice daily", "three times daily", "as needed", "every 6 hours", "at bedtime"],
10115
+ weights: [0.35, 0.25, 0.1, 0.15, 0.05, 0.1]
10116
+ }
10117
+ }
10118
+ },
10119
+ {
10120
+ columnName: "route",
10121
+ strategy: {
10122
+ kind: "enum",
10123
+ options: {
10124
+ values: ["oral", "topical", "injection", "inhaled", "sublingual"],
10125
+ weights: [0.75, 0.08, 0.07, 0.06, 0.04]
10126
+ }
10127
+ }
10128
+ },
10129
+ {
10130
+ columnName: "prescribed_at",
10131
+ strategy: { kind: "timestamp", options: { mode: "past" } }
10132
+ },
10133
+ {
10134
+ columnName: "end_date",
10135
+ strategy: { kind: "timestamp", options: { mode: "past" } },
10136
+ description: "Nullable \u2014 null for ongoing medications"
10137
+ },
10138
+ {
10139
+ columnName: "status",
10140
+ strategy: {
10141
+ kind: "enum",
10142
+ options: {
10143
+ values: ["active", "discontinued", "completed"],
10144
+ weights: [0.65, 0.2, 0.15]
10145
+ }
10146
+ }
10147
+ }
10148
+ ]
10149
+ }],
10150
+ ["vitals", {
10151
+ tableName: "vitals",
10152
+ matchPattern: ["vitals", "*vital*", "*measurement*"],
10153
+ rowCountMultiplier: 3,
10154
+ columnOverrides: [
10155
+ {
10156
+ columnName: "systolic_bp",
10157
+ strategy: { kind: "integer", options: { min: 90, max: 180 } }
10158
+ },
10159
+ {
10160
+ columnName: "diastolic_bp",
10161
+ strategy: { kind: "integer", options: { min: 55, max: 110 } }
10162
+ },
10163
+ {
10164
+ columnName: "heart_rate",
10165
+ strategy: { kind: "integer", options: { min: 50, max: 120 } }
10166
+ },
10167
+ {
10168
+ columnName: "temperature_f",
10169
+ strategy: { kind: "float", options: { min: 96, max: 103 } }
10170
+ },
10171
+ {
10172
+ columnName: "weight_lbs",
10173
+ strategy: { kind: "float", options: { min: 100, max: 350 } }
10174
+ },
10175
+ {
10176
+ columnName: "height_inches",
10177
+ strategy: { kind: "integer", options: { min: 55, max: 78 } }
10178
+ },
10179
+ {
10180
+ columnName: "recorded_at",
10181
+ strategy: { kind: "timestamp", options: { mode: "past" } }
9606
10182
  }
9607
10183
  ]
9608
10184
  }]
@@ -10292,7 +10868,8 @@ function buildGenerationPlan(schema, config, timelineConfig) {
10292
10868
  required: !column.isNullable && !column.hasDefault,
10293
10869
  strategy,
10294
10870
  defaultValueMode: "generated",
10295
- maxLength: column.maxLength
10871
+ maxLength: column.maxLength,
10872
+ isUnique: column.isUnique
10296
10873
  };
10297
10874
  const fk = fkBySource.get(`${table.name}.${column.name}`);
10298
10875
  if (fk) {
@@ -10605,6 +11182,12 @@ function normalizeSchema(raw) {
10605
11182
  for (const pk of raw.primaryKeys) {
10606
11183
  primaryKeyMap.set(pk.table_name, pk);
10607
11184
  }
11185
+ const uniqueColumns = /* @__PURE__ */ new Set();
11186
+ if (raw.uniqueConstraints) {
11187
+ for (const uc of raw.uniqueConstraints) {
11188
+ uniqueColumns.add(`${uc.table_name}.${uc.column_name}`);
11189
+ }
11190
+ }
10608
11191
  const columnsByTable = /* @__PURE__ */ new Map();
10609
11192
  for (const col of raw.columns) {
10610
11193
  const existing = columnsByTable.get(col.table_name) ?? [];
@@ -10636,7 +11219,7 @@ function normalizeSchema(raw) {
10636
11219
  defaultValue: col.column_default,
10637
11220
  maxLength: col.character_maximum_length,
10638
11221
  isPrimaryKey: pk !== null && pk.column_name === col.column_name,
10639
- isUnique: false,
11222
+ isUnique: pk !== null && pk.column_name === col.column_name || uniqueColumns.has(`${rawTable.table_name}.${col.column_name}`),
10640
11223
  ordinalPosition: col.ordinal_position
10641
11224
  }));
10642
11225
  tables.push({
@@ -10772,15 +11355,32 @@ async function getPrimaryKeys(pool, schemaName = "public") {
10772
11355
  return result.rows;
10773
11356
  }
10774
11357
 
11358
+ // ../../packages/schema/dist/introspection/getUniqueConstraints.js
11359
+ async function getUniqueConstraints(pool, schemaName = "public") {
11360
+ const result = await pool.query(`SELECT
11361
+ tc.constraint_name,
11362
+ kcu.table_name,
11363
+ kcu.column_name
11364
+ FROM information_schema.table_constraints tc
11365
+ JOIN information_schema.key_column_usage kcu
11366
+ ON tc.constraint_name = kcu.constraint_name
11367
+ AND tc.constraint_schema = kcu.constraint_schema
11368
+ WHERE tc.constraint_type = 'UNIQUE'
11369
+ AND tc.constraint_schema = $1
11370
+ ORDER BY kcu.table_name, kcu.ordinal_position`, [schemaName]);
11371
+ return result.rows;
11372
+ }
11373
+
10775
11374
  // ../../packages/schema/dist/introspectDatabase.js
10776
11375
  async function introspectDatabase(pool, schemaName = "public", options) {
10777
- const [tables, columns, foreignKeys, primaryKeys] = await Promise.all([
11376
+ const [tables, columns, foreignKeys, primaryKeys, uniqueConstraints] = await Promise.all([
10778
11377
  getTables(pool, schemaName),
10779
11378
  getColumns(pool, schemaName),
10780
11379
  getForeignKeys(pool, schemaName),
10781
- getPrimaryKeys(pool, schemaName)
11380
+ getPrimaryKeys(pool, schemaName),
11381
+ getUniqueConstraints(pool, schemaName)
10782
11382
  ]);
10783
- const schema = normalizeSchema({ tables, columns, foreignKeys, primaryKeys });
11383
+ const schema = normalizeSchema({ tables, columns, foreignKeys, primaryKeys, uniqueConstraints });
10784
11384
  const validation = validateSchema(schema);
10785
11385
  for (const warning of validation.warnings) {
10786
11386
  console.warn(`[databox] Schema warning: ${warning}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "realitydb",
3
- "version": "1.3.1",
3
+ "version": "1.4.2",
4
4
  "description": "Developer Reality Platform - realistic database environments from your schema",
5
5
  "license": "MIT",
6
6
  "keywords": [