Nxdom Framework

Nusantara eXtreme Development Object Model — dokumentasi resmi

NX.Storage().model() — NexaModels

Query builder SQL JavaScript di NX. Mulai dari NX.Storage().model("nama_tabel"), lalu rantai select, where, get(), dan seterusnya. Ringkasan alur Storage: NX.Storage(). Lanjutan: IndexedDBNexaForge.

Overview

NexaModels adalah query builder SQL yang terintegrasi dalam framework NX. Anda menyusun query database dengan method chaining, tanpa menyusun string SQL mentah secara manual, dengan pola yang mudah dibaca.

Fitur utama

  • Method chaining — sintaks mudah dibaca.
  • SQL injection protection — prepared statements.
  • Security features — filter field sensitif otomatis.
  • Promise support — async/await dan .then()/.catch().
  • Type safety — validasi input dan parameter.
  • Flexible query building — operasi SQL standar.
  • NX integration — lewat NX.Storage().model().

Installation & setup

1. Lewat NX.Storage().model() (cara di app)

Query builder tabel SQL dimulai dari NX.Storage().model(namaTabel). Rantai .select() / .where() / .get() sama seperti pada NexaModels; untuk data dari server gunakan misalnya const rows = await NX.Storage()….

Penting — jangan tertukar:

Pemanggilan Fungsi
NX.Storage().model("news") Tabel SQL news — query builder (NexaModels).
NX.Storage().models("News", { method, params }) Class model PHP News — bukan builder tabel.
const rows = await NX.Storage() .model("news") .select("*") .get();

Setelah .model("…") Anda memakai seluruh method NexaModels (where, join, orderBy, toSql, dll.). Contoh dengan variabel query di bawah mengasumsikan const query = NX.Storage().model("users"); (ganti nama tabel sesuai kebutuhan).

Basic usage

1. Simple SELECT query

const sqlQuery = NX.Storage() .model("users") .select(["id", "name", "email"]) .where("status", "=", "active") .toSql(); console.log(sqlQuery); // Output: SELECT id, name, email FROM users WHERE status = ?

2. Complex query dengan JOIN

const sqlQuery = NX.Storage() .model("users") .select(["users.name", "profiles.bio", "departments.name as dept_name"]) .join("profiles", "users.id", "=", "profiles.user_id") .leftJoin("departments", "users.department_id", "=", "departments.id") .where("users.status", "=", "active") .orderBy("users.name", "ASC") .toSql();

3. Query dengan kondisi lanjutan

const sqlQuery = NX.Storage() .model("users") .select(["*"]) .whereIn("id", [1, 2, 3, 4, 5]) .whereBetween("created_at", ["2024-01-01", "2024-12-31"]) .whereNotNull("email") .groupBy("department_id") .having("COUNT(*)", ">", 5) .toSql();

Query building methods

Table selection

// Basic: tabel dari Storage (disarankan) const query = NX.Storage().model("users"); // Alias untuk table query.from("users as u"); // Tabel lain — builder baru const products = NX.Storage().model("products"); // Eksekusi async const rows = await NX.Storage().model("news").select("*").get();

Column selection

query.select(["id", "name", "email"]); query.select("*"); query.select(["id", "name as full_name", "email"]); query.except(["password", "secret_key"]); query.noSensitive(); query.noTimestamps();

WHERE clauses

query.where("status", "=", "active"); query.where("age", ">", 18); query.where("name", "LIKE", "%john%"); query.orWhere("role", "=", "admin"); query.whereIn("id", [1, 2, 3, 4, 5]); query.whereNotIn("status", ["banned", "suspended"]); query.whereBetween("created_at", ["2024-01-01", "2024-12-31"]); query.whereNotBetween("age", [18, 65]); query.whereNull("deleted_at"); query.whereNotNull("email"); query.whereLike("name", "%john%"); query.orWhereLike("email", "%gmail%"); query.whereDate("created_at", "=", "2024-01-01"); query.whereYear("created_at", "=", 2024); query.whereMonth("created_at", "=", 12); query.whereDay("created_at", "=", 25);

JOIN operations

query.join("profiles", "users.id", "=", "profiles.user_id"); query.leftJoin("departments", "users.department_id", "=", "departments.id"); query.rightJoin("orders", "users.id", "=", "orders.user_id"); query.innerJoin("profiles", "users.id", "=", "profiles.user_id");

ORDER BY & GROUP BY

query.orderBy("name", "ASC"); query.orderBy("created_at", "DESC"); query.latest("created_at"); query.oldest("updated_at"); query.inRandomOrder(); query.groupBy("department_id"); query.groupBy(["department_id", "status"]); query.having("COUNT(*)", ">", 5); query.having("SUM(amount)", ">", 1000);

LIMIT & OFFSET

query.limit(10); query.offset(20); query.take(10); query.skip(20); query.paginateQuery(1, 10);

UNION operations

query.union(otherQuery); query.unionAll(otherQuery);

Security features

1. Sensitive data filtering

query.noSensitive(); query.except(["password", "secret_key", "api_token"]); query.noTimestamps(); query.noSystem(); query.noId();

2. Input validation

query.validateTableName("users"); query.validateTableName("users; DROP TABLE users;"); query.validateColumnName("name"); query.validateColumnName("name; DROP TABLE users;");

3. SQL injection protection

const query = NX.Storage() .model("users") .where("name", "=", userInput); const { sql, bindings } = query.toSqlWithBindings();

Aggregate functions

Count

query.countSql("id"); query.countSql("*"); query.countByConditions("id", [ { column: "status", operator: "=", value: "active" }, { column: "age", operator: ">", value: 18 }, ]); query.countWithPercentage("id", [ { column: "status", operator: "=", value: "active" }, ]); query.countByGroup("department_id", "id");

Sum, average, min, max

query.sumSql("amount"); query.sumColumns(["price", "tax", "shipping"]); query.avgSql("rating"); query.avgColumns(["score1", "score2", "score3"]); query.minSql("created_at"); query.maxSql("updated_at");

Custom aggregate

query.aggregateSql("COUNT", "id"); query.aggregateSql("AVG", "rating");

API integration

1. HTTP methods

const query = NX.Storage() .model("users") .where("status", "=", "active"); const rows = await query.get("Fetch"); const newUser = await query.insert( { name: "John Doe", email: "john@example.com" }, "Create" ); const updated = await query.update({ name: "Jane Doe" }, "Update"); const deleted = await query.delete("Delete");

2. Promise support

query .get("Fetch") .then((rows) => console.log("Data:", rows)) .catch((error) => console.error("Error:", error)); try { const rows = await query.get("Fetch"); console.log("Data:", rows); } catch (error) { console.error("Error:", error); }

3. Pagination

const rows = await query.paginate(1, 10, "Fetch"); const paginationInfo = query.paginateInfo(1, 10);

Advanced features

1. Query cloning

const baseQuery = NX.Storage() .model("users") .where("status", "=", "active"); const clonedQuery = baseQuery.clone(); const activeUsers = await clonedQuery.get("Fetch"); const adminUsers = clonedQuery.where("role", "=", "admin").get("Fetch");

2. Query debugging

query.dump(); query.dd(); const queryInfo = query.inspect(); console.log(queryInfo);

3. Raw SQL

query.rawSql("SELECT * FROM users WHERE age > ?", [18]); query.rawSql("SELECT COUNT(*) FROM users");

4. Transaction support

const transactionQueries = [ { sql: "INSERT INTO users (name) VALUES (?)", bindings: ["John"] }, { sql: "INSERT INTO profiles (user_id, bio) VALUES (?, ?)", bindings: [1, "Bio"], }, ]; query.transactionSql(transactionQueries);

Practical examples

1. User management

async function getActiveUsers(page = 1, perPage = 10) { const query = NX.Storage() .model("users") .select(["id", "name", "email", "created_at"]) .where("status", "=", "active") .orderBy("created_at", "DESC"); try { return await query.paginate(page, perPage, "Fetch"); } catch (error) { console.error("Error loading users:", error); return null; } } async function searchUsers(searchTerm, filters = {}) { const query = NX.Storage() .model("users") .select(["id", "name", "email"]); if (searchTerm) { query .whereLike("name", `%${searchTerm}%`) .orWhereLike("email", `%${searchTerm}%`); } if (filters.department) query.where("department_id", "=", filters.department); if (filters.status) query.where("status", "=", filters.status); return await query.get("Fetch"); } async function createUser(userData) { return await NX.Storage().model("users").insert(userData, "Create"); }

2. Dashboard statistics

async function getDashboardStats() { try { const [totalUsers, totalRevenue, totalProducts] = await Promise.all([ NX.Storage().model("users").count("id", "Fetch"), NX.Storage().model("orders").sum("total", "Fetch"), NX.Storage().model("products").count("id", "Fetch"), ]); return { totalUsers, totalRevenue, totalProducts }; } catch (error) { console.error("Error loading dashboard stats:", error); return null; } }

3. E-commerce products

async function getProductsWithCategories(filters = {}) { const query = NX.Storage() .model("products") .select(["products.*", "categories.name as category_name"]) .join("categories", "products.category_id", "=", "categories.id") .where("products.status", "=", "active"); if (filters.category) query.where("categories.id", "=", filters.category); if (filters.priceMin) query.where("products.price", ">=", filters.priceMin); if (filters.priceMax) query.where("products.price", "<=", filters.priceMax); if (filters.search) query.whereLike("products.name", `%${filters.search}%`); query.orderBy("products.name", "ASC"); return await query.get("Fetch"); } async function getProductStats() { const [totalProducts, avgPrice, maxPrice, minPrice] = await Promise.all([ NX.Storage().model("products").count("id", "Fetch"), NX.Storage().model("products").avg("price", "Fetch"), NX.Storage().model("products").max("price", "Fetch"), NX.Storage().model("products").min("price", "Fetch"), ]); return { totalProducts, avgPrice, maxPrice, minPrice }; }

Integrasi NX components

1. NexaTabel

async function loadTableData() { const query = NX.Storage() .model("users") .select(["id", "name", "email", "status"]) .where("active", "=", 1) .orderBy("name", "ASC"); const rows = await query.get("Fetch"); const table = new NX().NexaTabel(); table.render("#users-table", rows); return rows; }

2. NexaModal

async function loadUserForm(userId) { const row = await NX.Storage() .model("users") .select(["*"]) .where("id", "=", userId) .first("Fetch"); if (row) NX().nexaModal.open("user-form", row); }

3. NexaFilter

function setupDataFilter() { const query = NX.Storage() .model("users") .select(["id", "name", "email", "department_id"]); const filter = new NX().NexaFilter(); filter.setup("#filter-container", { data: query, filters: [ { field: "name", type: "text", placeholder: "Search by name" }, { field: "department_id", type: "select", options: departmentOptions }, { field: "status", type: "select", options: statusOptions }, ], onFilter: (filteredData) => updateTable(filteredData), }); }

Best practices

Query optimization & error handling

// Pilih kolom yang perlu saja query.select(["id", "name", "email"]); // Error handling try { return await query.get("Fetch"); } catch (error) { console.error("Query failed:", error); return null; } // Pagination untuk data besar query.paginate(1, 10, "Fetch");

Security & performance

// Gunakan binding / where terparameter query.where("name", "=", userInput); // Hindari konkatenasi mentah ke raw SQL untuk input pengguna // query.rawSql(`SELECT * FROM users WHERE name = '${userInput}'`); // buruk

API reference

Constructor (internal / library)

new NexaModels((secretKey = "nexa-default-secret-key-2025"));

Di aplikasi mulai dari NX.Storage().model("nama_tabel"); jangan menginstansiasi NexaModels langsung kecuali untuk pengembangan inti library.

Table methods

  • table(tableName) — set nama tabel
  • from(tableName) — alias table
  • Storage(tableName) — alias table

Selection methods

  • select(columns), except(columns)
  • noSensitive(), noTimestamps(), noSystem()

WHERE methods

  • where, orWhere, whereIn, whereNotIn
  • whereBetween, whereNotBetween, whereNull, whereNotNull
  • whereLike, orWhereLike
  • whereDate, whereYear, whereMonth, whereDay

JOIN methods

  • join, leftJoin, rightJoin, innerJoin

Order & group

  • orderBy, latest, oldest, inRandomOrder
  • groupBy, having

Limit

  • limit, offset, take, skip

SQL generation

  • toSql(), toSqlWithBindings(), toSqlWithParams(), getBindings()

API methods

  • get(endpoint, options), post(endpoint, options)
  • insert(data, endpoint, options), update(data, endpoint, options)
  • delete(endpoint, options), paginate(page, perPage, endpoint, options)

Utility

  • clone(), reset(), dump(), dd(), inspect()

Troubleshooting

  • Query tanpa hasil — cek nama tabel, kondisi WHERE, dan data di database.
  • SQL injection — gunakan prepared statements / where terparameter; hindari konkatenasi string.
  • Performa — pagination, pilih kolom secukupnya, indeks di DB.
  • Memori — chunking untuk data besar; reset query jika perlu.
console.log(query.toSql()); console.log(query.getBindings()); query.dump(); console.log(query.inspect());