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.
- package/README.md +368 -364
- package/dist/app.js +25 -16
- package/dist/auth/config.d.ts +1 -1
- package/dist/auth/config.js +18 -30
- package/dist/auth/crypto.js +11 -21
- package/dist/auth/middleware.js +9 -16
- package/dist/auth/routes.js +9 -15
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.js +20 -29
- package/dist/cli/config.d.ts +1 -1
- package/dist/cli/config.js +15 -18
- package/dist/cli/runner.js +13 -13
- package/dist/data/chain.d.ts +1 -1
- package/dist/data/chain.js +40 -617
- package/dist/data/datasets.d.ts +1 -1
- package/dist/data/datasets.js +43 -1
- package/dist/data/detector.js +45 -21
- package/dist/data/engine.d.ts +1 -1
- package/dist/data/engine.js +483 -142
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +8 -0
- package/dist/data/prng.d.ts +1 -0
- package/dist/data/prng.js +73 -0
- package/dist/data/registry.d.ts +1 -0
- package/dist/data/registry.js +805 -0
- package/dist/data/schema-graph.d.ts +1 -0
- package/dist/data/schema-graph.js +210 -0
- package/dist/data/strategies.d.ts +1 -1
- package/dist/data/strategies.js +44 -283
- package/dist/data/templates.d.ts +1 -0
- package/dist/data/templates.js +134 -0
- package/dist/data/types.d.ts +1 -1
- package/dist/data/validator.d.ts +1 -0
- package/dist/data/validator.js +160 -0
- package/dist/db/database.js +9 -14
- package/dist/db/export.js +32 -55
- package/dist/db/filters.d.ts +1 -1
- package/dist/db/filters.js +15 -38
- package/dist/db/introspection.js +4 -7
- package/dist/db/manager.d.ts +1 -1
- package/dist/db/manager.js +48 -53
- package/dist/db/migrations.js +7 -14
- package/dist/db/postgres.js +30 -78
- package/dist/index.d.ts +1 -1
- package/dist/public/css/app.css +1 -1
- package/dist/public/js/browse.js +1 -1
- package/dist/public/js/inspector.js +1 -1
- package/dist/public/js/query.js +1 -1
- package/dist/public/js/seed.js +1 -1
- package/dist/routes/api/erd.js +3 -8
- package/dist/routes/api/helpers.d.ts +1 -1
- package/dist/routes/api/helpers.js +75 -25
- package/dist/routes/api/import-export.js +1 -2
- package/dist/routes/api/query.js +2 -6
- package/dist/routes/api/rows.js +4 -8
- package/dist/routes/api/seed.js +35 -21
- package/dist/routes/api/tables.js +15 -30
- package/dist/routes/databases.js +8 -26
- package/dist/routes/pages.js +67 -18
- package/dist/serverless.js +31 -44
- package/dist/sql/generator.d.ts +1 -1
- package/dist/sql/generator.js +35 -109
- package/dist/types/api.d.ts +1 -1
- package/dist/utils/common.d.ts +1 -1
- package/dist/utils/common.js +45 -85
- package/dist/utils/csv.d.ts +1 -1
- package/dist/utils/csv.js +11 -17
- package/dist/utils/datatype.js +46 -60
- package/dist/utils/icons.js +8 -8
- package/dist/views/layouts/main.hbs +1 -87
- package/dist/views/pages/databases.hbs +1 -233
- package/dist/views/pages/designer.hbs +1 -89
- package/dist/views/pages/erd.hbs +1 -1241
- package/dist/views/pages/error.hbs +1 -10
- package/dist/views/pages/form.hbs +1 -59
- package/dist/views/pages/home.hbs +1 -220
- package/dist/views/pages/info.hbs +1 -107
- package/dist/views/pages/login.hbs +1 -98
- package/dist/views/pages/query.hbs +1 -129
- package/dist/views/pages/schema.hbs +1 -298
- package/dist/views/pages/seed-select.hbs +251 -0
- package/dist/views/pages/seed.hbs +256 -414
- package/dist/views/pages/table.hbs +1 -327
- package/dist/views/partials/navbar.hbs +1 -83
- package/dist/views/partials/sidebar.hbs +1 -129
- package/docs/API.md +149 -149
- package/docs/EXAMPLES.md +579 -579
- package/docs/SECURITY.md +265 -265
- package/package.json +80 -79
package/dist/data/datasets.d.ts
CHANGED
|
@@ -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[];
|
package/dist/data/datasets.js
CHANGED
|
@@ -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
|
+
];
|
package/dist/data/detector.js
CHANGED
|
@@ -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
|
|
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
|
|
45
|
+
i++;
|
|
46
46
|
break;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
else
|
|
50
|
-
i
|
|
50
|
+
i++;
|
|
51
51
|
}
|
|
52
52
|
continue;
|
|
53
53
|
}
|
|
54
54
|
if (ch === '"' || ch === '`' || ch === '[') {
|
|
55
55
|
const close = ch === '[' ? ']' : ch;
|
|
56
|
-
i
|
|
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
|
|
61
|
+
i++;
|
|
62
62
|
}
|
|
63
|
-
i
|
|
63
|
+
i++;
|
|
64
64
|
continue;
|
|
65
65
|
}
|
|
66
66
|
if (ch === '(')
|
|
67
|
-
depth
|
|
67
|
+
depth++;
|
|
68
68
|
else if (ch === ')') {
|
|
69
|
-
depth
|
|
69
|
+
depth--;
|
|
70
70
|
if (depth === 0)
|
|
71
71
|
break;
|
|
72
72
|
}
|
|
73
|
-
i
|
|
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
|
-
|
|
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:
|
|
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 (
|
|
479
|
-
out.values = r.values.map(
|
|
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)) {
|
package/dist/data/engine.d.ts
CHANGED
|
@@ -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>;
|
|
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>;
|