@h3ravel/arquebus 0.3.5 → 0.4.0

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