@h3ravel/arquebus 0.3.6 → 0.4.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/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import Knex$1 from "knex";
7
7
  import path from "path";
8
8
  import { existsSync } from "fs";
9
9
  import pluralize from "pluralize";
10
- import { Logger } from "@h3ravel/shared";
10
+ import { Logger, TaskManager } from "@h3ravel/shared";
11
11
  import fs from "node:fs/promises";
12
12
  import { access } from "fs/promises";
13
13
  import escalade from "escalade/sync";
@@ -208,6 +208,7 @@ const tap = (instance, callback) => {
208
208
  return result instanceof Promise ? result.then(() => instance) : instance;
209
209
  };
210
210
  const { compose } = mixin_exports;
211
+ const flatten = (arr) => arr.flat();
211
212
  const flattenDeep = (arr) => Array.isArray(arr) ? arr.reduce((a, b) => a.concat(flattenDeep(b)), []) : [arr];
212
213
  const kebabCase = (str) => trim(dash(str.replace(/[^a-zA-Z0-9_-]/g, "-")), "_-");
213
214
  const snakeCase = (str) => trim(snake(str.replace(/[^a-zA-Z0-9_-]/g, "-")), "_-");
@@ -3526,13 +3527,1430 @@ var MigrationRepository = class {
3526
3527
  return this.getConnection().table(this.table);
3527
3528
  }
3528
3529
  getConnection() {
3529
- return this.resolver.connection(this.connection);
3530
+ return this.resolver.fire(this.connection);
3530
3531
  }
3531
3532
  setSource(name) {
3532
3533
  this.connection = name;
3533
3534
  }
3534
3535
  };
3535
3536
 
3537
+ //#endregion
3538
+ //#region src/inspector/utils/strip-quotes.ts
3539
+ /**
3540
+ * Strip leading/trailing quotes from a string and handle null values.
3541
+ */
3542
+ function stripQuotes(value) {
3543
+ if (value === null || value === void 0) return null;
3544
+ const trimmed = value.trim();
3545
+ if (trimmed.startsWith("'") && trimmed.endsWith("'") || trimmed.startsWith("\"") && trimmed.endsWith("\"")) return trimmed.slice(1, -1);
3546
+ return value;
3547
+ }
3548
+
3549
+ //#endregion
3550
+ //#region src/inspector/dialects/cockroachdb.ts
3551
+ /**
3552
+ * Converts CockroachDB default value to JS
3553
+ * Eg `'example'::character varying` => `example`
3554
+ */
3555
+ function parseDefaultValue$5(value) {
3556
+ if (value === null) return null;
3557
+ if (value.startsWith("nextval(")) return value;
3558
+ value = value.split("::")[0];
3559
+ return stripQuotes(value);
3560
+ }
3561
+ var CockroachDB = class {
3562
+ knex;
3563
+ schema;
3564
+ explodedSchema;
3565
+ constructor(knex) {
3566
+ this.knex = knex;
3567
+ const config = knex.client.config;
3568
+ if (!config.searchPath) {
3569
+ this.schema = "public";
3570
+ this.explodedSchema = [this.schema];
3571
+ } else if (typeof config.searchPath === "string") {
3572
+ this.schema = config.searchPath;
3573
+ this.explodedSchema = [config.searchPath];
3574
+ } else {
3575
+ this.schema = config.searchPath[0];
3576
+ this.explodedSchema = config.searchPath;
3577
+ }
3578
+ }
3579
+ /**
3580
+ * Set the schema to be used in other methods
3581
+ */
3582
+ withSchema(schema) {
3583
+ this.schema = schema;
3584
+ this.explodedSchema = [this.schema];
3585
+ return this;
3586
+ }
3587
+ /**
3588
+ * List all existing tables in the current schema/database
3589
+ */
3590
+ async tables() {
3591
+ return (await this.knex.select("tablename").from("pg_catalog.pg_tables").whereIn("schemaname", this.explodedSchema)).map(({ tablename }) => tablename);
3592
+ }
3593
+ async tableInfo(table) {
3594
+ const query = this.knex.select("table_name", "table_schema", this.knex.select(this.knex.raw("obj_description(oid)")).from("pg_class").where({ relkind: "r" }).andWhere({ relname: "table_name" }).as("table_comment")).from("information_schema.tables").whereIn("table_schema", this.explodedSchema).andWhereRaw("\"table_catalog\" = current_database()").andWhere({ table_type: "BASE TABLE" }).orderBy("table_name", "asc");
3595
+ if (table) {
3596
+ const rawTable = await query.andWhere({ table_name: table }).limit(1).first();
3597
+ return {
3598
+ name: rawTable.table_name,
3599
+ schema: rawTable.table_schema,
3600
+ comment: rawTable.table_comment
3601
+ };
3602
+ }
3603
+ return (await query).map((rawTable) => {
3604
+ return {
3605
+ name: rawTable.table_name,
3606
+ schema: rawTable.table_schema,
3607
+ comment: rawTable.table_comment
3608
+ };
3609
+ });
3610
+ }
3611
+ /**
3612
+ * Check if a table exists in the current schema/database
3613
+ */
3614
+ async hasTable(table) {
3615
+ const subquery = this.knex.select().from("information_schema.tables").whereIn("table_schema", this.explodedSchema).andWhere({ table_name: table });
3616
+ const record = await this.knex.select(this.knex.raw("exists (?)", [subquery])).first();
3617
+ return (record === null || record === void 0 ? void 0 : record.exists) || false;
3618
+ }
3619
+ /**
3620
+ * Get all the available columns in the current schema/database. Can be filtered to a specific table
3621
+ */
3622
+ async columns(table) {
3623
+ const query = this.knex.select("table_name", "column_name").from("information_schema.columns").whereIn("table_schema", this.explodedSchema);
3624
+ if (table) query.andWhere({ table_name: table });
3625
+ return (await query).map(({ table_name, column_name }) => ({
3626
+ table: table_name,
3627
+ column: column_name
3628
+ }));
3629
+ }
3630
+ async columnInfo(table, column) {
3631
+ const { knex } = this;
3632
+ const bindings = [];
3633
+ if (table) bindings.push(table);
3634
+ if (column) bindings.push(column);
3635
+ const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
3636
+ const [columns, constraints] = await Promise.all([knex.raw(`
3637
+ SELECT *, CASE WHEN res.is_generated THEN (
3638
+ SELECT
3639
+ generation_expression
3640
+ FROM
3641
+ information_schema.columns
3642
+ WHERE
3643
+ table_schema = res.schema
3644
+ AND table_name = res.table
3645
+ AND column_name = res.name
3646
+ ) ELSE NULL END AS generation_expression
3647
+ FROM (
3648
+ SELECT
3649
+ att.attname AS name,
3650
+ rel.relname AS table,
3651
+ rel.relnamespace::regnamespace::text AS schema,
3652
+ format_type(att.atttypid, null) AS data_type,
3653
+ NOT att.attnotnull AS is_nullable,
3654
+ CASE WHEN att.attgenerated = '' THEN pg_get_expr(ad.adbin, ad.adrelid) ELSE null END AS default_value,
3655
+ att.attgenerated = 's' AS is_generated,
3656
+ CASE
3657
+ WHEN att.atttypid IN (1042, 1043) THEN (att.atttypmod - 4)::int4
3658
+ WHEN att.atttypid IN (1560, 1562) THEN (att.atttypmod)::int4
3659
+ ELSE NULL
3660
+ END AS max_length,
3661
+ des.description AS comment,
3662
+ CASE att.atttypid
3663
+ WHEN 21 THEN 16
3664
+ WHEN 23 THEN 32
3665
+ WHEN 20 THEN 64
3666
+ WHEN 1700 THEN
3667
+ CASE WHEN atttypmod = -1 THEN NULL
3668
+ ELSE (((atttypmod - 4) >> 16) & 65535)::int4
3669
+ END
3670
+ WHEN 700 THEN 24
3671
+ WHEN 701 THEN 53
3672
+ ELSE NULL
3673
+ END AS numeric_precision,
3674
+ CASE
3675
+ WHEN atttypid IN (21, 23, 20) THEN 0
3676
+ WHEN atttypid = 1700 THEN
3677
+ CASE
3678
+ WHEN atttypmod = -1 THEN NULL
3679
+ ELSE ((atttypmod - 4) & 65535)::int4
3680
+ END
3681
+ ELSE null
3682
+ END AS numeric_scale
3683
+ FROM
3684
+ pg_attribute att
3685
+ LEFT JOIN pg_class rel ON att.attrelid = rel.oid
3686
+ LEFT JOIN pg_attrdef ad ON (att.attrelid, att.attnum) = (ad.adrelid, ad.adnum)
3687
+ LEFT JOIN pg_description des ON (att.attrelid, att.attnum) = (des.objoid, des.objsubid)
3688
+ WHERE
3689
+ rel.relnamespace IN (${schemaIn})
3690
+ ${table ? "AND rel.relname = ?" : ""}
3691
+ ${column ? "AND att.attname = ?" : ""}
3692
+ AND rel.relkind = 'r'
3693
+ AND att.attnum > 0
3694
+ AND NOT att.attisdropped
3695
+ ORDER BY rel.relname, att.attnum) res;
3696
+ `, bindings), knex.raw(`
3697
+ SELECT
3698
+ con.contype AS type,
3699
+ rel.relname AS table,
3700
+ att.attname AS column,
3701
+ frel.relnamespace::regnamespace::text AS foreign_key_schema,
3702
+ frel.relname AS foreign_key_table,
3703
+ fatt.attname AS foreign_key_column
3704
+ FROM
3705
+ pg_constraint con
3706
+ LEFT JOIN pg_class rel ON con.conrelid = rel.oid
3707
+ LEFT JOIN pg_class frel ON con.confrelid = frel.oid
3708
+ LEFT JOIN pg_attribute att ON att.attrelid = con.conrelid AND att.attnum = con.conkey[1]
3709
+ LEFT JOIN pg_attribute fatt ON fatt.attrelid = con.confrelid AND fatt.attnum = con.confkey[1]
3710
+ WHERE con.connamespace IN (${schemaIn})
3711
+ AND array_length(con.conkey, 1) <= 1
3712
+ AND (con.confkey IS NULL OR array_length(con.confkey, 1) = 1)
3713
+ ${table ? "AND rel.relname = ?" : ""}
3714
+ ${column ? "AND att.attname = ?" : ""}
3715
+ `, bindings)]);
3716
+ const parsedColumms = columns.rows.map((col) => {
3717
+ var _col$default_value;
3718
+ const constraintsForColumn = constraints.rows.filter((constraint) => constraint.table === col.table && constraint.column === col.name);
3719
+ const foreignKeyConstraint = constraintsForColumn.find((constraint) => constraint.type === "f");
3720
+ return {
3721
+ ...col,
3722
+ is_unique: constraintsForColumn.some((constraint) => ["u", "p"].includes(constraint.type)),
3723
+ is_primary_key: constraintsForColumn.some((constraint) => constraint.type === "p"),
3724
+ has_auto_increment: ["integer", "bigint"].includes(col.data_type) && (((_col$default_value = col.default_value) === null || _col$default_value === void 0 ? void 0 : _col$default_value.startsWith("nextval(")) ?? false),
3725
+ default_value: parseDefaultValue$5(col.default_value),
3726
+ foreign_key_schema: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_schema) ?? null,
3727
+ foreign_key_table: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_table) ?? null,
3728
+ foreign_key_column: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_column) ?? null
3729
+ };
3730
+ });
3731
+ if (table && column) return parsedColumms[0];
3732
+ return parsedColumms;
3733
+ }
3734
+ /**
3735
+ * Check if the given table contains the given column
3736
+ */
3737
+ async hasColumn(table, column) {
3738
+ const subquery = this.knex.select().from("information_schema.columns").whereIn("table_schema", this.explodedSchema).andWhere({
3739
+ table_name: table,
3740
+ column_name: column
3741
+ });
3742
+ const record = await this.knex.select(this.knex.raw("exists (?)", [subquery])).first();
3743
+ return (record === null || record === void 0 ? void 0 : record.exists) || false;
3744
+ }
3745
+ /**
3746
+ * Get the primary key column for the given table
3747
+ */
3748
+ async primary(table) {
3749
+ const result = await this.knex.select("information_schema.key_column_usage.column_name").from("information_schema.key_column_usage").leftJoin("information_schema.table_constraints", function() {
3750
+ this.on("information_schema.table_constraints.constraint_name", "=", "information_schema.key_column_usage.constraint_name").andOn("information_schema.table_constraints.table_name", "=", "information_schema.key_column_usage.table_name");
3751
+ }).whereIn("information_schema.table_constraints.table_schema", this.explodedSchema).andWhere({
3752
+ "information_schema.table_constraints.constraint_type": "PRIMARY KEY",
3753
+ "information_schema.table_constraints.table_name": table
3754
+ });
3755
+ return result.length > 0 ? result.length === 1 ? result[0].column_name : result.map((r) => r.column_name) : null;
3756
+ }
3757
+ async foreignKeys(table) {
3758
+ const rowsWithoutQuotes = (await this.knex.raw(`
3759
+ SELECT
3760
+ c.conrelid::regclass::text AS "table",
3761
+ (
3762
+ SELECT
3763
+ STRING_AGG(a.attname, ','
3764
+ ORDER BY
3765
+ t.seq)
3766
+ FROM (
3767
+ SELECT
3768
+ ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq,
3769
+ attnum
3770
+ FROM
3771
+ UNNEST(c.conkey) AS t (attnum)) AS t
3772
+ INNER JOIN pg_attribute AS a ON a.attrelid = c.conrelid
3773
+ AND a.attnum = t.attnum) AS "column",
3774
+ tt.name AS foreign_key_table,
3775
+ (
3776
+ SELECT
3777
+ STRING_AGG(QUOTE_IDENT(a.attname), ','
3778
+ ORDER BY
3779
+ t.seq)
3780
+ FROM (
3781
+ SELECT
3782
+ ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq,
3783
+ attnum
3784
+ FROM
3785
+ UNNEST(c.confkey) AS t (attnum)) AS t
3786
+ INNER JOIN pg_attribute AS a ON a.attrelid = c.confrelid
3787
+ AND a.attnum = t.attnum) AS foreign_key_column,
3788
+ tt.schema AS foreign_key_schema,
3789
+ c.conname AS constraint_name,
3790
+ CASE confupdtype
3791
+ WHEN 'r' THEN
3792
+ 'RESTRICT'
3793
+ WHEN 'c' THEN
3794
+ 'CASCADE'
3795
+ WHEN 'n' THEN
3796
+ 'SET NULL'
3797
+ WHEN 'd' THEN
3798
+ 'SET DEFAULT'
3799
+ WHEN 'a' THEN
3800
+ 'NO ACTION'
3801
+ ELSE
3802
+ NULL
3803
+ END AS on_update,
3804
+ CASE confdeltype
3805
+ WHEN 'r' THEN
3806
+ 'RESTRICT'
3807
+ WHEN 'c' THEN
3808
+ 'CASCADE'
3809
+ WHEN 'n' THEN
3810
+ 'SET NULL'
3811
+ WHEN 'd' THEN
3812
+ 'SET DEFAULT'
3813
+ WHEN 'a' THEN
3814
+ 'NO ACTION'
3815
+ ELSE
3816
+ NULL
3817
+ END AS
3818
+ on_delete
3819
+ FROM
3820
+ pg_catalog.pg_constraint AS c
3821
+ INNER JOIN (
3822
+ SELECT
3823
+ pg_class.oid,
3824
+ QUOTE_IDENT(pg_namespace.nspname) AS SCHEMA,
3825
+ QUOTE_IDENT(pg_class.relname) AS name
3826
+ FROM
3827
+ pg_class
3828
+ INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid) AS tf ON tf.oid = c.conrelid
3829
+ INNER JOIN (
3830
+ SELECT
3831
+ pg_class.oid,
3832
+ QUOTE_IDENT(pg_namespace.nspname) AS SCHEMA,
3833
+ QUOTE_IDENT(pg_class.relname) AS name
3834
+ FROM
3835
+ pg_class
3836
+ INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid) AS tt ON tt.oid = c.confrelid
3837
+ WHERE
3838
+ c.contype = 'f';
3839
+ `)).rows.map(stripRowQuotes);
3840
+ if (table) return rowsWithoutQuotes.filter((row) => row.table === table);
3841
+ return rowsWithoutQuotes;
3842
+ function stripRowQuotes(row) {
3843
+ return Object.fromEntries(Object.entries(row).map(([key, value]) => {
3844
+ return [key, stripQuotes(value)];
3845
+ }));
3846
+ }
3847
+ }
3848
+ };
3849
+
3850
+ //#endregion
3851
+ //#region src/inspector/dialects/mssql.ts
3852
+ function rawColumnToColumn$2(rawColumn) {
3853
+ return {
3854
+ ...rawColumn,
3855
+ default_value: parseDefaultValue$4(rawColumn.default_value),
3856
+ generation_expression: rawColumn.generation_expression || null,
3857
+ is_generated: !!rawColumn.is_generated,
3858
+ is_unique: rawColumn.is_unique === true,
3859
+ is_primary_key: rawColumn.is_primary_key === true,
3860
+ is_nullable: rawColumn.is_nullable === "YES",
3861
+ has_auto_increment: rawColumn.has_auto_increment === "YES",
3862
+ numeric_precision: rawColumn.numeric_precision || null,
3863
+ numeric_scale: rawColumn.numeric_scale || null,
3864
+ max_length: parseMaxLength(rawColumn)
3865
+ };
3866
+ function parseMaxLength(rawColumn$1) {
3867
+ const max_length = Number(rawColumn$1.max_length);
3868
+ if (Number.isNaN(max_length) || rawColumn$1.max_length === null || rawColumn$1.max_length === void 0) return null;
3869
+ if ([
3870
+ "nvarchar",
3871
+ "nchar",
3872
+ "ntext"
3873
+ ].includes(rawColumn$1.data_type)) return max_length === -1 ? max_length : max_length / 2;
3874
+ return max_length;
3875
+ }
3876
+ }
3877
+ function parseDefaultValue$4(value) {
3878
+ if (value === null) return null;
3879
+ while (value.startsWith("(") && value.endsWith(")")) value = value.slice(1, -1);
3880
+ if (value.trim().toLowerCase() === "null") return null;
3881
+ return stripQuotes(value);
3882
+ }
3883
+ var MSSQL = class {
3884
+ knex;
3885
+ _schema;
3886
+ constructor(knex) {
3887
+ this.knex = knex;
3888
+ }
3889
+ /**
3890
+ * Set the schema to be used in other methods
3891
+ */
3892
+ withSchema(schema) {
3893
+ this.schema = schema;
3894
+ return this;
3895
+ }
3896
+ get schema() {
3897
+ return this._schema || "dbo";
3898
+ }
3899
+ set schema(value) {
3900
+ this._schema = value;
3901
+ }
3902
+ /**
3903
+ * List all existing tables in the current schema/database
3904
+ */
3905
+ async tables() {
3906
+ return (await this.knex.select("TABLE_NAME").from("INFORMATION_SCHEMA.TABLES").where({
3907
+ TABLE_TYPE: "BASE TABLE",
3908
+ TABLE_CATALOG: this.knex.client.database(),
3909
+ TABLE_SCHEMA: this.schema
3910
+ })).map(({ TABLE_NAME }) => TABLE_NAME);
3911
+ }
3912
+ async tableInfo(table) {
3913
+ const query = this.knex.select("TABLE_NAME", "TABLE_SCHEMA", "TABLE_CATALOG", "TABLE_TYPE").from("INFORMATION_SCHEMA.TABLES").where({
3914
+ TABLE_CATALOG: this.knex.client.database(),
3915
+ TABLE_TYPE: "BASE TABLE",
3916
+ TABLE_SCHEMA: this.schema
3917
+ });
3918
+ if (table) {
3919
+ const rawTable = await query.andWhere({ table_name: table }).first();
3920
+ return {
3921
+ name: rawTable.TABLE_NAME,
3922
+ schema: rawTable.TABLE_SCHEMA,
3923
+ catalog: rawTable.TABLE_CATALOG
3924
+ };
3925
+ }
3926
+ return (await query).map((rawTable) => {
3927
+ return {
3928
+ name: rawTable.TABLE_NAME,
3929
+ schema: rawTable.TABLE_SCHEMA,
3930
+ catalog: rawTable.TABLE_CATALOG
3931
+ };
3932
+ });
3933
+ }
3934
+ /**
3935
+ * Check if a table exists in the current schema/database
3936
+ */
3937
+ async hasTable(table) {
3938
+ const result = await this.knex.count({ count: "*" }).from("INFORMATION_SCHEMA.TABLES").where({
3939
+ TABLE_CATALOG: this.knex.client.database(),
3940
+ table_name: table,
3941
+ TABLE_SCHEMA: this.schema
3942
+ }).first();
3943
+ return result && result.count === 1 || false;
3944
+ }
3945
+ /**
3946
+ * Get all the available columns in the current schema/database. Can be filtered to a specific table
3947
+ */
3948
+ async columns(table) {
3949
+ const query = this.knex.select("TABLE_NAME", "COLUMN_NAME").from("INFORMATION_SCHEMA.COLUMNS").where({
3950
+ TABLE_CATALOG: this.knex.client.database(),
3951
+ TABLE_SCHEMA: this.schema
3952
+ });
3953
+ if (table) query.andWhere({ TABLE_NAME: table });
3954
+ return (await query).map(({ TABLE_NAME, COLUMN_NAME }) => ({
3955
+ table: TABLE_NAME,
3956
+ column: COLUMN_NAME
3957
+ }));
3958
+ }
3959
+ async columnInfo(table, column) {
3960
+ const dbName = this.knex.client.database();
3961
+ const query = this.knex.select(this.knex.raw(`
3962
+ [o].[name] AS [table],
3963
+ [c].[name] AS [name],
3964
+ [t].[name] AS [data_type],
3965
+ [c].[max_length] AS [max_length],
3966
+ [c].[precision] AS [numeric_precision],
3967
+ [c].[scale] AS [numeric_scale],
3968
+ CASE WHEN [c].[is_nullable] = 0 THEN
3969
+ 'NO'
3970
+ ELSE
3971
+ 'YES'
3972
+ END AS [is_nullable],
3973
+ object_definition ([c].[default_object_id]) AS [default_value],
3974
+ [i].[is_primary_key],
3975
+ [i].[is_unique],
3976
+ CASE [c].[is_identity]
3977
+ WHEN 1 THEN
3978
+ 'YES'
3979
+ ELSE
3980
+ 'NO'
3981
+ END AS [has_auto_increment],
3982
+ OBJECT_NAME ([fk].[referenced_object_id]) AS [foreign_key_table],
3983
+ COL_NAME ([fk].[referenced_object_id],
3984
+ [fk].[referenced_column_id]) AS [foreign_key_column],
3985
+ [cc].[is_computed] as [is_generated],
3986
+ [cc].[definition] as [generation_expression]`)).from(this.knex.raw("??.[sys].[columns] [c]", [dbName])).joinRaw("JOIN [sys].[types] [t] ON [c].[user_type_id] = [t].[user_type_id]").joinRaw("JOIN [sys].[tables] [o] ON [o].[object_id] = [c].[object_id]").joinRaw("JOIN [sys].[schemas] [s] ON [s].[schema_id] = [o].[schema_id]").joinRaw("LEFT JOIN [sys].[computed_columns] AS [cc] ON [cc].[object_id] = [c].[object_id] AND [cc].[column_id] = [c].[column_id]").joinRaw("LEFT JOIN [sys].[foreign_key_columns] AS [fk] ON [fk].[parent_object_id] = [c].[object_id] AND [fk].[parent_column_id] = [c].[column_id]").joinRaw(`LEFT JOIN (
3987
+ SELECT
3988
+ [ic].[object_id],
3989
+ [ic].[column_id],
3990
+ [ix].[is_unique],
3991
+ [ix].[is_primary_key],
3992
+ MAX([ic].[index_column_id]) OVER(partition by [ic].[index_id], [ic].[object_id]) AS index_column_count,
3993
+ ROW_NUMBER() OVER (
3994
+ PARTITION BY [ic].[object_id], [ic].[column_id]
3995
+ ORDER BY [ix].[is_primary_key] DESC, [ix].[is_unique] DESC
3996
+ ) AS index_priority
3997
+ FROM
3998
+ [sys].[index_columns] [ic]
3999
+ JOIN [sys].[indexes] AS [ix] ON [ix].[object_id] = [ic].[object_id]
4000
+ AND [ix].[index_id] = [ic].[index_id]
4001
+ ) AS [i]
4002
+ ON [i].[object_id] = [c].[object_id]
4003
+ AND [i].[column_id] = [c].[column_id]
4004
+ AND ISNULL([i].[index_column_count], 1) = 1
4005
+ AND ISNULL([i].[index_priority], 1) = 1`).where({ "s.name": this.schema });
4006
+ if (table) query.andWhere({ "o.name": table });
4007
+ if (column) {
4008
+ const rawColumn = await query.andWhere({ "c.name": column }).first();
4009
+ return rawColumnToColumn$2(rawColumn);
4010
+ }
4011
+ return (await query).map(rawColumnToColumn$2);
4012
+ }
4013
+ /**
4014
+ * Check if a table exists in the current schema/database
4015
+ */
4016
+ async hasColumn(table, column) {
4017
+ const result = await this.knex.count({ count: "*" }).from("INFORMATION_SCHEMA.COLUMNS").where({
4018
+ TABLE_CATALOG: this.knex.client.database(),
4019
+ TABLE_NAME: table,
4020
+ COLUMN_NAME: column,
4021
+ TABLE_SCHEMA: this.schema
4022
+ }).first();
4023
+ return result && result.count === 1 || false;
4024
+ }
4025
+ /**
4026
+ * Get the primary key column for the given table
4027
+ */
4028
+ async primary(table) {
4029
+ const results = await this.knex.raw(`SELECT
4030
+ Col.Column_Name
4031
+ FROM
4032
+ INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab,
4033
+ INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col
4034
+ WHERE
4035
+ Col.Constraint_Name = Tab.Constraint_Name
4036
+ AND Col.Table_Name = Tab.Table_Name
4037
+ AND Constraint_Type = 'PRIMARY KEY'
4038
+ AND Col.Table_Name = ?
4039
+ AND Tab.CONSTRAINT_SCHEMA = ?`, [table, this.schema]);
4040
+ return results.length > 0 ? results.length === 1 ? results[0]["Column_Name"] : results.map((row) => row["Column_Name"]) : null;
4041
+ }
4042
+ async foreignKeys(table) {
4043
+ const result = await this.knex.raw(`
4044
+ SELECT
4045
+ OBJECT_NAME (fc.parent_object_id) AS "table",
4046
+ COL_NAME (fc.parent_object_id, fc.parent_column_id) AS "column",
4047
+ OBJECT_SCHEMA_NAME (f.referenced_object_id) AS foreign_key_schema,
4048
+ OBJECT_NAME (f.referenced_object_id) AS foreign_key_table,
4049
+ COL_NAME (fc.referenced_object_id, fc.referenced_column_id) AS foreign_key_column,
4050
+ f.name AS constraint_name,
4051
+ REPLACE(f.update_referential_action_desc, '_', ' ') AS on_update,
4052
+ REPLACE(f.delete_referential_action_desc, '_', ' ') AS on_delete
4053
+ FROM
4054
+ sys.foreign_keys AS f
4055
+ INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id
4056
+ WHERE
4057
+ OBJECT_SCHEMA_NAME (f.parent_object_id) = ?;
4058
+ `, [this.schema]);
4059
+ if (table) return result === null || result === void 0 ? void 0 : result.filter((row) => row.table === table);
4060
+ return result;
4061
+ }
4062
+ };
4063
+
4064
+ //#endregion
4065
+ //#region src/inspector/dialects/mysql.ts
4066
+ function rawColumnToColumn$1(rawColumn) {
4067
+ var _rawColumn$EXTRA;
4068
+ let dataType = rawColumn.COLUMN_TYPE.replace(/\(.*?\)/, "");
4069
+ if (rawColumn.COLUMN_TYPE.startsWith("tinyint(1)")) dataType = "boolean";
4070
+ return {
4071
+ name: rawColumn.COLUMN_NAME,
4072
+ table: rawColumn.TABLE_NAME,
4073
+ collation: rawColumn.COLLATION_NAME,
4074
+ data_type: dataType,
4075
+ default_value: parseDefaultValue$3(rawColumn.COLUMN_DEFAULT),
4076
+ generation_expression: rawColumn.GENERATION_EXPRESSION || null,
4077
+ max_length: rawColumn.CHARACTER_MAXIMUM_LENGTH,
4078
+ numeric_precision: rawColumn.NUMERIC_PRECISION,
4079
+ numeric_scale: rawColumn.NUMERIC_SCALE,
4080
+ is_generated: !!((_rawColumn$EXTRA = rawColumn.EXTRA) === null || _rawColumn$EXTRA === void 0 ? void 0 : _rawColumn$EXTRA.endsWith("GENERATED")),
4081
+ is_nullable: rawColumn.IS_NULLABLE === "YES",
4082
+ is_unique: rawColumn.COLUMN_KEY === "UNI",
4083
+ is_primary_key: rawColumn.CONSTRAINT_NAME === "PRIMARY" || rawColumn.COLUMN_KEY === "PRI",
4084
+ has_auto_increment: rawColumn.EXTRA === "auto_increment",
4085
+ foreign_key_column: rawColumn.REFERENCED_COLUMN_NAME,
4086
+ foreign_key_table: rawColumn.REFERENCED_TABLE_NAME,
4087
+ comment: rawColumn.COLUMN_COMMENT
4088
+ };
4089
+ }
4090
+ function parseDefaultValue$3(value) {
4091
+ if (value === null || value.trim().toLowerCase() === "null") return null;
4092
+ return stripQuotes(value);
4093
+ }
4094
+ var MySQL = class {
4095
+ knex;
4096
+ constructor(knex) {
4097
+ this.knex = knex;
4098
+ }
4099
+ /**
4100
+ * List all existing tables in the current schema/database
4101
+ */
4102
+ async tables() {
4103
+ return (await this.knex.select("TABLE_NAME").from("INFORMATION_SCHEMA.TABLES").where({
4104
+ TABLE_TYPE: "BASE TABLE",
4105
+ TABLE_SCHEMA: this.knex.client.database()
4106
+ })).map(({ TABLE_NAME }) => TABLE_NAME);
4107
+ }
4108
+ async tableInfo(table) {
4109
+ const query = this.knex.select("TABLE_NAME", "ENGINE", "TABLE_SCHEMA", "TABLE_COLLATION", "TABLE_COMMENT").from("information_schema.tables").where({
4110
+ table_schema: this.knex.client.database(),
4111
+ table_type: "BASE TABLE"
4112
+ });
4113
+ if (table) {
4114
+ const rawTable = await query.andWhere({ table_name: table }).first();
4115
+ return {
4116
+ name: rawTable.TABLE_NAME,
4117
+ schema: rawTable.TABLE_SCHEMA,
4118
+ comment: rawTable.TABLE_COMMENT,
4119
+ collation: rawTable.TABLE_COLLATION,
4120
+ engine: rawTable.ENGINE
4121
+ };
4122
+ }
4123
+ return (await query).map((rawTable) => {
4124
+ return {
4125
+ name: rawTable.TABLE_NAME,
4126
+ schema: rawTable.TABLE_SCHEMA,
4127
+ comment: rawTable.TABLE_COMMENT,
4128
+ collation: rawTable.TABLE_COLLATION,
4129
+ engine: rawTable.ENGINE
4130
+ };
4131
+ });
4132
+ }
4133
+ /**
4134
+ * Check if a table exists in the current schema/database
4135
+ */
4136
+ async hasTable(table) {
4137
+ const result = await this.knex.count({ count: "*" }).from("information_schema.tables").where({
4138
+ table_schema: this.knex.client.database(),
4139
+ table_name: table
4140
+ }).first();
4141
+ return result && result.count === 1 || false;
4142
+ }
4143
+ /**
4144
+ * Get all the available columns in the current schema/database. Can be filtered to a specific table
4145
+ */
4146
+ async columns(table) {
4147
+ const query = this.knex.select("TABLE_NAME", "COLUMN_NAME").from("INFORMATION_SCHEMA.COLUMNS").where({ TABLE_SCHEMA: this.knex.client.database() });
4148
+ if (table) query.andWhere({ TABLE_NAME: table });
4149
+ return (await query).map(({ TABLE_NAME, COLUMN_NAME }) => ({
4150
+ table: TABLE_NAME,
4151
+ column: COLUMN_NAME
4152
+ }));
4153
+ }
4154
+ async columnInfo(table, column) {
4155
+ const query = this.knex.select("c.TABLE_NAME", "c.COLUMN_NAME", "c.COLUMN_DEFAULT", "c.COLUMN_TYPE", "c.CHARACTER_MAXIMUM_LENGTH", "c.IS_NULLABLE", "c.COLUMN_KEY", "c.EXTRA", "c.COLLATION_NAME", "c.COLUMN_COMMENT", "c.NUMERIC_PRECISION", "c.NUMERIC_SCALE", "c.GENERATION_EXPRESSION", "fk.REFERENCED_TABLE_NAME", "fk.REFERENCED_COLUMN_NAME", "fk.CONSTRAINT_NAME", "rc.UPDATE_RULE", "rc.DELETE_RULE", "rc.MATCH_OPTION").from("INFORMATION_SCHEMA.COLUMNS as c").leftJoin("INFORMATION_SCHEMA.KEY_COLUMN_USAGE as fk", function() {
4156
+ this.on("c.TABLE_NAME", "=", "fk.TABLE_NAME").andOn("fk.COLUMN_NAME", "=", "c.COLUMN_NAME").andOn("fk.CONSTRAINT_SCHEMA", "=", "c.TABLE_SCHEMA");
4157
+ }).leftJoin("INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as rc", function() {
4158
+ this.on("rc.TABLE_NAME", "=", "fk.TABLE_NAME").andOn("rc.CONSTRAINT_NAME", "=", "fk.CONSTRAINT_NAME").andOn("rc.CONSTRAINT_SCHEMA", "=", "fk.CONSTRAINT_SCHEMA");
4159
+ }).where({ "c.TABLE_SCHEMA": this.knex.client.database() });
4160
+ if (table) query.andWhere({ "c.TABLE_NAME": table });
4161
+ if (column) {
4162
+ const rawColumn = await query.andWhere({ "c.column_name": column }).first();
4163
+ return rawColumnToColumn$1(rawColumn);
4164
+ }
4165
+ return (await query).map(rawColumnToColumn$1).sort((column$1) => +!column$1.foreign_key_column).filter((column$1, index, records) => {
4166
+ return records.findIndex((_column) => {
4167
+ return column$1.name === _column.name && column$1.table === _column.table;
4168
+ }) === index;
4169
+ });
4170
+ }
4171
+ /**
4172
+ * Check if a table exists in the current schema/database
4173
+ */
4174
+ async hasColumn(table, column) {
4175
+ const result = await this.knex.count("*", { as: "count" }).from("information_schema.columns").where({
4176
+ table_schema: this.knex.client.database(),
4177
+ table_name: table,
4178
+ column_name: column
4179
+ }).first();
4180
+ return !!(result && result.count);
4181
+ }
4182
+ /**
4183
+ * Get the primary key column for the given table
4184
+ */
4185
+ async primary(table) {
4186
+ const results = await this.knex.raw("SHOW KEYS FROM ?? WHERE Key_name = 'PRIMARY'", table);
4187
+ if (results && results.length && results[0].length) {
4188
+ if (results[0].length === 1) return results[0][0]["Column_name"];
4189
+ return results[0].map((row) => row["Column_name"]);
4190
+ }
4191
+ return null;
4192
+ }
4193
+ async foreignKeys(table) {
4194
+ const query = this.knex.select("rc.TABLE_NAME AS table", "kcu.COLUMN_NAME AS column", "rc.REFERENCED_TABLE_NAME AS foreign_key_table", "kcu.REFERENCED_COLUMN_NAME AS foreign_key_column", "rc.CONSTRAINT_NAME AS constraint_name", "rc.UPDATE_RULE AS on_update", "rc.DELETE_RULE AS on_delete").from("information_schema.referential_constraints AS rc").leftJoin("information_schema.key_column_usage AS kcu ", function() {
4195
+ this.on("rc.CONSTRAINT_NAME", "=", "kcu.CONSTRAINT_NAME").andOn("kcu.CONSTRAINT_SCHEMA", "=", "rc.CONSTRAINT_SCHEMA");
4196
+ }).where({ "rc.CONSTRAINT_SCHEMA": this.knex.client.database() });
4197
+ if (table) query.andWhere({ "rc.TABLE_NAME": table });
4198
+ return await query;
4199
+ }
4200
+ async uniqueConstraints(table) {
4201
+ const { knex } = this;
4202
+ const query = knex.select("stat.table_name AS table_name", "stat.index_name AS constraint_name", knex.raw("group_concat(stat.column_name ORDER BY stat.seq_in_index separator ', ') AS columns")).from("information_schema.statistics stat").join("information_schema.table_constraints tco", function() {
4203
+ this.on("stat.table_schema", "=", "tco.table_schema").andOn("stat.table_name", "=", "tco.table_name").andOn("stat.index_name", "=", "tco.constraint_name");
4204
+ }).where("stat.non_unique", "=", 0).andWhere("tco.constraint_type", "=", "UNIQUE").andWhere("stat.table_schema", knex.client.database()).groupBy([
4205
+ "stat.table_name",
4206
+ "stat.index_name",
4207
+ "tco.constraint_type"
4208
+ ]);
4209
+ if (table) query.andWhere("stat.table_name", "=", table);
4210
+ return (await query).map((v) => ({
4211
+ table: v.table_name,
4212
+ constraint_name: v.constraint_name,
4213
+ columns: v.columns
4214
+ }));
4215
+ }
4216
+ };
4217
+
4218
+ //#endregion
4219
+ //#region src/inspector/dialects/oracledb.ts
4220
+ /**
4221
+ * NOTE: Use previous optimizer for better data dictionary performance.
4222
+ */
4223
+ const OPTIMIZER_FEATURES = "11.2.0.4";
4224
+ function rawColumnToColumn(rawColumn) {
4225
+ const is_generated = rawColumn.VIRTUAL_COLUMN === "YES";
4226
+ const default_value = parseDefaultValue$2(rawColumn.DATA_DEFAULT);
4227
+ return {
4228
+ name: rawColumn.COLUMN_NAME,
4229
+ table: rawColumn.TABLE_NAME,
4230
+ data_type: rawColumn.DATA_TYPE,
4231
+ default_value: !is_generated ? default_value : null,
4232
+ generation_expression: is_generated ? default_value : null,
4233
+ max_length: rawColumn.DATA_LENGTH,
4234
+ numeric_precision: rawColumn.DATA_PRECISION,
4235
+ numeric_scale: rawColumn.DATA_SCALE,
4236
+ is_generated: rawColumn.VIRTUAL_COLUMN === "YES",
4237
+ is_nullable: rawColumn.NULLABLE === "Y",
4238
+ is_unique: rawColumn.CONSTRAINT_TYPE === "U",
4239
+ is_primary_key: rawColumn.CONSTRAINT_TYPE === "P",
4240
+ has_auto_increment: rawColumn.IDENTITY_COLUMN === "YES",
4241
+ foreign_key_column: rawColumn.REFERENCED_COLUMN_NAME,
4242
+ foreign_key_table: rawColumn.REFERENCED_TABLE_NAME,
4243
+ comment: rawColumn.COLUMN_COMMENT
4244
+ };
4245
+ }
4246
+ function parseDefaultValue$2(value) {
4247
+ if (value === null || value.trim().toLowerCase() === "null") return null;
4248
+ if (value === "CURRENT_TIMESTAMP ") return "CURRENT_TIMESTAMP";
4249
+ return stripQuotes(value);
4250
+ }
4251
+ var oracleDB = class {
4252
+ knex;
4253
+ constructor(knex) {
4254
+ this.knex = knex;
4255
+ }
4256
+ /**
4257
+ * List all existing tables in the current schema/database
4258
+ */
4259
+ async tables() {
4260
+ return (await this.knex.select(this.knex.raw(`
4261
+ /*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
4262
+ "TABLE_NAME" "name"
4263
+ `)).from("USER_TABLES")).map(({ name }) => name);
4264
+ }
4265
+ async tableInfo(table) {
4266
+ const query = this.knex.select(this.knex.raw(`
4267
+ /*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
4268
+ "TABLE_NAME" "name"
4269
+ `)).from("USER_TABLES");
4270
+ if (table) return await query.andWhere({ TABLE_NAME: table }).first();
4271
+ return await query;
4272
+ }
4273
+ /**
4274
+ * Check if a table exists in the current schema/database
4275
+ */
4276
+ async hasTable(table) {
4277
+ const result = await this.knex.select(this.knex.raw(`
4278
+ /*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
4279
+ COUNT(*) "count"
4280
+ `)).from("USER_TABLES").where({ TABLE_NAME: table }).first();
4281
+ return !!(result === null || result === void 0 ? void 0 : result.count);
4282
+ }
4283
+ /**
4284
+ * Get all the available columns in the current schema/database. Can be filtered to a specific table
4285
+ */
4286
+ async columns(table) {
4287
+ const query = this.knex.select(this.knex.raw(`
4288
+ /*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') NO_QUERY_TRANSFORMATION */
4289
+ "TABLE_NAME" "table",
4290
+ "COLUMN_NAME" "column"
4291
+ `)).from("USER_TAB_COLS").where({ HIDDEN_COLUMN: "NO" });
4292
+ if (table) query.andWhere({ TABLE_NAME: table });
4293
+ return await query;
4294
+ }
4295
+ async columnInfo(table, column) {
4296
+ /**
4297
+ * NOTE: Keep in mind, this query is optimized for speed.
4298
+ */
4299
+ const query = this.knex.with("uc", this.knex.raw(`
4300
+ SELECT /*+ MATERIALIZE */
4301
+ "uc"."TABLE_NAME",
4302
+ "ucc"."COLUMN_NAME",
4303
+ "uc"."CONSTRAINT_NAME",
4304
+ "uc"."CONSTRAINT_TYPE",
4305
+ "uc"."R_CONSTRAINT_NAME",
4306
+ COUNT(*) OVER(
4307
+ PARTITION BY
4308
+ "uc"."CONSTRAINT_NAME"
4309
+ ) "CONSTRAINT_COUNT",
4310
+ ROW_NUMBER() OVER(
4311
+ PARTITION BY
4312
+ "uc"."TABLE_NAME",
4313
+ "ucc"."COLUMN_NAME"
4314
+ ORDER BY
4315
+ "uc"."CONSTRAINT_TYPE"
4316
+ ) "CONSTRAINT_PRIORITY"
4317
+ FROM "USER_CONSTRAINTS" "uc"
4318
+ INNER JOIN "USER_CONS_COLUMNS" "ucc"
4319
+ ON "uc"."CONSTRAINT_NAME" = "ucc"."CONSTRAINT_NAME"
4320
+ WHERE "uc"."CONSTRAINT_TYPE" IN ('P', 'U', 'R')
4321
+ `)).select(this.knex.raw(`
4322
+ /*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
4323
+ "c"."TABLE_NAME",
4324
+ "c"."COLUMN_NAME",
4325
+ "c"."DATA_DEFAULT",
4326
+ "c"."DATA_TYPE",
4327
+ "c"."DATA_LENGTH",
4328
+ "c"."DATA_PRECISION",
4329
+ "c"."DATA_SCALE",
4330
+ "c"."NULLABLE",
4331
+ "c"."IDENTITY_COLUMN",
4332
+ "c"."VIRTUAL_COLUMN",
4333
+ "cm"."COMMENTS" "COLUMN_COMMENT",
4334
+ "ct"."CONSTRAINT_TYPE",
4335
+ "fk"."TABLE_NAME" "REFERENCED_TABLE_NAME",
4336
+ "fk"."COLUMN_NAME" "REFERENCED_COLUMN_NAME"
4337
+ FROM "USER_TAB_COLS" "c"
4338
+ LEFT JOIN "USER_COL_COMMENTS" "cm"
4339
+ ON "c"."TABLE_NAME" = "cm"."TABLE_NAME"
4340
+ AND "c"."COLUMN_NAME" = "cm"."COLUMN_NAME"
4341
+ LEFT JOIN "uc" "ct"
4342
+ ON "c"."TABLE_NAME" = "ct"."TABLE_NAME"
4343
+ AND "c"."COLUMN_NAME" = "ct"."COLUMN_NAME"
4344
+ AND "ct"."CONSTRAINT_COUNT" = 1
4345
+ AND "ct"."CONSTRAINT_PRIORITY" = 1
4346
+ LEFT JOIN "uc" "fk"
4347
+ ON "ct"."R_CONSTRAINT_NAME" = "fk"."CONSTRAINT_NAME"
4348
+ `)).where({ "c.HIDDEN_COLUMN": "NO" });
4349
+ if (table) query.andWhere({ "c.TABLE_NAME": table });
4350
+ if (column) {
4351
+ const rawColumn = await query.andWhere({ "c.COLUMN_NAME": column }).first();
4352
+ return rawColumnToColumn(rawColumn);
4353
+ }
4354
+ return (await query).map(rawColumnToColumn);
4355
+ }
4356
+ /**
4357
+ * Check if a table exists in the current schema/database
4358
+ */
4359
+ async hasColumn(table, column) {
4360
+ const result = await this.knex.select(this.knex.raw(`
4361
+ /*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') NO_QUERY_TRANSFORMATION */
4362
+ COUNT(*) "count"
4363
+ `)).from("USER_TAB_COLS").where({
4364
+ TABLE_NAME: table,
4365
+ COLUMN_NAME: column,
4366
+ HIDDEN_COLUMN: "NO"
4367
+ }).first();
4368
+ return !!(result === null || result === void 0 ? void 0 : result.count);
4369
+ }
4370
+ /**
4371
+ * Get the primary key column for the given table
4372
+ */
4373
+ async primary(table) {
4374
+ /**
4375
+ * NOTE: Keep in mind, this query is optimized for speed.
4376
+ */
4377
+ const result = await this.knex.with("uc", this.knex.select(this.knex.raw("/*+ MATERIALIZE */ \"CONSTRAINT_NAME\"")).from("USER_CONSTRAINTS").where({
4378
+ TABLE_NAME: table,
4379
+ CONSTRAINT_TYPE: "P"
4380
+ })).select(this.knex.raw(`
4381
+ /*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
4382
+ "ucc"."COLUMN_NAME"
4383
+ FROM "USER_CONS_COLUMNS" "ucc"
4384
+ INNER JOIN "uc" "pk"
4385
+ ON "ucc"."CONSTRAINT_NAME" = "pk"."CONSTRAINT_NAME"
4386
+ `));
4387
+ return result.length > 0 ? result.length === 1 ? result[0].COLUMN_NAME : result.map((r) => r.COLUMN_NAME) : null;
4388
+ }
4389
+ async foreignKeys(table) {
4390
+ /**
4391
+ * NOTE: Keep in mind, this query is optimized for speed.
4392
+ */
4393
+ const query = this.knex.with("ucc", this.knex.raw(`
4394
+ SELECT /*+ MATERIALIZE */
4395
+ "TABLE_NAME",
4396
+ "COLUMN_NAME",
4397
+ "CONSTRAINT_NAME"
4398
+ FROM "USER_CONS_COLUMNS"
4399
+ `)).select(this.knex.raw(`
4400
+ /*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
4401
+ "uc"."TABLE_NAME" "table",
4402
+ "fcc"."COLUMN_NAME" "column",
4403
+ "rcc"."TABLE_NAME" AS "foreign_key_table",
4404
+ "rcc"."COLUMN_NAME" AS "foreign_key_column",
4405
+ "uc"."CONSTRAINT_NAME" "constraint_name",
4406
+ NULL as "on_update",
4407
+ "uc"."DELETE_RULE" "on_delete"
4408
+ FROM "USER_CONSTRAINTS" "uc"
4409
+ INNER JOIN "ucc" "fcc"
4410
+ ON "uc"."CONSTRAINT_NAME" = "fcc"."CONSTRAINT_NAME"
4411
+ INNER JOIN "ucc" "rcc"
4412
+ ON "uc"."R_CONSTRAINT_NAME" = "rcc"."CONSTRAINT_NAME"
4413
+ `)).where({ "uc.CONSTRAINT_TYPE": "R" });
4414
+ if (table) query.andWhere({ "uc.TABLE_NAME": table });
4415
+ return await query;
4416
+ }
4417
+ };
4418
+
4419
+ //#endregion
4420
+ //#region src/inspector/dialects/postgres.ts
4421
+ /**
4422
+ * Converts Postgres default value to JS
4423
+ * Eg `'example'::character varying` => `example`
4424
+ */
4425
+ function parseDefaultValue$1(value) {
4426
+ if (value === null) return null;
4427
+ if (value.startsWith("nextval(")) return value;
4428
+ value = value.split("::")[0];
4429
+ if (value.trim().toLowerCase() === "null") return null;
4430
+ return stripQuotes(value);
4431
+ }
4432
+ var Postgres = class {
4433
+ knex;
4434
+ schema;
4435
+ explodedSchema;
4436
+ constructor(knex) {
4437
+ this.knex = knex;
4438
+ const config = knex.client.config;
4439
+ if (!config.searchPath) {
4440
+ this.schema = "public";
4441
+ this.explodedSchema = [this.schema];
4442
+ } else if (typeof config.searchPath === "string") {
4443
+ this.schema = config.searchPath;
4444
+ this.explodedSchema = [config.searchPath];
4445
+ } else {
4446
+ this.schema = config.searchPath[0];
4447
+ this.explodedSchema = config.searchPath;
4448
+ }
4449
+ }
4450
+ /**
4451
+ * Set the schema to be used in other methods
4452
+ */
4453
+ withSchema(schema) {
4454
+ this.schema = schema;
4455
+ this.explodedSchema = [this.schema];
4456
+ return this;
4457
+ }
4458
+ /**
4459
+ * List all existing tables in the current schema/database
4460
+ */
4461
+ async tables() {
4462
+ const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
4463
+ return (await this.knex.raw(`
4464
+ SELECT
4465
+ rel.relname AS name
4466
+ FROM
4467
+ pg_class rel
4468
+ WHERE
4469
+ rel.relnamespace IN (${schemaIn})
4470
+ AND rel.relkind = 'r'
4471
+ ORDER BY rel.relname
4472
+ `)).rows.map((row) => row.name);
4473
+ }
4474
+ async tableInfo(table) {
4475
+ const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
4476
+ const bindings = [];
4477
+ if (table) bindings.push(table);
4478
+ const result = await this.knex.raw(`
4479
+ SELECT
4480
+ rel.relnamespace::regnamespace::text AS schema,
4481
+ rel.relname AS name,
4482
+ des.description AS comment
4483
+ FROM
4484
+ pg_class rel
4485
+ LEFT JOIN pg_description des ON rel.oid = des.objoid AND des.objsubid = 0
4486
+ WHERE
4487
+ rel.relnamespace IN (${schemaIn})
4488
+ ${table ? "AND rel.relname = ?" : ""}
4489
+ AND rel.relkind = 'r'
4490
+ ORDER BY rel.relname
4491
+ `, bindings);
4492
+ if (table) return result.rows[0];
4493
+ return result.rows;
4494
+ }
4495
+ /**
4496
+ * Check if a table exists in the current schema/database
4497
+ */
4498
+ async hasTable(table) {
4499
+ const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
4500
+ return (await this.knex.raw(`
4501
+ SELECT
4502
+ rel.relname AS name
4503
+ FROM
4504
+ pg_class rel
4505
+ WHERE
4506
+ rel.relnamespace IN (${schemaIn})
4507
+ AND rel.relkind = 'r'
4508
+ AND rel.relname = ?
4509
+ ORDER BY rel.relname
4510
+ `, [table])).rows.length > 0;
4511
+ }
4512
+ /**
4513
+ * Get all the available columns in the current schema/database. Can be filtered to a specific table
4514
+ */
4515
+ async columns(table) {
4516
+ const bindings = [];
4517
+ if (table) bindings.push(table);
4518
+ const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
4519
+ return (await this.knex.raw(`
4520
+ SELECT
4521
+ att.attname AS column,
4522
+ rel.relname AS table
4523
+ FROM
4524
+ pg_attribute att
4525
+ LEFT JOIN pg_class rel ON att.attrelid = rel.oid
4526
+ WHERE
4527
+ rel.relnamespace IN (${schemaIn})
4528
+ ${table ? "AND rel.relname = ?" : ""}
4529
+ AND rel.relkind = 'r'
4530
+ AND att.attnum > 0
4531
+ AND NOT att.attisdropped;
4532
+ `, bindings)).rows;
4533
+ }
4534
+ async columnInfo(table, column) {
4535
+ var _versionResponse$rows;
4536
+ const { knex } = this;
4537
+ const bindings = [];
4538
+ if (table) bindings.push(table);
4539
+ if (column) bindings.push(column);
4540
+ const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
4541
+ const majorVersion = ((_versionResponse$rows = (await this.knex.raw("SHOW server_version")).rows) === null || _versionResponse$rows === void 0 || (_versionResponse$rows = _versionResponse$rows[0]) === null || _versionResponse$rows === void 0 || (_versionResponse$rows = _versionResponse$rows.server_version) === null || _versionResponse$rows === void 0 || (_versionResponse$rows = _versionResponse$rows.split(".")) === null || _versionResponse$rows === void 0 ? void 0 : _versionResponse$rows[0]) ?? 10;
4542
+ let generationSelect = `
4543
+ NULL AS generation_expression,
4544
+ pg_get_expr(ad.adbin, ad.adrelid) AS default_value,
4545
+ FALSE AS is_generated,
4546
+ `;
4547
+ if (Number(majorVersion) >= 12) generationSelect = `
4548
+ CASE WHEN att.attgenerated = 's' THEN pg_get_expr(ad.adbin, ad.adrelid) ELSE null END AS generation_expression,
4549
+ CASE WHEN att.attgenerated = '' THEN pg_get_expr(ad.adbin, ad.adrelid) ELSE null END AS default_value,
4550
+ att.attgenerated = 's' AS is_generated,
4551
+ `;
4552
+ const [columns, constraints] = await Promise.all([knex.raw(`
4553
+ SELECT
4554
+ att.attname AS name,
4555
+ rel.relname AS table,
4556
+ rel.relnamespace::regnamespace::text as schema,
4557
+ att.atttypid::regtype::text AS data_type,
4558
+ NOT att.attnotnull AS is_nullable,
4559
+ ${generationSelect}
4560
+ CASE
4561
+ WHEN att.atttypid IN (1042, 1043) THEN (att.atttypmod - 4)::int4
4562
+ WHEN att.atttypid IN (1560, 1562) THEN (att.atttypmod)::int4
4563
+ ELSE NULL
4564
+ END AS max_length,
4565
+ des.description AS comment,
4566
+ CASE att.atttypid
4567
+ WHEN 21 THEN 16
4568
+ WHEN 23 THEN 32
4569
+ WHEN 20 THEN 64
4570
+ WHEN 1700 THEN
4571
+ CASE WHEN atttypmod = -1 THEN NULL
4572
+ ELSE (((atttypmod - 4) >> 16) & 65535)::int4
4573
+ END
4574
+ WHEN 700 THEN 24
4575
+ WHEN 701 THEN 53
4576
+ ELSE NULL
4577
+ END AS numeric_precision,
4578
+ CASE
4579
+ WHEN atttypid IN (21, 23, 20) THEN 0
4580
+ WHEN atttypid = 1700 THEN
4581
+ CASE
4582
+ WHEN atttypmod = -1 THEN NULL
4583
+ ELSE ((atttypmod - 4) & 65535)::int4
4584
+ END
4585
+ ELSE null
4586
+ END AS numeric_scale
4587
+ FROM
4588
+ pg_attribute att
4589
+ LEFT JOIN pg_class rel ON att.attrelid = rel.oid
4590
+ LEFT JOIN pg_attrdef ad ON (att.attrelid, att.attnum) = (ad.adrelid, ad.adnum)
4591
+ LEFT JOIN pg_description des ON (att.attrelid, att.attnum) = (des.objoid, des.objsubid)
4592
+ WHERE
4593
+ rel.relnamespace IN (${schemaIn})
4594
+ ${table ? "AND rel.relname = ?" : ""}
4595
+ ${column ? "AND att.attname = ?" : ""}
4596
+ AND rel.relkind = 'r'
4597
+ AND att.attnum > 0
4598
+ AND NOT att.attisdropped
4599
+ ORDER BY rel.relname, att.attnum;
4600
+ `, bindings), knex.raw(`
4601
+ SELECT
4602
+ con.contype AS type,
4603
+ rel.relname AS table,
4604
+ att.attname AS column,
4605
+ frel.relnamespace::regnamespace::text AS foreign_key_schema,
4606
+ frel.relname AS foreign_key_table,
4607
+ fatt.attname AS foreign_key_column,
4608
+ CASE
4609
+ WHEN con.contype = 'p' THEN pg_get_serial_sequence(att.attrelid::regclass::text, att.attname) != ''
4610
+ ELSE NULL
4611
+ END AS has_auto_increment
4612
+ FROM
4613
+ pg_constraint con
4614
+ LEFT JOIN pg_class rel ON con.conrelid = rel.oid
4615
+ LEFT JOIN pg_class frel ON con.confrelid = frel.oid
4616
+ LEFT JOIN pg_attribute att ON att.attrelid = con.conrelid AND att.attnum = con.conkey[1]
4617
+ LEFT JOIN pg_attribute fatt ON fatt.attrelid = con.confrelid AND fatt.attnum = con.confkey[1]
4618
+ WHERE con.connamespace IN (${schemaIn})
4619
+ AND array_length(con.conkey, 1) <= 1
4620
+ AND (con.confkey IS NULL OR array_length(con.confkey, 1) = 1)
4621
+ ${table ? "AND rel.relname = ?" : ""}
4622
+ ${column ? "AND att.attname = ?" : ""}
4623
+ `, bindings)]);
4624
+ const parsedColumms = columns.rows.map((col) => {
4625
+ const constraintsForColumn = constraints.rows.filter((constraint) => constraint.table === col.table && constraint.column === col.name);
4626
+ const foreignKeyConstraint = constraintsForColumn.find((constraint) => constraint.type === "f");
4627
+ return {
4628
+ ...col,
4629
+ is_unique: constraintsForColumn.some((constraint) => ["u", "p"].includes(constraint.type)),
4630
+ is_primary_key: constraintsForColumn.some((constraint) => constraint.type === "p"),
4631
+ has_auto_increment: constraintsForColumn.some((constraint) => constraint.has_auto_increment),
4632
+ default_value: parseDefaultValue$1(col.default_value),
4633
+ foreign_key_schema: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_schema) ?? null,
4634
+ foreign_key_table: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_table) ?? null,
4635
+ foreign_key_column: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_column) ?? null
4636
+ };
4637
+ });
4638
+ if (table && column) return parsedColumms[0];
4639
+ return parsedColumms;
4640
+ }
4641
+ /**
4642
+ * Check if the given table contains the given column
4643
+ */
4644
+ async hasColumn(table, column) {
4645
+ const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
4646
+ return (await this.knex.raw(`
4647
+ SELECT
4648
+ att.attname AS column,
4649
+ rel.relname AS table
4650
+ FROM
4651
+ pg_attribute att
4652
+ LEFT JOIN pg_class rel ON att.attrelid = rel.oid
4653
+ WHERE
4654
+ rel.relnamespace IN (${schemaIn})
4655
+ AND rel.relname = ?
4656
+ AND att.attname = ?
4657
+ AND rel.relkind = 'r'
4658
+ AND att.attnum > 0
4659
+ AND NOT att.attisdropped;
4660
+ `, [table, column])).rows;
4661
+ }
4662
+ /**
4663
+ * Get the primary key column for the given table
4664
+ */
4665
+ async primary(table) {
4666
+ const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
4667
+ const result = await this.knex.raw(`
4668
+ SELECT
4669
+ att.attname AS column
4670
+ FROM
4671
+ pg_constraint con
4672
+ LEFT JOIN pg_class rel ON con.conrelid = rel.oid
4673
+ LEFT JOIN pg_attribute att ON att.attrelid = con.conrelid AND att.attnum = ANY(con.conkey)
4674
+ WHERE con.connamespace IN (${schemaIn})
4675
+ AND con.contype = 'p'
4676
+ AND rel.relname = ?
4677
+ `, [table]);
4678
+ return result.rows.length !== 0 ? result.rows.length === 1 ? result.rows[0].column : result.rows.map((r) => r.column) : null;
4679
+ }
4680
+ async foreignKeys(table) {
4681
+ const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
4682
+ const bindings = [];
4683
+ if (table) bindings.push(table);
4684
+ return (await this.knex.raw(`
4685
+ SELECT
4686
+ con.conname AS constraint_name,
4687
+ rel.relname AS table,
4688
+ att.attname AS column,
4689
+ frel.relnamespace::regnamespace::text AS foreign_key_schema,
4690
+ frel.relname AS foreign_key_table,
4691
+ fatt.attname AS foreign_key_column,
4692
+ CASE con.confupdtype
4693
+ WHEN 'r' THEN
4694
+ 'RESTRICT'
4695
+ WHEN 'c' THEN
4696
+ 'CASCADE'
4697
+ WHEN 'n' THEN
4698
+ 'SET NULL'
4699
+ WHEN 'd' THEN
4700
+ 'SET DEFAULT'
4701
+ WHEN 'a' THEN
4702
+ 'NO ACTION'
4703
+ ELSE
4704
+ NULL
4705
+ END AS on_update,
4706
+ CASE con.confdeltype
4707
+ WHEN 'r' THEN
4708
+ 'RESTRICT'
4709
+ WHEN 'c' THEN
4710
+ 'CASCADE'
4711
+ WHEN 'n' THEN
4712
+ 'SET NULL'
4713
+ WHEN 'd' THEN
4714
+ 'SET DEFAULT'
4715
+ WHEN 'a' THEN
4716
+ 'NO ACTION'
4717
+ ELSE
4718
+ NULL
4719
+ END AS on_delete
4720
+ FROM
4721
+ pg_constraint con
4722
+ LEFT JOIN pg_class rel ON con.conrelid = rel.oid
4723
+ LEFT JOIN pg_class frel ON con.confrelid = frel.oid
4724
+ LEFT JOIN pg_attribute att ON att.attrelid = con.conrelid AND att.attnum = con.conkey[1]
4725
+ LEFT JOIN pg_attribute fatt ON fatt.attrelid = con.confrelid AND fatt.attnum = con.confkey[1]
4726
+ WHERE con.connamespace IN (${schemaIn})
4727
+ AND array_length(con.conkey, 1) <= 1
4728
+ AND (con.confkey IS NULL OR array_length(con.confkey, 1) = 1)
4729
+ AND con.contype = 'f'
4730
+ ${table ? "AND rel.relname = ?" : ""}
4731
+ `, bindings)).rows;
4732
+ }
4733
+ async uniqueConstraints(table) {
4734
+ const { knex } = this;
4735
+ const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
4736
+ const bindings = [];
4737
+ if (table) bindings.push(table);
4738
+ return (await knex.raw(`
4739
+ SELECT
4740
+ con.conrelid::regclass AS table_name,
4741
+ con.conname AS constraint_name,
4742
+ array_agg(a.attname ORDER BY k.n) AS columns
4743
+ FROM
4744
+ pg_constraint AS con
4745
+ CROSS JOIN LATERAL unnest(con.conkey) WITH ORDINALITY AS k(con,n)
4746
+ LEFT JOIN pg_class rel ON con.conrelid = rel.oid
4747
+ JOIN pg_attribute AS a ON a.attnum = k.con AND a.attrelid = con.conrelid
4748
+ WHERE con.contype = 'u'
4749
+ AND con.connamespace IN (${schemaIn})
4750
+ ${table ? "AND rel.relname = ?" : ""}
4751
+ GROUP BY con.oid, con.conrelid, con.conname;
4752
+ `, bindings)).rows.map((v) => {
4753
+ const columns = Array.isArray(v.columns) ? v.columns : v.columns.substring(1, v.columns.length - 1).split(",");
4754
+ return {
4755
+ table: v.table_name,
4756
+ constraint_name: v.constraint_name,
4757
+ columns
4758
+ };
4759
+ });
4760
+ }
4761
+ };
4762
+
4763
+ //#endregion
4764
+ //#region src/inspector/utils/extract-max-length.ts
4765
+ /**
4766
+ * Extracts the length value out of a given datatype
4767
+ * For example: `varchar(32)` => 32
4768
+ */
4769
+ function extractMaxLength(type) {
4770
+ const matches = /\(([^)]+)\)/.exec(type);
4771
+ if (matches && matches.length > 0 && matches[1]) return Number(matches[1]);
4772
+ return null;
4773
+ }
4774
+
4775
+ //#endregion
4776
+ //#region src/inspector/utils/extract-type.ts
4777
+ /**
4778
+ * Extracts the type out of a given datatype
4779
+ * For example: `varchar(32)` => varchar
4780
+ */
4781
+ function extractType(type) {
4782
+ return type.replace(/[^a-zA-Z]/g, "").toLowerCase();
4783
+ }
4784
+
4785
+ //#endregion
4786
+ //#region src/inspector/dialects/sqlite.ts
4787
+ function parseDefaultValue(value) {
4788
+ if (value === null || value.trim().toLowerCase() === "null") return null;
4789
+ return stripQuotes(value);
4790
+ }
4791
+ var SQLite = class {
4792
+ knex;
4793
+ constructor(knex) {
4794
+ this.knex = knex;
4795
+ }
4796
+ /**
4797
+ * List all existing tables in the current schema/database
4798
+ */
4799
+ async tables() {
4800
+ return (await this.knex.select("name").from("sqlite_master").whereRaw("type = 'table' AND name NOT LIKE 'sqlite_%'")).map(({ name }) => name);
4801
+ }
4802
+ async tableInfo(table) {
4803
+ const query = this.knex.select("name", "sql").from("sqlite_master").where({ type: "table" }).andWhereRaw("name NOT LIKE 'sqlite_%'");
4804
+ if (table) query.andWhere({ name: table });
4805
+ let records = await query;
4806
+ records = records.map((table$1) => ({
4807
+ name: table$1.name,
4808
+ sql: table$1.sql
4809
+ }));
4810
+ if (table) return records[0];
4811
+ return records;
4812
+ }
4813
+ /**
4814
+ * Check if a table exists in the current schema/database
4815
+ */
4816
+ async hasTable(table) {
4817
+ return (await this.knex.select(1).from("sqlite_master").where({
4818
+ type: "table",
4819
+ name: table
4820
+ })).length > 0;
4821
+ }
4822
+ /**
4823
+ * Get all the available columns in the current schema/database. Can be filtered to a specific table
4824
+ */
4825
+ async columns(table) {
4826
+ if (table) return (await this.knex.raw("PRAGMA table_xinfo(??)", table)).map((column) => ({
4827
+ table,
4828
+ column: column.name
4829
+ }));
4830
+ const tables = await this.tables();
4831
+ const columnsPerTable = await Promise.all(tables.map(async (table$1) => await this.columns(table$1)));
4832
+ return flatten(columnsPerTable);
4833
+ }
4834
+ async columnInfo(table, column) {
4835
+ const getColumnsForTable = async (table$1) => {
4836
+ const tablesWithAutoIncrementPrimaryKeys = (await this.knex.select("name").from("sqlite_master").whereRaw("sql LIKE '%AUTOINCREMENT%'")).map(({ name }) => name);
4837
+ const columns = await this.knex.raw("PRAGMA table_xinfo(??)", table$1);
4838
+ const foreignKeys = await this.knex.raw("PRAGMA foreign_key_list(??)", table$1);
4839
+ const indexList = await this.knex.raw("PRAGMA index_list(??)", table$1);
4840
+ const indexInfoList = await Promise.all(indexList.map((index) => this.knex.raw("PRAGMA index_info(??)", index.name)));
4841
+ return columns.map((raw) => {
4842
+ const foreignKey = foreignKeys.find((fk) => fk.from === raw.name);
4843
+ const indexIndex = indexInfoList.findIndex((list) => list.find((fk) => fk.name === raw.name));
4844
+ const index = indexList[indexIndex];
4845
+ const indexInfo = indexInfoList[indexIndex];
4846
+ return {
4847
+ name: raw.name,
4848
+ table: table$1,
4849
+ data_type: extractType(raw.type),
4850
+ default_value: parseDefaultValue(raw.dflt_value),
4851
+ max_length: extractMaxLength(raw.type),
4852
+ numeric_precision: null,
4853
+ numeric_scale: null,
4854
+ is_generated: raw.hidden !== 0,
4855
+ generation_expression: null,
4856
+ is_nullable: raw.notnull === 0,
4857
+ is_unique: !!(index === null || index === void 0 ? void 0 : index.unique) && (indexInfo === null || indexInfo === void 0 ? void 0 : indexInfo.length) === 1,
4858
+ is_primary_key: raw.pk === 1,
4859
+ has_auto_increment: raw.pk === 1 && tablesWithAutoIncrementPrimaryKeys.includes(table$1),
4860
+ foreign_key_column: (foreignKey === null || foreignKey === void 0 ? void 0 : foreignKey.to) || null,
4861
+ foreign_key_table: (foreignKey === null || foreignKey === void 0 ? void 0 : foreignKey.table) || null
4862
+ };
4863
+ });
4864
+ };
4865
+ if (!table) {
4866
+ const tables = await this.tables();
4867
+ const columnsPerTable = await Promise.all(tables.map(async (table$1) => await getColumnsForTable(table$1)));
4868
+ return flatten(columnsPerTable);
4869
+ }
4870
+ if (table && !column) return await getColumnsForTable(table);
4871
+ return (await getColumnsForTable(table)).find((columnInfo) => columnInfo.name === column);
4872
+ }
4873
+ /**
4874
+ * Check if a table exists in the current schema/database
4875
+ */
4876
+ async hasColumn(table, column) {
4877
+ let isColumn = false;
4878
+ if ((await this.knex.raw(`SELECT COUNT(*) AS ct FROM pragma_table_xinfo('${table}') WHERE name='${column}'`))[0]["ct"] !== 0) isColumn = true;
4879
+ return isColumn;
4880
+ }
4881
+ /**
4882
+ * Get the primary key column for the given table
4883
+ */
4884
+ async primary(table) {
4885
+ const pkColumns = (await this.knex.raw("PRAGMA table_xinfo(??)", table)).filter((col) => col.pk !== 0);
4886
+ return pkColumns.length > 0 ? pkColumns.length === 1 ? pkColumns[0].name : pkColumns.map((col) => col.name) : null;
4887
+ }
4888
+ async foreignKeys(table) {
4889
+ if (table) return (await this.knex.raw("PRAGMA foreign_key_list(??)", table)).map((key) => ({
4890
+ table,
4891
+ column: key.from,
4892
+ foreign_key_table: key.table,
4893
+ foreign_key_column: key.to,
4894
+ on_update: key.on_update,
4895
+ on_delete: key.on_delete,
4896
+ constraint_name: null
4897
+ }));
4898
+ const tables = await this.tables();
4899
+ const keysPerTable = await Promise.all(tables.map(async (table$1) => await this.foreignKeys(table$1)));
4900
+ return flatten(keysPerTable);
4901
+ }
4902
+ async uniqueConstraints(table) {
4903
+ if (table) {
4904
+ const indexList = await this.knex.raw("PRAGMA index_list(??)", table);
4905
+ const indexInfoList = await Promise.all(indexList.map((index) => this.knex.raw("PRAGMA index_info(??)", index.name)));
4906
+ return indexList.filter((i) => i.unique).map((index, i) => {
4907
+ const info = indexInfoList[i];
4908
+ return {
4909
+ table,
4910
+ constraint_name: index.name,
4911
+ columns: info.map((c) => c.name)
4912
+ };
4913
+ });
4914
+ }
4915
+ const tables = await this.tables();
4916
+ const constraintsPerTable = await Promise.all(tables.map(async (table$1) => await this.uniqueConstraints(table$1)));
4917
+ return flatten(constraintsPerTable);
4918
+ }
4919
+ };
4920
+
4921
+ //#endregion
4922
+ //#region src/inspector/index.ts
4923
+ var SchemaInspector = class {
4924
+ static inspect(knex) {
4925
+ let constructor;
4926
+ switch (knex.client.constructor.name) {
4927
+ case "Client_MySQL":
4928
+ case "Client_MySQL2":
4929
+ constructor = MySQL;
4930
+ break;
4931
+ case "Client_PG":
4932
+ constructor = Postgres;
4933
+ break;
4934
+ case "Client_CockroachDB":
4935
+ constructor = CockroachDB;
4936
+ break;
4937
+ case "Client_SQLite3":
4938
+ case "Client_BetterSQLite3":
4939
+ constructor = SQLite;
4940
+ break;
4941
+ case "Client_Oracledb":
4942
+ case "Client_Oracle":
4943
+ constructor = oracleDB;
4944
+ break;
4945
+ case "Client_MSSQL":
4946
+ constructor = MSSQL;
4947
+ break;
4948
+ default: throw Error("Unsupported driver used: " + knex.client.constructor.name);
4949
+ }
4950
+ return new constructor(knex);
4951
+ }
4952
+ };
4953
+
3536
4954
  //#endregion
3537
4955
  //#region src/migrations/migrator.ts
3538
4956
  async function glob(folderPath) {
@@ -3574,14 +4992,14 @@ var Migrator = class {
3574
4992
  return Object.values(files).filter((file) => !ran.includes(this.getMigrationName(file)));
3575
4993
  }
3576
4994
  async runPending(migrations, options = {}) {
3577
- if (migrations.length === 0) {
3578
- this.write("Nothing to migrate");
4995
+ if (migrations.length === 0 && !options.quiet) {
4996
+ Logger.info("INFO: Nothing to migrate.");
3579
4997
  return;
3580
4998
  }
3581
4999
  let batch = await this.repository.getNextBatchNumber();
3582
5000
  const pretend = options.pretend || false;
3583
5001
  const step = options.step || false;
3584
- this.write("Running migrations.");
5002
+ Logger.info("INFO: Running migrations...");
3585
5003
  for (const file of migrations) {
3586
5004
  await this.runUp(file, batch, pretend);
3587
5005
  if (step) batch++;
@@ -3590,19 +5008,19 @@ var Migrator = class {
3590
5008
  async runUp(file, batch, _pretend) {
3591
5009
  const migration = await this.resolvePath(file);
3592
5010
  const name = this.getMigrationName(file);
3593
- await this.writeTask(name, () => this.runMigration(migration, "up"));
5011
+ await TaskManager.taskRunner(name, () => this.runMigration(migration, "up"));
3594
5012
  await this.repository.log(name, batch);
3595
5013
  }
3596
5014
  async runDown(file, migration, _pretend) {
3597
5015
  const instance = await this.resolvePath(file);
3598
5016
  const name = this.getMigrationName(file);
3599
- await this.writeTask(name, () => this.runMigration(instance, "down"));
5017
+ await TaskManager.taskRunner(name, () => this.runMigration(instance, "down"));
3600
5018
  await this.repository.delete(migration);
3601
5019
  }
3602
5020
  async rollback(paths = [], options = {}) {
3603
5021
  const migrations = await this.getMigrationsForRollback(options);
3604
5022
  if (migrations.length === 0) {
3605
- this.write("Nothing to rollback.");
5023
+ Logger.info("INFO: Nothing to rollback");
3606
5024
  return [];
3607
5025
  }
3608
5026
  return await this.rollbackMigrations(migrations, paths, options);
@@ -3615,7 +5033,7 @@ var Migrator = class {
3615
5033
  async rollbackMigrations(migrations, paths, options) {
3616
5034
  const rolledBack = [];
3617
5035
  const files = await this.getMigrationFiles(paths);
3618
- this.write("Rolling back migrations.");
5036
+ Logger.info("INFO: Rolling back migrations...");
3619
5037
  for (const migration of migrations) {
3620
5038
  const file = files[migration.migration];
3621
5039
  if (!file) {
@@ -3627,11 +5045,35 @@ var Migrator = class {
3627
5045
  }
3628
5046
  return rolledBack;
3629
5047
  }
3630
- reset(_paths = [], _pretend = false) {
3631
- this.repository.getRan().then((r) => r.reverse());
3632
- return [];
5048
+ async reset(paths = [], options, pretend = false) {
5049
+ const migrations = await this.repository.getRan().then((r) => r.map((e) => ({ migration: e })).reverse());
5050
+ if (migrations.length === 0) {
5051
+ if (!options.quiet) Logger.info("INFO: Nothing to reset.");
5052
+ return [];
5053
+ }
5054
+ return this.resetMigrations(migrations, paths, pretend);
3633
5055
  }
3634
- resetMigrations(migrations, paths, pretend = false) {
5056
+ /**
5057
+ * Drop all tables and re-run all migrations
5058
+ *
5059
+ * @param paths
5060
+ * @param options
5061
+ */
5062
+ async fresh(paths, options) {
5063
+ /** Initialise connections */
5064
+ const connection = this.repository.getConnection().connector;
5065
+ const inspector = SchemaInspector.inspect(connection);
5066
+ await connection.raw("SET foreign_key_checks = 0");
5067
+ /** Drop all existing tables */
5068
+ for (const table of await inspector.tables()) await TaskManager.taskRunner(`Dropping ${Logger.parse([[table, "grey"]], "", false)} table`, () => connection.schema.dropTableIfExists(table));
5069
+ await connection.raw("SET foreign_key_checks = 1");
5070
+ /** Create the migration repository */
5071
+ await this.repository.createRepository();
5072
+ console.log();
5073
+ /** Run fresh migrations */
5074
+ await this.run(paths, options);
5075
+ }
5076
+ async resetMigrations(migrations, paths, pretend = false) {
3635
5077
  return this.rollbackMigrations(migrations, paths, { pretend });
3636
5078
  }
3637
5079
  async runMigration(migration, method) {
@@ -3682,7 +5124,7 @@ var Migrator = class {
3682
5124
  return this.connection;
3683
5125
  }
3684
5126
  resolveConnection(connection) {
3685
- return this.resolver.connection(connection || this.connection);
5127
+ return this.resolver.fire(connection || this.connection);
3686
5128
  }
3687
5129
  getRepository() {
3688
5130
  return this.repository;
@@ -3704,17 +5146,6 @@ var Migrator = class {
3704
5146
  write(...args) {
3705
5147
  if (this.output) console.log(...args);
3706
5148
  }
3707
- async writeTask(description, task) {
3708
- const startTime = process.hrtime();
3709
- let result = false;
3710
- try {
3711
- result = await (task || (() => true))();
3712
- } finally {
3713
- const endTime = process.hrtime(startTime);
3714
- const duration = (endTime[0] * 1e9 + endTime[1]) / 1e6;
3715
- Logger.twoColumnLog(Logger.parse([[description, "green"]], "", false), [Logger.parse([[`${Math.floor(duration)}ms`, "gray"]], "", false), Logger.parse([[result !== false ? "✔" : "✘", result !== false ? "green" : "red"]], "", false)].join(" "));
3716
- }
3717
- }
3718
5149
  };
3719
5150
  var migrator_default = Migrator;
3720
5151
 
@@ -3815,6 +5246,49 @@ var Migrate = class {
3815
5246
  if (destroyAll) await arquebus$1.destroyAll();
3816
5247
  }
3817
5248
  /**
5249
+ * Rollback all database migrations
5250
+ *
5251
+ * @param config
5252
+ * @param options
5253
+ * @param destroyAll
5254
+ */
5255
+ async reset(config, options = {}, destroyAll = false) {
5256
+ const { arquebus: arquebus$1, migrator } = await this.setupConnection(config);
5257
+ const paths = await Utils.getMigrationPaths(this.basePath ?? process.cwd(), migrator, config.migrations.path, options.path);
5258
+ await migrator.setOutput(true).reset(paths, {
5259
+ step: options.step || 0,
5260
+ pretend: options.pretend,
5261
+ batch: options.batch || 0,
5262
+ quiet: options.quiet || false
5263
+ });
5264
+ if (destroyAll) await arquebus$1.destroyAll();
5265
+ }
5266
+ /**
5267
+ * Reset and re-run all migrations
5268
+ *
5269
+ * @param config
5270
+ * @param options
5271
+ * @param destroyAll
5272
+ */
5273
+ async refresh(config, options = {}, destroyAll = false) {
5274
+ await this.reset(config, Object.assign({}, options, { quiet: true }), false);
5275
+ console.log("");
5276
+ await this.run(config, options, destroyAll);
5277
+ }
5278
+ /**
5279
+ * Drop all tables and re-run all migrations
5280
+ *
5281
+ * @param config
5282
+ * @param options
5283
+ * @param destroyAll
5284
+ */
5285
+ async fresh(config, options = {}, destroyAll = false) {
5286
+ const { arquebus: arquebus$1, migrator } = await this.setupConnection(config);
5287
+ const paths = await Utils.getMigrationPaths(this.basePath ?? process.cwd(), migrator, config.migrations.path, options.path);
5288
+ await migrator.setOutput(true).fresh(paths, { pretend: options.pretend });
5289
+ if (destroyAll) await arquebus$1.destroyAll();
5290
+ }
5291
+ /**
3818
5292
  * Prepares the database for migration
3819
5293
  *
3820
5294
  * @param migrator
@@ -4072,4 +5546,4 @@ const makeCollection = (model, data) => new collection_default(data.map((item) =
4072
5546
  const makePaginator = (model, data) => new paginator_default(data.data.map((item) => model.make(item)), data.total, data.per_page, data.current_page);
4073
5547
 
4074
5548
  //#endregion
4075
- export { attribute_default as Attribute, builder_default as Builder, casts_attributes_default as CastsAttributes, collection_default as Collection, has_unique_ids_default as HasUniqueIds, InvalidArgumentError, Migrate, migration_default as Migration, model_default as Model, ModelNotFoundError, paginator_default as Paginator, pivot_default as Pivot, query_builder_default as QueryBuilder, RelationNotFoundError, scope_default as Scope, soft_deletes_default as SoftDeletes, arquebus_default as arquebus, compose, defineConfig, flattenDeep, getAttrMethod, getAttrName, getGetterMethod, getRelationMethod, getRelationName, getScopeMethod, getScopeName, getSetterMethod, kebabCase, make, makeCollection, makePaginator, now, snakeCase, tap };
5549
+ export { attribute_default as Attribute, builder_default as Builder, casts_attributes_default as CastsAttributes, collection_default as Collection, has_unique_ids_default as HasUniqueIds, InvalidArgumentError, Migrate, migration_default as Migration, model_default as Model, ModelNotFoundError, paginator_default as Paginator, pivot_default as Pivot, query_builder_default as QueryBuilder, RelationNotFoundError, scope_default as Scope, soft_deletes_default as SoftDeletes, arquebus_default as arquebus, compose, defineConfig, flatten, flattenDeep, getAttrMethod, getAttrName, getGetterMethod, getRelationMethod, getRelationName, getScopeMethod, getScopeName, getSetterMethod, kebabCase, make, makeCollection, makePaginator, now, snakeCase, tap };