Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
85da5b8
docs/add docs for creating unions
NickRMD Sep 30, 2025
4332722
refact/moved queryKind files to queryKind/dml since they were all dml…
NickRMD Sep 30, 2025
8901862
refact/renamed QueryDefinition to DmlQueryDefinition
NickRMD Sep 30, 2025
7ac671c
refact/change query.ts to dmlQueryDefinition.ts
NickRMD Sep 30, 2025
fc1d68b
fix/change query.js to dmlQueryDefinition.js
NickRMD Sep 30, 2025
632adad
ongoing/feat/started adding ddl queries
NickRMD Sep 30, 2025
5a1e034
feat/added exports for lots of things like dml queries for example
NickRMD Sep 30, 2025
938bfc3
feat/added other entries for exporting and also added all index.ts to…
NickRMD Sep 30, 2025
e5fbfe0
Started adding more query kinds/types as from the issue #65
NickRMD Sep 30, 2025
9189b9c
fix/added default export to CteMaker
NickRMD Sep 30, 2025
53bd070
Merge branch 'dev' of https://github.com/NickRMD/queryMaker into feat…
NickRMD Sep 30, 2025
b04c5c7
feat/added error handling from when select queries in unions have dif…
NickRMD Sep 30, 2025
06c1f70
fix/updated package-lock.json after version bump
NickRMD Oct 1, 2025
d6f7809
Merge branch 'dev' of https://github.com/NickRMD/queryMaker into feat…
NickRMD Oct 1, 2025
6300f46
Merge branch 'dev' of https://github.com/NickRMD/queryMaker into feat…
NickRMD Oct 1, 2025
4b98931
Merge branch 'next' of https://github.com/NickRMD/queryMaker into fea…
NickRMD Oct 1, 2025
cac5da9
fix/fix git url
NickRMD Oct 2, 2025
5dd7fe4
feat/added columnTypes, columnType class and columns class with a lot…
NickRMD Oct 2, 2025
bfb0fa1
feat/fix/changed how DdlQueryDefinition works to adapt to how other c…
NickRMD Oct 2, 2025
9f1454e
feat/introduced tables as the first ddl queries to exist in this pack…
NickRMD Oct 2, 2025
029414d
feat/added tables to the queryMaker
NickRMD Oct 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
],
"repository": {
"type": "git",
"url": "https://github.com/NickRMD/queryMaker.git"
"url": "git+https://github.com/NickRMD/queryMaker.git"
},
"homepage": "https://github.com/NickRMD/queryMaker#readme",
"bugs": {
Expand Down
4 changes: 2 additions & 2 deletions src/cteMaker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import QueryDefinition from "./queryKinds/query.js";
import SelectQuery from "./queryKinds/select.js";
import QueryDefinition from "./queryKinds/dml/dmlQueryDefinition.js";
import SelectQuery from "./queryKinds/dml/select.js";

/**
* Cte represents a Common Table Expression (CTE) in SQL.
Expand Down
6 changes: 3 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Query from "./queryMaker.js";
import Statement from "./statementMaker.js";
import CteMaker from "./cteMaker.js";
export * from './cteMaker.js'
export { default as CteMaker } from './cteMaker.js'

export {
Query,
Statement,
CteMaker
Statement
}
244 changes: 244 additions & 0 deletions src/queryKinds/ddl/ddlQueryDefinition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
import SqlEscaper from "../../sqlEscaper.js";
import QueryKind from "../../types/QueryKind";
import sqlFlavor from "../../types/sqlFlavor.js";

/**
* An array of function names that can be used to execute SQL queries.
* These functions are commonly found in database client libraries.
*/
const functionNames = ['execute', 'query', 'run', 'all', 'get'] as const;

/**
* FunctionDeclaration type defines the signature for functions that execute SQL queries.
* It takes a query string and an array of parameters, and returns a promise that resolves
* with any result.
*/
type FunctionDeclaration = (query: string, params?: any[]) => Promise<any>;

/**
* QueryExecutorObject interface defines the structure for an object that can execute SQL queries.
* It includes optional methods for executing queries in different ways, as well as an optional manager property.
*/
interface QueryExecutorObject {
execute?: FunctionDeclaration;
query?: FunctionDeclaration;
run?: FunctionDeclaration;
all?: FunctionDeclaration;
get?: FunctionDeclaration;
manager?: QueryExecutor;
}

/**
* QueryExecutor type can be either a QueryExecutorObject or a function that executes a query.
*/
type QueryExecutor =
QueryExecutorObject
| FunctionDeclaration;

/**
* Abstract class DdlQueryDefinition serves as a blueprint for defining DDL (Data Definition Language) query structures.
* It is intended to be extended by specific DDL query classes such as CreateTableQuery, AlterTableQuery, and DropTableQuery.
* This class will provide common properties and methods that are shared among all DDL query types and also some abstract methods
* that must be implemented by the subclasses to ensure they adhere to a consistent interface for building DDL queries.
*/
export default abstract class DdlQueryDefinition {
/** The name of the table involved in the DDL operation. */
protected tableName: string = '';

/** The built DDL query string, initialized to null. */
protected builtQuery: string | string[] | null = null;

/**
* Sets the name of the table for the DDL operation.
* @param name - The name of the table.
* @returns The current instance for method chaining.
*/
public table(name: string | null = null): this {
this.tableName = name ? SqlEscaper.escapeTableName(name, this.flavor) : '';
return this;
}

/**
* Checks if the DDL query has been built.
* @returns True if the query has been built, false otherwise.
*/
public isDone(): boolean {
return this.builtQuery !== null;
}

/**
* Abstract method to build the DDL query string.
* This method must be implemented by subclasses to generate the appropriate SQL statement.
* @param deepAnalysis - Optional boolean to indicate if deep analysis is required (default is false).
* @returns The constructed DDL query string.
*/
public abstract build(deepAnalysis?: boolean): string | string[];

/**
* Builds an EXPLAIN query for the DDL operation.
* This method prefixes the built DDL query with "EXPLAIN".
* @param deepAnalysis - Optional boolean to indicate if deep analysis is required (default is false).
* @returns The constructed EXPLAIN query string.
*/
public buildExplain(deepAnalysis?: boolean): string {
return `EXPLAIN ${this.build(deepAnalysis)}`;
}

/**
* Builds an EXPLAIN ANALYZE query for the DDL operation.
* This method prefixes the built DDL query with "EXPLAIN ANALYZE".
* @param deepAnalysis - Optional boolean to indicate if deep analysis is required (default is false).
* @returns The constructed EXPLAIN ANALYZE query string.
*/
public buildExplainAnalyze(deepAnalysis?: boolean): string {
return `EXPLAIN ANALYZE ${this.build(deepAnalysis)}`;
}

/**
* Utility method to add indentation to each line of a given string.
* This is useful for formatting multi-line SQL queries for better readability.
* @param str - The input string to be indented.
* @param spaces - The number of spaces to indent each line (default is 0).
* @returns The indented string.
*/
protected spaceLines(str: string, spaces: number = 0): string {
const space = ' '.repeat(spaces);
return str.split('\n').map(line => space + line).join('\n');
}

/**
* Abstract method to clone the current DDL query definition instance.
* This method must be implemented by subclasses to return a new instance
* that is a copy of the current instance.
* @returns A new instance of the DDL query definition.
*/
public abstract clone(): DdlQueryDefinition;

/**
* Abstract method to reset the state of the DDL query definition.
* This method must be implemented by subclasses to clear any set properties
* and return the instance to its initial state.
* @returns The current instance for method chaining.
*/
public abstract reset(): this;

/**
* Abstract method to convert the DDL query definition to its SQL string representation.
* This method must be implemented by subclasses to return the SQL string
* that represents the DDL operation defined by the instance.
* @returns The SQL string representation of the DDL query.
*/
public abstract toSQL(): string | string[];

/**
* Abstract getter to retrieve the kind of DDL query.
* This property must be implemented by subclasses to return the specific
* type of DDL operation (e.g., 'CREATE', 'ALTER', 'DROP').
*/
public abstract get kind(): QueryKind;

/**
* The SQL flavor to use for escaping identifiers.
* Default is PostgreSQL.
*/
protected flavor: sqlFlavor = sqlFlavor.postgres;

/**
* Schemas to be used in the query.
* This is useful for databases that support multiple schemas.
* NOTICE: SQL Injection is not checked in schema names. Be sure to use only trusted schema names.
*/
protected schemas: string[] = [];

/**
* Sets the SQL flavor for escaping identifiers.
* @param flavor The SQL flavor to set.
* @returns The current DmlQueryDefinition instance for chaining.
*/
public sqlFlavor(flavor: sqlFlavor) {
this.flavor = flavor;
return this;
}

/**
* Set schemas to be used in the query.
* This is useful for databases that support multiple schemas.
* NOTICE: SQL Injection is not checked in schema names. Be sure to use only trusted schema names.
* @param schemas The schemas to set.
* @returns The current SelectQuery instance for chaining.
*/
public schema(...schemas: string[]): this {
this.schemas = schemas;
return this;
}

/**
* Adds schemas to the existing list of schemas.
* This is useful for databases that support multiple schemas.
* NOTICE: SQL Injection is not checked in schema names. Be sure to use only trusted schema names.
* @param schemas The schemas to add.
* @returns The current SelectQuery instance for chaining.
*/
public addSchema(...schemas: string[]): this {
this.schemas.push(...schemas);
return this;
}

/**
* Executes the built SQL query using the provided query executor.
* The query executor can be a function or an object with methods to execute the query.
* The optional noManager parameter can be used to bypass the manager property if present.
* @param queryExecutor The executor to run the SQL query.
* @param noManager If true, bypasses the manager property of the executor object.
* @returns A promise that resolves when the query execution is complete.
* @throws An error if the provided query executor is invalid.
*/
public async execute(
queryExecutor: QueryExecutor,
noManager: boolean = false
): Promise<void> {
if (typeof queryExecutor === 'function') {
const builtQuery = this.build();
if (Array.isArray(builtQuery)) {
for (const query of builtQuery) {
await queryExecutor(query);
}
} else {
await queryExecutor(builtQuery);
}
return;
}

if (!noManager && 'manager' in queryExecutor && typeof queryExecutor?.manager === 'object') {
for (const functionName of functionNames) {
if (typeof queryExecutor.manager[functionName] === 'function') {
const builtQuery = this.build();
if (Array.isArray(builtQuery)) {
for (const query of builtQuery) {
await queryExecutor.manager[functionName]!(query);
}
} else {
await queryExecutor.manager[functionName]!(builtQuery);
}
return;
}
}
} else if(typeof queryExecutor === 'object') {
for (const functionName of functionNames) {
if (typeof queryExecutor[functionName] === 'function') {
const builtQuery = this.build();
if (Array.isArray(builtQuery)) {
for (const query of builtQuery) {
await queryExecutor[functionName]!(query);
}
} else {
await queryExecutor[functionName]!(builtQuery);
}
return;
}
}
}

throw new Error('Invalid query executor provided.');
}
}
Loading