admindb 2.2.1 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +368 -364
  2. package/dist/app.js +25 -16
  3. package/dist/auth/config.d.ts +1 -1
  4. package/dist/auth/config.js +18 -30
  5. package/dist/auth/crypto.js +11 -21
  6. package/dist/auth/middleware.js +9 -16
  7. package/dist/auth/routes.js +9 -15
  8. package/dist/cli/args.d.ts +1 -1
  9. package/dist/cli/args.js +20 -29
  10. package/dist/cli/config.d.ts +1 -1
  11. package/dist/cli/config.js +15 -18
  12. package/dist/cli/runner.js +13 -13
  13. package/dist/data/chain.d.ts +1 -1
  14. package/dist/data/chain.js +40 -617
  15. package/dist/data/datasets.d.ts +1 -1
  16. package/dist/data/datasets.js +43 -1
  17. package/dist/data/detector.js +45 -21
  18. package/dist/data/engine.d.ts +1 -1
  19. package/dist/data/engine.js +483 -142
  20. package/dist/data/index.d.ts +1 -1
  21. package/dist/data/index.js +8 -0
  22. package/dist/data/prng.d.ts +1 -0
  23. package/dist/data/prng.js +73 -0
  24. package/dist/data/registry.d.ts +1 -0
  25. package/dist/data/registry.js +805 -0
  26. package/dist/data/schema-graph.d.ts +1 -0
  27. package/dist/data/schema-graph.js +210 -0
  28. package/dist/data/strategies.d.ts +1 -1
  29. package/dist/data/strategies.js +44 -283
  30. package/dist/data/templates.d.ts +1 -0
  31. package/dist/data/templates.js +134 -0
  32. package/dist/data/types.d.ts +1 -1
  33. package/dist/data/validator.d.ts +1 -0
  34. package/dist/data/validator.js +160 -0
  35. package/dist/db/database.js +9 -14
  36. package/dist/db/export.js +32 -55
  37. package/dist/db/filters.d.ts +1 -1
  38. package/dist/db/filters.js +15 -38
  39. package/dist/db/introspection.js +4 -7
  40. package/dist/db/manager.d.ts +1 -1
  41. package/dist/db/manager.js +48 -53
  42. package/dist/db/migrations.js +7 -14
  43. package/dist/db/postgres.js +30 -78
  44. package/dist/index.d.ts +1 -1
  45. package/dist/public/css/app.css +1 -1
  46. package/dist/public/js/browse.js +1 -1
  47. package/dist/public/js/inspector.js +1 -1
  48. package/dist/public/js/query.js +1 -1
  49. package/dist/public/js/seed.js +1 -1
  50. package/dist/routes/api/erd.js +3 -8
  51. package/dist/routes/api/helpers.d.ts +1 -1
  52. package/dist/routes/api/helpers.js +75 -25
  53. package/dist/routes/api/import-export.js +1 -2
  54. package/dist/routes/api/query.js +2 -6
  55. package/dist/routes/api/rows.js +4 -8
  56. package/dist/routes/api/seed.js +35 -21
  57. package/dist/routes/api/tables.js +15 -30
  58. package/dist/routes/databases.js +8 -26
  59. package/dist/routes/pages.js +67 -18
  60. package/dist/serverless.js +31 -44
  61. package/dist/sql/generator.d.ts +1 -1
  62. package/dist/sql/generator.js +35 -109
  63. package/dist/types/api.d.ts +1 -1
  64. package/dist/utils/common.d.ts +1 -1
  65. package/dist/utils/common.js +45 -85
  66. package/dist/utils/csv.d.ts +1 -1
  67. package/dist/utils/csv.js +11 -17
  68. package/dist/utils/datatype.js +46 -60
  69. package/dist/utils/icons.js +8 -8
  70. package/dist/views/layouts/main.hbs +1 -87
  71. package/dist/views/pages/databases.hbs +1 -233
  72. package/dist/views/pages/designer.hbs +1 -89
  73. package/dist/views/pages/erd.hbs +1 -1241
  74. package/dist/views/pages/error.hbs +1 -10
  75. package/dist/views/pages/form.hbs +1 -59
  76. package/dist/views/pages/home.hbs +1 -220
  77. package/dist/views/pages/info.hbs +1 -107
  78. package/dist/views/pages/login.hbs +1 -98
  79. package/dist/views/pages/query.hbs +1 -129
  80. package/dist/views/pages/schema.hbs +1 -298
  81. package/dist/views/pages/seed-select.hbs +251 -0
  82. package/dist/views/pages/seed.hbs +256 -414
  83. package/dist/views/pages/table.hbs +1 -327
  84. package/dist/views/partials/navbar.hbs +1 -83
  85. package/dist/views/partials/sidebar.hbs +1 -129
  86. package/docs/API.md +149 -149
  87. package/docs/EXAMPLES.md +579 -579
  88. package/docs/SECURITY.md +265 -265
  89. package/package.json +80 -79
@@ -1 +1 @@
1
- export declare const FIRST_NAMES:string[];export declare const LAST_NAMES:string[];export declare const CITIES:string[];export declare const COUNTRIES:string[];export declare const DOMAINS:string[];export declare const LOREM_WORDS:string[];export declare const COMPANIES:string[];export declare const JOB_TITLES:string[];export declare const US_STATES:string[];export declare const CURRENCIES:string[];export declare const COUNTRY_CODES:string[];export declare const STATUSES:string[];export declare const HEX_COLORS:string[];export declare const NAMED_COLORS:string[];
1
+ export declare const FIRST_NAMES:string[];export declare const LAST_NAMES:string[];export declare const CITIES:string[];export declare const COUNTRIES:string[];export declare const DOMAINS:string[];export declare const LOREM_WORDS:string[];export declare const COMPANIES:string[];export declare const JOB_TITLES:string[];export declare const US_STATES:string[];export declare const CURRENCIES:string[];export declare const COUNTRY_CODES:string[];export declare const STATUSES:string[];export declare const HEX_COLORS:string[];export declare const NAMED_COLORS:string[];export declare const PRODUCT_CATEGORIES:string[];export declare const PRODUCT_NAMES:string[];export declare const DEPARTMENTS:string[];export declare const PAYMENT_METHODS:string[];export declare const TRANSACTION_TYPES:string[];export declare const TECH_SKILLS:string[];export declare const ORDER_STATUSES:string[];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NAMED_COLORS = exports.HEX_COLORS = exports.STATUSES = exports.COUNTRY_CODES = exports.CURRENCIES = exports.US_STATES = exports.JOB_TITLES = exports.COMPANIES = exports.LOREM_WORDS = exports.DOMAINS = exports.COUNTRIES = exports.CITIES = exports.LAST_NAMES = exports.FIRST_NAMES = void 0;
3
+ exports.ORDER_STATUSES = exports.TECH_SKILLS = exports.TRANSACTION_TYPES = exports.PAYMENT_METHODS = exports.DEPARTMENTS = exports.PRODUCT_NAMES = exports.PRODUCT_CATEGORIES = exports.NAMED_COLORS = exports.HEX_COLORS = exports.STATUSES = exports.COUNTRY_CODES = exports.CURRENCIES = exports.US_STATES = exports.JOB_TITLES = exports.COMPANIES = exports.LOREM_WORDS = exports.DOMAINS = exports.COUNTRIES = exports.CITIES = exports.LAST_NAMES = exports.FIRST_NAMES = void 0;
4
4
  exports.FIRST_NAMES = [
5
5
  "Sombat", "Ting", "Rajan", "Minh", "Hiroshi", "William", "Made", "Ravi", "John", "Kiran",
6
6
  "Raj", "Wayan", "Chaiwat", "Aarav", "Sita", "Zara", "Ratna", "Ananya", "Ha-eun", "Siti",
@@ -127,3 +127,45 @@ exports.NAMED_COLORS = [
127
127
  "Sky", "Slate", "Teal", "Fuchsia", "Crimson", "Navy",
128
128
  "Coral", "Bronze", "Charcoal", "Mint", "Lavender", "Ruby", "Cobalt"
129
129
  ];
130
+ exports.PRODUCT_CATEGORIES = [
131
+ "Electronics", "Computers & Accessories", "Apparel & Footwear", "Home & Kitchen",
132
+ "Health & Wellness", "Books & Media", "Sports & Outdoors", "Beauty & Personal Care",
133
+ "Toys & Games", "Automotive & Industrial", "Groceries & Gourmet", "Office Products"
134
+ ];
135
+ exports.PRODUCT_NAMES = [
136
+ "Wireless Noise-Canceling Earbuds", "Ergonomic Mechanical Keyboard", "Ultra HD 4K IPS Monitor",
137
+ "Organic Fair-Trade Coffee Beans", "Stainless Steel Thermal Tumbler", "Merino Wool Athletic Socks",
138
+ "Waterproof Smart Fitness Watch", "Non-Stick Ceramic Frying Pan", "Hydrating Hyaluronic Facial Serum",
139
+ "Portable Bluetooth Outdoor Speaker", "Compact Cordless Handheld Vacuum", "Memory Foam Contoured Pillow",
140
+ "Natural Soy Aromatherapy Candle", "Adjustable Standing Desk Converter", "High-Speed 65W GaN Fast Charger",
141
+ "Full-Grain Leather Bi-Fold Wallet", "Polarized Lightweight Sunglasses", "Recycled Aluminum Laptop Stand",
142
+ "Organic Green Matcha Tea Powder", "Precision Kitchen Digital Scale", "Active Noise Canceling Headphones",
143
+ "Tempered Glass Screen Protector", "Braided Nylon Heavy-Duty Cable", "Plant-Based Protein Powder",
144
+ "Ceramic Essential Oil Diffuser", "Stainless Steel Chef Knife 8-Inch", "Resistance Band Exercise Set",
145
+ "Double-Wall Insulated Mug", "Minimalist Water-Resistant Backpack", "Rechargeable LED Desk Lamp"
146
+ ];
147
+ exports.DEPARTMENTS = [
148
+ "Engineering", "Product Management", "Design & UX", "Marketing & Growth",
149
+ "Sales & Business Development", "Customer Support", "Human Resources",
150
+ "Finance & Accounting", "Legal & Compliance", "Operations & Logistics",
151
+ "Data & Analytics", "Quality Assurance", "Information Security", "Corporate Strategy"
152
+ ];
153
+ exports.PAYMENT_METHODS = [
154
+ "Credit Card", "Debit Card", "PayPal", "Apple Pay", "Google Pay",
155
+ "Bank Transfer", "Stripe Checkout", "Klarna Pay in 4", "Cash on Delivery",
156
+ "Affirm", "Afterpay", "Wire Transfer", "Venmo"
157
+ ];
158
+ exports.TRANSACTION_TYPES = [
159
+ "purchase", "refund", "subscription", "authorization", "capture",
160
+ "chargeback", "payout", "transfer", "adjustment", "deposit", "withdrawal"
161
+ ];
162
+ exports.TECH_SKILLS = [
163
+ "TypeScript", "JavaScript", "Python", "Rust", "Go", "SQL", "PostgreSQL",
164
+ "SQLite", "MySQL", "React", "Vue", "Next.js", "Node.js", "GraphQL",
165
+ "Redis", "Docker", "Kubernetes", "AWS", "Cloudflare", "Linux", "Git",
166
+ "TailwindCSS", "Terraform", "Kafka", "Elasticsearch", "Prometheus"
167
+ ];
168
+ exports.ORDER_STATUSES = [
169
+ "pending", "confirmed", "processing", "shipped", "out_for_delivery",
170
+ "delivered", "cancelled", "refunded", "on_hold", "failed"
171
+ ];
@@ -36,41 +36,41 @@ function extractCheckExprs(sql) {
36
36
  while (i < sql.length && depth > 0) {
37
37
  const ch = sql[i];
38
38
  if (ch === "'") {
39
- i += 1;
39
+ i++;
40
40
  while (i < sql.length) {
41
41
  if (sql[i] === "'") {
42
42
  if (sql[i + 1] === "'")
43
43
  i += 2;
44
44
  else {
45
- i += 1;
45
+ i++;
46
46
  break;
47
47
  }
48
48
  }
49
49
  else
50
- i += 1;
50
+ i++;
51
51
  }
52
52
  continue;
53
53
  }
54
54
  if (ch === '"' || ch === '`' || ch === '[') {
55
55
  const close = ch === '[' ? ']' : ch;
56
- i += 1;
56
+ i++;
57
57
  while (i < sql.length && sql[i] !== close) {
58
58
  if (sql[i] === close && sql[i + 1] === close)
59
59
  i += 2;
60
60
  else
61
- i += 1;
61
+ i++;
62
62
  }
63
- i += 1;
63
+ i++;
64
64
  continue;
65
65
  }
66
66
  if (ch === '(')
67
- depth += 1;
67
+ depth++;
68
68
  else if (ch === ')') {
69
- depth -= 1;
69
+ depth--;
70
70
  if (depth === 0)
71
71
  break;
72
72
  }
73
- i += 1;
73
+ i++;
74
74
  }
75
75
  out.push(sql.slice(start, i));
76
76
  }
@@ -128,8 +128,7 @@ function parseChecks(sql) {
128
128
  const col = mColIn[1] || mColIn[2] || mColIn[3] || mColIn[4];
129
129
  if (!col || ['json_extract', 'strftime', 'datetime', 'date', 'length', 'typeof'].includes(col.toLowerCase()))
130
130
  continue;
131
- const matchPos = mColIn.index;
132
- if (expr.slice(Math.max(0, matchPos - 5), matchPos).includes('->'))
131
+ if (expr.slice(Math.max(0, mColIn.index - 5), mColIn.index).includes('->'))
133
132
  continue;
134
133
  const inContent = mColIn[5];
135
134
  const strValues = (inContent.match(/'(?:[^']|'')*'/g) ?? []).map((s) => s.slice(1, -1).replace(/''/g, "'"));
@@ -253,6 +252,13 @@ function extractJsonColumns(sql) {
253
252
  const TEXT_PATTERNS = [
254
253
  [/avatar|picture|photo|image|img|thumbnail|icon|logo/, () => ({ strategy: 'avatar' })],
255
254
  [/company|organization|org|firm|corp|employer|agency/, () => ({ strategy: 'company' })],
255
+ [/department|division|dept/, () => ({ strategy: 'department' })],
256
+ [/productcategory|categoryname|^category$/, () => ({ strategy: 'productCategory' })],
257
+ [/productname|producttitle|^product$|^item$|itemname/, () => ({ strategy: 'product' })],
258
+ [/paymentmethod|paymenttype|paymentmode|paymentprovider/, () => ({ strategy: 'paymentMethod' })],
259
+ [/transactiontype|txntype|txtype/, () => ({ strategy: 'transactionType' })],
260
+ [/techskill|skill|skills|techstack|technology/, () => ({ strategy: 'techSkill' })],
261
+ [/orderstatus|shipmentstatus|deliverystatus/, () => ({ strategy: 'orderStatus' })],
256
262
  [/job|title|role|position|occupation|profession/, () => ({ strategy: 'job' })],
257
263
  [/currency|curr|currencycode/, () => ({ strategy: 'currency' })],
258
264
  [/countrycode|countryiso|isocountry|cca2/, () => ({ strategy: 'countryCode' })],
@@ -398,12 +404,18 @@ function buildColumnConfigs(info) {
398
404
  let uqM;
399
405
  while ((uqM = uqRe.exec(info.sql))) {
400
406
  const rawCols = uqM[1].split(',').map((s) => s.trim().replace(/[`"\[\]]/g, ''));
401
- if (rawCols.length === 1 && rawCols[0]) {
407
+ if (rawCols.length === 1 && rawCols[0])
402
408
  uniqueCols.add(rawCols[0]);
403
- }
404
409
  }
405
410
  }
406
411
  const checkInfo = parseChecks(info.sql ?? null);
412
+ const colNames = info.columns.map((c) => c.name.toLowerCase());
413
+ const hasFirstName = colNames.includes('first_name') || colNames.includes('firstname');
414
+ const hasLastName = colNames.includes('last_name') || colNames.includes('lastname');
415
+ const fullNameCol = info.columns.find((c) => {
416
+ const lc = c.name.toLowerCase();
417
+ return lc === 'full_name' || lc === 'fullname' || lc === 'name' || lc === 'customer_name';
418
+ });
407
419
  return info.columns.map((col) => {
408
420
  const fk = fkByColumn.get(col.name) ?? null;
409
421
  const strategies = (0, strategies_1.strategiesFor)(col, fk);
@@ -450,6 +462,17 @@ function buildColumnConfigs(info) {
450
462
  defaultPlan.maxLen = colLen.max;
451
463
  }
452
464
  }
465
+ if (defaultPlan.strategy === 'email' && !col.pk) {
466
+ if (hasFirstName && hasLastName) {
467
+ defaultPlan = { strategy: 'template', template: '{{first_name}}.{{last_name}}@example.com' };
468
+ }
469
+ else if (fullNameCol && fullNameCol.name !== col.name) {
470
+ defaultPlan = { strategy: 'template', template: `{{${fullNameCol.name}}}@example.com` };
471
+ }
472
+ }
473
+ if ((col.name.toLowerCase() === 'full_name' || col.name.toLowerCase() === 'fullname') && hasFirstName && hasLastName && !col.pk) {
474
+ defaultPlan = { strategy: 'template', template: '{{first_name}} {{last_name}}' };
475
+ }
453
476
  if (!strategies.some((s) => s.id === defaultPlan.strategy) || (!col.pk && col.notnull && col.dflt_value == null && (defaultPlan.strategy === 'skip' || defaultPlan.strategy === 'null'))) {
454
477
  defaultPlan = (0, strategies_1.fallbackPlanFor)(col);
455
478
  }
@@ -457,7 +480,7 @@ function buildColumnConfigs(info) {
457
480
  name: col.name,
458
481
  type: col.type,
459
482
  pk: col.pk > 0,
460
- notnull: !!col.notnull,
483
+ notnull: Boolean(col.notnull),
461
484
  hasDefault: col.dflt_value != null,
462
485
  unique,
463
486
  fk,
@@ -466,7 +489,7 @@ function buildColumnConfigs(info) {
466
489
  };
467
490
  });
468
491
  }
469
- const STR_PLAN_KEYS = ['value', 'from', 'to', 'prefix', 'suffix', 'pattern', 'format'];
492
+ const STR_PLAN_KEYS = ['value', 'from', 'to', 'prefix', 'suffix', 'pattern', 'format', 'template', 'refTable', 'refColumn'];
470
493
  const NUM_PLAN_KEYS = ['min', 'max', 'precision', 'minLen', 'maxLen', 'nullPct', 'start', 'step'];
471
494
  function sanitizeColumnPlan(raw) {
472
495
  if (!raw || typeof raw !== 'object')
@@ -475,24 +498,25 @@ function sanitizeColumnPlan(raw) {
475
498
  if (typeof r.strategy !== 'string' || !r.strategy)
476
499
  return null;
477
500
  const out = { strategy: r.strategy };
478
- if (r.values !== undefined && r.values !== null && Array.isArray(r.values)) {
479
- out.values = r.values.map((x) => String(x));
501
+ if (Array.isArray(r.values)) {
502
+ out.values = r.values.map(String);
503
+ }
504
+ if (r.unique !== undefined && r.unique !== null) {
505
+ out.unique = Boolean(r.unique);
480
506
  }
481
507
  if (r.jsonKeys !== undefined && r.jsonKeys !== null) {
482
508
  const rawKeys = Array.isArray(r.jsonKeys) ? r.jsonKeys.map(String) : String(r.jsonKeys).split(/[,;]/);
483
509
  out.jsonKeys = rawKeys.map((s) => s.trim()).filter(Boolean);
484
510
  }
485
511
  for (const key of STR_PLAN_KEYS) {
486
- if (r[key] !== undefined && r[key] !== null) {
512
+ if (r[key] !== undefined && r[key] !== null)
487
513
  out[key] = String(r[key]);
488
- }
489
514
  }
490
515
  for (const key of NUM_PLAN_KEYS) {
491
516
  if (r[key] !== undefined && r[key] !== null) {
492
517
  const n = Number(r[key]);
493
- if (Number.isFinite(n)) {
518
+ if (Number.isFinite(n))
494
519
  out[key] = n;
495
- }
496
520
  }
497
521
  }
498
522
  if (r.jsonValues && typeof r.jsonValues === 'object' && !Array.isArray(r.jsonValues)) {
@@ -1 +1 @@
1
- import type {IDatabase,TableInfoData,WhereClause} from '../db/index';import{type ColumnGeneratorConfig,type ColumnPlan,type GenerateResult} from './types';export declare function generateRows(db:IDatabase,info:TableInfoData,configs:ColumnGeneratorConfig[],count:number,plan?:Record<string,ColumnPlan>,truncate?:boolean):Promise<GenerateResult>;export declare function buildSeedInsertSql(table:string,rows:WhereClause[][]):string;
1
+ import type {IDatabase,TableInfoData,WhereClause} from '../db/index';import{type ColumnGeneratorConfig,type ColumnPlan,type ErChainResult,type GenerateResult,type GenerationOptions,type GenerationPlan} from './types';export declare class SeedEngine{static executePlan(db:IDatabase,plan:GenerationPlan,optionsOverride?:Partial<GenerationOptions>):Promise<ErChainResult>;}export declare function buildSeedInsertSql(table:string,rows:WhereClause[][]):string;export declare function buildChainInsertSql(executionOrder:string[],tableResults:ErChainResult['tableResults']):string;export declare function generateRows(db:IDatabase,info:TableInfoData,configs:ColumnGeneratorConfig[],count:number,plan?:Record<string,ColumnPlan>,truncate?:boolean):Promise<GenerateResult>;