@promakeai/cli 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +214 -135
- package/dist/registry/about-page.json +1 -1
- package/dist/registry/about-section.json +1 -1
- package/dist/registry/api.json +55 -0
- package/dist/registry/auth.json +70 -0
- package/dist/registry/bento-grid-section.json +1 -1
- package/dist/registry/blog-list-page.json +1 -1
- package/dist/registry/blog-section.json +1 -1
- package/dist/registry/cart-drawer.json +1 -1
- package/dist/registry/cart-page.json +3 -2
- package/dist/registry/category-section.json +1 -1
- package/dist/registry/checkout-page.json +3 -2
- package/dist/registry/contact-info-grid.json +1 -1
- package/dist/registry/contact-page-centered.json +1 -1
- package/dist/registry/contact-page-map-overlay.json +1 -1
- package/dist/registry/contact-page.json +1 -1
- package/dist/registry/cookies-page.json +1 -1
- package/dist/registry/cta-section.json +1 -1
- package/dist/registry/db.json +129 -0
- package/dist/registry/docs/cart-page.md +1 -0
- package/dist/registry/docs/checkout-page.md +1 -0
- package/dist/registry/docs/forgot-password-page.md +37 -0
- package/dist/registry/docs/header-ecommerce.md +1 -0
- package/dist/registry/docs/products-page.md +1 -0
- package/dist/registry/docs/register-page.md +39 -0
- package/dist/registry/ecommerce-core.json +1 -1
- package/dist/registry/empty-page.json +1 -1
- package/dist/registry/faq-categorized.json +1 -1
- package/dist/registry/faq-simple.json +1 -1
- package/dist/registry/favorites-blog-block.json +1 -1
- package/dist/registry/favorites-ecommerce-block.json +1 -1
- package/dist/registry/feature-section.json +1 -1
- package/dist/registry/featured-products.json +1 -1
- package/dist/registry/footer-detailed.json +1 -1
- package/dist/registry/footer-minimal.json +3 -3
- package/dist/registry/footer.json +1 -1
- package/dist/registry/forgot-password-page.json +49 -0
- package/dist/registry/header-ecommerce.json +3 -2
- package/dist/registry/header-mega.json +1 -1
- package/dist/registry/header-minimal.json +1 -1
- package/dist/registry/header-simple.json +1 -1
- package/dist/registry/hero-cta.json +1 -1
- package/dist/registry/hero-gradient.json +1 -1
- package/dist/registry/hero-profile.json +1 -1
- package/dist/registry/hero.json +1 -1
- package/dist/registry/index.json +3 -0
- package/dist/registry/orders-list-block.json +1 -1
- package/dist/registry/payment-success-block.json +1 -1
- package/dist/registry/post-detail-block.json +1 -1
- package/dist/registry/pricing-section.json +1 -1
- package/dist/registry/privacy-page.json +1 -1
- package/dist/registry/products-page.json +3 -2
- package/dist/registry/register-page.json +49 -0
- package/dist/registry/related-posts-block.json +1 -1
- package/dist/registry/terms-page.json +1 -1
- package/dist/registry/testimonials-carousel.json +1 -1
- package/dist/registry/testimonials-grid.json +1 -1
- package/package.json +1 -1
- package/template/src/App.tsx +3 -24
- package/template/src/components/Layout.tsx +0 -4
- package/template/src/index.css +1 -0
- package/template/src/lang/en/index.json +1 -28
- package/template/src/lang/tr/index.json +1 -28
- package/template/src/pages/Index.tsx +1 -102
- package/template/src/components/Footer.tsx +0 -100
- package/template/src/components/Header.tsx +0 -79
- package/template/src/components/Hero.tsx +0 -69
- package/template/src/modules/api/USAGE.md +0 -515
- package/template/src/modules/api/customer-client.ts +0 -20
- package/template/src/modules/api/get-error-message.ts +0 -18
- package/template/src/modules/api/validation/en.json +0 -29
- package/template/src/modules/api/validation/tr.json +0 -29
- package/template/src/modules/auth/USAGE.md +0 -248
- package/template/src/modules/auth/auth-header-menu.tsx +0 -123
- package/template/src/modules/auth/auth-store.ts +0 -57
- package/template/src/modules/auth/forgot-password-page.tsx +0 -371
- package/template/src/modules/auth/login-page.tsx +0 -183
- package/template/src/modules/auth/register-page.tsx +0 -252
- package/template/src/modules/auth/use-auth.ts +0 -273
- package/template/src/modules/db/adapters/IDataAdapter.ts +0 -26
- package/template/src/modules/db/adapters/SqliteAdapter.ts +0 -364
- package/template/src/modules/db/adapters/index.ts +0 -2
- package/template/src/modules/db/config.ts +0 -59
- package/template/src/modules/db/core/DataManager.ts +0 -125
- package/template/src/modules/db/core/types.ts +0 -101
- package/template/src/modules/db/index.ts +0 -42
- package/template/src/modules/db/react/QueryProvider.tsx +0 -16
- package/template/src/modules/db/react/index.ts +0 -23
- package/template/src/modules/db/react/queryClient.ts +0 -64
- package/template/src/modules/db/react/useRepository.ts +0 -400
- package/template/src/modules/db/utils/parsers.ts +0 -96
|
@@ -1,364 +0,0 @@
|
|
|
1
|
-
import initSqlJs, { Database } from "sql.js";
|
|
2
|
-
import type { IDataAdapter } from "./IDataAdapter";
|
|
3
|
-
import type {
|
|
4
|
-
QueryOptions,
|
|
5
|
-
WhereCondition,
|
|
6
|
-
WhereGroup,
|
|
7
|
-
JoinClause,
|
|
8
|
-
} from "../core/types";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* SQLite Adapter
|
|
12
|
-
* Loads database from file using sql.js
|
|
13
|
-
* Supports complex queries: JOIN, WHERE groups, LIKE, IN, BETWEEN
|
|
14
|
-
*/
|
|
15
|
-
export class SqliteAdapter implements IDataAdapter {
|
|
16
|
-
private db: Database | null = null;
|
|
17
|
-
private dbPath: string;
|
|
18
|
-
|
|
19
|
-
constructor(dbPath: string = "/data/database.db") {
|
|
20
|
-
this.dbPath = dbPath;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// ============================================
|
|
24
|
-
// CONNECTION
|
|
25
|
-
// ============================================
|
|
26
|
-
|
|
27
|
-
async connect(): Promise<void> {
|
|
28
|
-
if (this.db) return;
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
const SQL = await initSqlJs({
|
|
32
|
-
locateFile: (file: string) => `https://sql.js.org/dist/${file}`,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
const response = await fetch(this.dbPath);
|
|
36
|
-
if (!response.ok) {
|
|
37
|
-
throw new Error(`Database file not found: ${this.dbPath}`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const buffer = await response.arrayBuffer();
|
|
41
|
-
this.db = new SQL.Database(new Uint8Array(buffer));
|
|
42
|
-
console.log("SQLite adapter connected");
|
|
43
|
-
} catch (error) {
|
|
44
|
-
console.error("SQLite adapter connection failed:", error);
|
|
45
|
-
throw error;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async disconnect(): Promise<void> {
|
|
50
|
-
if (this.db) {
|
|
51
|
-
this.db.close();
|
|
52
|
-
this.db = null;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// ============================================
|
|
57
|
-
// CRUD OPERATIONS
|
|
58
|
-
// ============================================
|
|
59
|
-
|
|
60
|
-
async findMany<T>(table: string, options?: QueryOptions): Promise<T[]> {
|
|
61
|
-
await this.connect();
|
|
62
|
-
if (!this.db) {
|
|
63
|
-
console.warn("Database not connected");
|
|
64
|
-
return [];
|
|
65
|
-
}
|
|
66
|
-
try {
|
|
67
|
-
const { sql, params } = this.buildSelectQuery(table, options);
|
|
68
|
-
return this.executeQuery<T>(sql, params);
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error(`Error querying table ${table}:`, error);
|
|
71
|
-
return [];
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async findOne<T>(table: string, options: QueryOptions): Promise<T | null> {
|
|
76
|
-
const results = await this.findMany<T>(table, { ...options, limit: 1 });
|
|
77
|
-
return results[0] || null;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async findById<T>(table: string, id: number | string): Promise<T | null> {
|
|
81
|
-
return this.findOne<T>(table, { where: { id } });
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async create<T>(table: string, data: Partial<T>): Promise<T> {
|
|
85
|
-
await this.connect();
|
|
86
|
-
|
|
87
|
-
// Otomatik timestamp - sadece yoksa ekle
|
|
88
|
-
const dataWithTimestamps: any = { ...data };
|
|
89
|
-
|
|
90
|
-
if (!dataWithTimestamps.created_at) {
|
|
91
|
-
dataWithTimestamps.created_at = new Date().toISOString();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (!dataWithTimestamps.updated_at) {
|
|
95
|
-
dataWithTimestamps.updated_at = new Date().toISOString();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const keys = Object.keys(dataWithTimestamps);
|
|
99
|
-
const values = Object.values(dataWithTimestamps) as any[];
|
|
100
|
-
const placeholders = keys.map(() => "?").join(", ");
|
|
101
|
-
|
|
102
|
-
const sql = `INSERT INTO ${table} (${keys.join(", ")}) VALUES (${placeholders})`;
|
|
103
|
-
this.db!.run(sql, values);
|
|
104
|
-
|
|
105
|
-
const lastIdResult = this.db!.exec("SELECT last_insert_rowid() as id");
|
|
106
|
-
const lastId = lastIdResult[0]?.values[0]?.[0] as number;
|
|
107
|
-
|
|
108
|
-
return this.findById<T>(table, lastId) as Promise<T>;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async update<T>(
|
|
112
|
-
table: string,
|
|
113
|
-
id: number | string,
|
|
114
|
-
data: Partial<T>,
|
|
115
|
-
): Promise<T> {
|
|
116
|
-
await this.connect();
|
|
117
|
-
|
|
118
|
-
// Otomatik updated_at - her zaman güncelle
|
|
119
|
-
const dataWithTimestamp = {
|
|
120
|
-
...data,
|
|
121
|
-
updated_at: new Date().toISOString(),
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const keys = Object.keys(dataWithTimestamp);
|
|
125
|
-
const values = Object.values(dataWithTimestamp) as any[];
|
|
126
|
-
const setClause = keys.map((key) => `${key} = ?`).join(", ");
|
|
127
|
-
|
|
128
|
-
const sql = `UPDATE ${table} SET ${setClause} WHERE id = ?`;
|
|
129
|
-
this.db!.run(sql, [...values, id]);
|
|
130
|
-
|
|
131
|
-
return this.findById<T>(table, id) as Promise<T>;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
async delete(table: string, id: number | string): Promise<boolean> {
|
|
135
|
-
await this.connect();
|
|
136
|
-
const sql = `DELETE FROM ${table} WHERE id = ?`;
|
|
137
|
-
this.db!.run(sql, [id]);
|
|
138
|
-
return true;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async count(table: string, options?: QueryOptions): Promise<number> {
|
|
142
|
-
await this.connect();
|
|
143
|
-
const { sql, params } = this.buildCountQuery(table, options);
|
|
144
|
-
const results = await this.executeQuery<{ count: number }>(sql, params);
|
|
145
|
-
return results[0]?.count || 0;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// ============================================
|
|
149
|
-
// RAW SQL QUERIES
|
|
150
|
-
// ============================================
|
|
151
|
-
|
|
152
|
-
async raw<T>(sql: string, params?: any[]): Promise<T[]> {
|
|
153
|
-
await this.connect();
|
|
154
|
-
return this.executeQuery<T>(sql, params);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
async rawOne<T>(sql: string, params?: any[]): Promise<T | null> {
|
|
158
|
-
const results = await this.raw<T>(sql, params);
|
|
159
|
-
return results[0] || null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// ============================================
|
|
163
|
-
// PRIVATE: QUERY EXECUTION
|
|
164
|
-
// ============================================
|
|
165
|
-
|
|
166
|
-
private async executeQuery<T>(sql: string, params?: any[]): Promise<T[]> {
|
|
167
|
-
if (!this.db) {
|
|
168
|
-
console.warn("Database not connected");
|
|
169
|
-
return [];
|
|
170
|
-
}
|
|
171
|
-
try {
|
|
172
|
-
const stmt = this.db.prepare(sql);
|
|
173
|
-
if (params && params.length > 0) stmt.bind(params);
|
|
174
|
-
|
|
175
|
-
const results: T[] = [];
|
|
176
|
-
while (stmt.step()) {
|
|
177
|
-
results.push(stmt.getAsObject() as T);
|
|
178
|
-
}
|
|
179
|
-
stmt.free();
|
|
180
|
-
return results;
|
|
181
|
-
} catch (error) {
|
|
182
|
-
console.error(`Query error: ${sql}`, error);
|
|
183
|
-
return [];
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// ============================================
|
|
188
|
-
// PRIVATE: QUERY BUILDERS
|
|
189
|
-
// ============================================
|
|
190
|
-
|
|
191
|
-
private buildSelectQuery(
|
|
192
|
-
table: string,
|
|
193
|
-
options?: QueryOptions,
|
|
194
|
-
): { sql: string; params: any[] } {
|
|
195
|
-
const params: any[] = [];
|
|
196
|
-
|
|
197
|
-
// SELECT clause
|
|
198
|
-
const selectFields = options?.select?.join(", ") || "*";
|
|
199
|
-
const distinct = options?.distinct ? "DISTINCT " : "";
|
|
200
|
-
let sql = `SELECT ${distinct}${selectFields} FROM ${table}`;
|
|
201
|
-
|
|
202
|
-
// JOIN clauses
|
|
203
|
-
if (options?.joins && options.joins.length > 0) {
|
|
204
|
-
sql += this.buildJoinClause(options.joins);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// WHERE clause
|
|
208
|
-
const whereClause = this.buildWhereClause(options, params);
|
|
209
|
-
if (whereClause) {
|
|
210
|
-
sql += ` WHERE ${whereClause}`;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// GROUP BY clause
|
|
214
|
-
if (options?.groupBy && options.groupBy.length > 0) {
|
|
215
|
-
sql += ` GROUP BY ${options.groupBy.join(", ")}`;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// HAVING clause
|
|
219
|
-
if (options?.having) {
|
|
220
|
-
const havingClause = this.buildWhereGroupClause(options.having, params);
|
|
221
|
-
if (havingClause) {
|
|
222
|
-
sql += ` HAVING ${havingClause}`;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// ORDER BY clause
|
|
227
|
-
if (options?.orderBy && options.orderBy.length > 0) {
|
|
228
|
-
const orderClauses = options.orderBy.map(
|
|
229
|
-
(o) => `${o.field} ${o.direction}`,
|
|
230
|
-
);
|
|
231
|
-
sql += ` ORDER BY ${orderClauses.join(", ")}`;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// LIMIT & OFFSET
|
|
235
|
-
if (options?.limit) {
|
|
236
|
-
sql += ` LIMIT ?`;
|
|
237
|
-
params.push(options.limit);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
if (options?.offset) {
|
|
241
|
-
sql += ` OFFSET ?`;
|
|
242
|
-
params.push(options.offset);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
return { sql, params };
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
private buildCountQuery(
|
|
249
|
-
table: string,
|
|
250
|
-
options?: QueryOptions,
|
|
251
|
-
): { sql: string; params: any[] } {
|
|
252
|
-
const params: any[] = [];
|
|
253
|
-
let sql = `SELECT COUNT(*) as count FROM ${table}`;
|
|
254
|
-
|
|
255
|
-
// JOIN clauses
|
|
256
|
-
if (options?.joins && options.joins.length > 0) {
|
|
257
|
-
sql += this.buildJoinClause(options.joins);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// WHERE clause
|
|
261
|
-
const whereClause = this.buildWhereClause(options, params);
|
|
262
|
-
if (whereClause) {
|
|
263
|
-
sql += ` WHERE ${whereClause}`;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
return { sql, params };
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
private buildJoinClause(joins: JoinClause[]): string {
|
|
270
|
-
return joins
|
|
271
|
-
.map((join) => {
|
|
272
|
-
const alias = join.alias ? ` ${join.alias}` : "";
|
|
273
|
-
const leftField = join.on.leftField;
|
|
274
|
-
const rightField = join.on.rightField;
|
|
275
|
-
return ` ${join.type} JOIN ${join.table}${alias} ON ${leftField} = ${rightField}`;
|
|
276
|
-
})
|
|
277
|
-
.join("");
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
private buildWhereClause(
|
|
281
|
-
options: QueryOptions | undefined,
|
|
282
|
-
params: any[],
|
|
283
|
-
): string {
|
|
284
|
-
const clauses: string[] = [];
|
|
285
|
-
|
|
286
|
-
// Simple where (backwards compatible)
|
|
287
|
-
if (options?.where) {
|
|
288
|
-
const simpleConditions = Object.entries(options.where).map(
|
|
289
|
-
([key, value]) => {
|
|
290
|
-
params.push(value);
|
|
291
|
-
return `${key} = ?`;
|
|
292
|
-
},
|
|
293
|
-
);
|
|
294
|
-
if (simpleConditions.length > 0) {
|
|
295
|
-
clauses.push(simpleConditions.join(" AND "));
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// Advanced where (new feature)
|
|
300
|
-
if (options?.whereAdvanced) {
|
|
301
|
-
const advancedClause = this.buildWhereGroupClause(
|
|
302
|
-
options.whereAdvanced,
|
|
303
|
-
params,
|
|
304
|
-
);
|
|
305
|
-
if (advancedClause) {
|
|
306
|
-
clauses.push(advancedClause);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
return clauses.length > 0 ? clauses.join(" AND ") : "";
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
private buildWhereGroupClause(group: WhereGroup, params: any[]): string {
|
|
314
|
-
const conditions = group.conditions
|
|
315
|
-
.map((condition) => {
|
|
316
|
-
// Recursive: WhereGroup
|
|
317
|
-
if ("type" in condition && "conditions" in condition) {
|
|
318
|
-
return `(${this.buildWhereGroupClause(condition as WhereGroup, params)})`;
|
|
319
|
-
}
|
|
320
|
-
// WhereCondition
|
|
321
|
-
return this.buildConditionClause(condition as WhereCondition, params);
|
|
322
|
-
})
|
|
323
|
-
.filter(Boolean);
|
|
324
|
-
|
|
325
|
-
return conditions.join(` ${group.type} `);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
private buildConditionClause(
|
|
329
|
-
condition: WhereCondition,
|
|
330
|
-
params: any[],
|
|
331
|
-
): string {
|
|
332
|
-
const { field, operator, value } = condition;
|
|
333
|
-
|
|
334
|
-
switch (operator) {
|
|
335
|
-
case "IS NULL":
|
|
336
|
-
return `${field} IS NULL`;
|
|
337
|
-
|
|
338
|
-
case "IS NOT NULL":
|
|
339
|
-
return `${field} IS NOT NULL`;
|
|
340
|
-
|
|
341
|
-
case "IN":
|
|
342
|
-
case "NOT IN":
|
|
343
|
-
if (Array.isArray(value)) {
|
|
344
|
-
const placeholders = value.map(() => "?").join(", ");
|
|
345
|
-
params.push(...value);
|
|
346
|
-
return `${field} ${operator} (${placeholders})`;
|
|
347
|
-
}
|
|
348
|
-
return "";
|
|
349
|
-
|
|
350
|
-
case "BETWEEN":
|
|
351
|
-
case "NOT BETWEEN":
|
|
352
|
-
if (Array.isArray(value) && value.length === 2) {
|
|
353
|
-
params.push(value[0], value[1]);
|
|
354
|
-
return `${field} ${operator} ? AND ?`;
|
|
355
|
-
}
|
|
356
|
-
return "";
|
|
357
|
-
|
|
358
|
-
default:
|
|
359
|
-
// =, !=, <>, >, <, >=, <=, LIKE, NOT LIKE
|
|
360
|
-
params.push(value);
|
|
361
|
-
return `${field} ${operator} ?`;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { IDataAdapter } from "./adapters/IDataAdapter";
|
|
2
|
-
import { SqliteAdapter } from "./adapters/SqliteAdapter";
|
|
3
|
-
|
|
4
|
-
export type AdapterType = "sqlite";
|
|
5
|
-
|
|
6
|
-
export interface DataConfig {
|
|
7
|
-
adapter: AdapterType;
|
|
8
|
-
options?: {
|
|
9
|
-
dbPath?: string;
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Get configuration from environment variables
|
|
15
|
-
*/
|
|
16
|
-
function getConfig(): DataConfig {
|
|
17
|
-
const adapter =
|
|
18
|
-
(import.meta.env.VITE_DATA_ADAPTER as AdapterType) || "sqlite";
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
adapter,
|
|
22
|
-
options: {
|
|
23
|
-
dbPath: import.meta.env.VITE_DB_PATH || "/data/database.db",
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Create adapter instance based on configuration
|
|
30
|
-
*/
|
|
31
|
-
export function createAdapter(config: DataConfig): IDataAdapter {
|
|
32
|
-
switch (config.adapter) {
|
|
33
|
-
case "sqlite":
|
|
34
|
-
return new SqliteAdapter(config.options?.dbPath);
|
|
35
|
-
|
|
36
|
-
default:
|
|
37
|
-
throw new Error(`Unknown adapter: ${config.adapter}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Get the configured adapter instance (singleton)
|
|
43
|
-
*/
|
|
44
|
-
let adapterInstance: IDataAdapter | null = null;
|
|
45
|
-
|
|
46
|
-
export function getAdapter(): IDataAdapter {
|
|
47
|
-
if (!adapterInstance) {
|
|
48
|
-
const config = getConfig();
|
|
49
|
-
adapterInstance = createAdapter(config);
|
|
50
|
-
}
|
|
51
|
-
return adapterInstance;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Reset adapter instance (useful for testing or switching adapters)
|
|
56
|
-
*/
|
|
57
|
-
export function resetAdapter(): void {
|
|
58
|
-
adapterInstance = null;
|
|
59
|
-
}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import type { IDataAdapter } from "../adapters/IDataAdapter";
|
|
2
|
-
import type { QueryOptions, PaginatedResult } from "./types";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* DataManager - Simple proxy to adapter
|
|
6
|
-
*/
|
|
7
|
-
export class DataManager {
|
|
8
|
-
private static instance: DataManager;
|
|
9
|
-
private adapter: IDataAdapter;
|
|
10
|
-
|
|
11
|
-
private constructor(adapter: IDataAdapter) {
|
|
12
|
-
this.adapter = adapter;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
static getInstance(adapter: IDataAdapter): DataManager {
|
|
16
|
-
if (!DataManager.instance) {
|
|
17
|
-
DataManager.instance = new DataManager(adapter);
|
|
18
|
-
}
|
|
19
|
-
return DataManager.instance;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Simple pass-through methods - no cache logic
|
|
23
|
-
async query<T = any>(table: string, options?: QueryOptions): Promise<T[]> {
|
|
24
|
-
return this.adapter.findMany<T>(table, options);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async queryOne<T = any>(
|
|
28
|
-
table: string,
|
|
29
|
-
options?: QueryOptions,
|
|
30
|
-
): Promise<T | null> {
|
|
31
|
-
const results = await this.query<T>(table, { ...options, limit: 1 });
|
|
32
|
-
return results[0] || null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async queryById<T = any>(
|
|
36
|
-
table: string,
|
|
37
|
-
id: number | string,
|
|
38
|
-
): Promise<T | null> {
|
|
39
|
-
return this.adapter.findById<T>(table, id);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async count(table: string, options?: QueryOptions): Promise<number> {
|
|
43
|
-
return this.adapter.count(table, options);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async paginate<T = any>(
|
|
47
|
-
table: string,
|
|
48
|
-
page: number = 1,
|
|
49
|
-
limit: number = 10,
|
|
50
|
-
options?: QueryOptions,
|
|
51
|
-
): Promise<PaginatedResult<T>> {
|
|
52
|
-
const offset = (page - 1) * limit;
|
|
53
|
-
|
|
54
|
-
const [data, total] = await Promise.all([
|
|
55
|
-
this.query<T>(table, { ...options, limit, offset }),
|
|
56
|
-
this.count(table, options),
|
|
57
|
-
]);
|
|
58
|
-
|
|
59
|
-
return {
|
|
60
|
-
data,
|
|
61
|
-
page,
|
|
62
|
-
limit,
|
|
63
|
-
total,
|
|
64
|
-
totalPages: Math.ceil(total / limit),
|
|
65
|
-
hasMore: page * limit < total,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Mutations - no cache invalidation here (React Query handles it)
|
|
70
|
-
async create<T = any>(table: string, data: Partial<T>): Promise<T> {
|
|
71
|
-
return this.adapter.create<T>(table, data);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async update<T = any>(
|
|
75
|
-
table: string,
|
|
76
|
-
id: number | string,
|
|
77
|
-
data: Partial<T>,
|
|
78
|
-
): Promise<T> {
|
|
79
|
-
return this.adapter.update<T>(table, id, data);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async delete(table: string, id: number | string): Promise<boolean> {
|
|
83
|
-
return this.adapter.delete(table, id);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Direct adapter access for advanced use cases
|
|
87
|
-
getAdapter(): IDataAdapter {
|
|
88
|
-
return this.adapter;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// ============================================
|
|
92
|
-
// RAW SQL QUERIES
|
|
93
|
-
// ============================================
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Execute raw SQL query - returns multiple rows
|
|
97
|
-
* Use for complex queries that can't be expressed with QueryOptions
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* const posts = await dm.raw<Post>(`
|
|
101
|
-
* SELECT DISTINCT p.*, c.name as category_name
|
|
102
|
-
* FROM posts p
|
|
103
|
-
* JOIN post_categories pc ON p.id = pc.post_id
|
|
104
|
-
* JOIN blog_categories c ON pc.category_id = c.id
|
|
105
|
-
* WHERE c.slug = ? AND p.published = 1
|
|
106
|
-
* `, [categorySlug]);
|
|
107
|
-
*/
|
|
108
|
-
async raw<T = any>(sql: string, params?: any[]): Promise<T[]> {
|
|
109
|
-
return this.adapter.raw<T>(sql, params);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Execute raw SQL query - returns single row or null
|
|
114
|
-
* Use for aggregations, single record lookups
|
|
115
|
-
*
|
|
116
|
-
* @example
|
|
117
|
-
* const priceRange = await dm.rawOne<{min: number, max: number}>(`
|
|
118
|
-
* SELECT MIN(price) as min, MAX(price) as max
|
|
119
|
-
* FROM products WHERE published = 1
|
|
120
|
-
* `);
|
|
121
|
-
*/
|
|
122
|
-
async rawOne<T = any>(sql: string, params?: any[]): Promise<T | null> {
|
|
123
|
-
return this.adapter.rawOne<T>(sql, params);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core type definitions for data-access module
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
// ============================================
|
|
6
|
-
// WHERE CONDITIONS
|
|
7
|
-
// ============================================
|
|
8
|
-
|
|
9
|
-
/** WHERE condition operators */
|
|
10
|
-
export type WhereOperator =
|
|
11
|
-
| "="
|
|
12
|
-
| "!="
|
|
13
|
-
| "<>"
|
|
14
|
-
| ">"
|
|
15
|
-
| "<"
|
|
16
|
-
| ">="
|
|
17
|
-
| "<="
|
|
18
|
-
| "LIKE"
|
|
19
|
-
| "NOT LIKE"
|
|
20
|
-
| "IN"
|
|
21
|
-
| "NOT IN"
|
|
22
|
-
| "BETWEEN"
|
|
23
|
-
| "NOT BETWEEN"
|
|
24
|
-
| "IS NULL"
|
|
25
|
-
| "IS NOT NULL";
|
|
26
|
-
|
|
27
|
-
/** Single WHERE condition */
|
|
28
|
-
export interface WhereCondition {
|
|
29
|
-
field: string;
|
|
30
|
-
operator: WhereOperator;
|
|
31
|
-
value: any;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** WHERE groups (AND/OR) - recursive structure */
|
|
35
|
-
export interface WhereGroup {
|
|
36
|
-
type: "AND" | "OR";
|
|
37
|
-
conditions: (WhereCondition | WhereGroup)[];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// ============================================
|
|
41
|
-
// JOIN DEFINITIONS
|
|
42
|
-
// ============================================
|
|
43
|
-
|
|
44
|
-
/** JOIN types */
|
|
45
|
-
export type JoinType = "INNER" | "LEFT" | "RIGHT" | "CROSS";
|
|
46
|
-
|
|
47
|
-
/** JOIN definition */
|
|
48
|
-
export interface JoinClause {
|
|
49
|
-
type: JoinType;
|
|
50
|
-
table: string;
|
|
51
|
-
alias?: string;
|
|
52
|
-
on: {
|
|
53
|
-
leftField: string;
|
|
54
|
-
rightField: string;
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// ============================================
|
|
59
|
-
// QUERY OPTIONS
|
|
60
|
-
// ============================================
|
|
61
|
-
|
|
62
|
-
/** Order definition */
|
|
63
|
-
export interface OrderBy {
|
|
64
|
-
field: string;
|
|
65
|
-
direction: "ASC" | "DESC";
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Extended Query Options */
|
|
69
|
-
export interface QueryOptions {
|
|
70
|
-
// Existing (backwards compatible)
|
|
71
|
-
where?: Record<string, any>;
|
|
72
|
-
limit?: number;
|
|
73
|
-
offset?: number;
|
|
74
|
-
orderBy?: OrderBy[];
|
|
75
|
-
include?: string[];
|
|
76
|
-
|
|
77
|
-
// New features
|
|
78
|
-
select?: string[]; // SELECT fields: ['p.*', 'c.name as category_name']
|
|
79
|
-
distinct?: boolean; // DISTINCT usage
|
|
80
|
-
joins?: JoinClause[]; // JOIN definitions
|
|
81
|
-
whereAdvanced?: WhereGroup; // Complex WHERE conditions (AND/OR groups)
|
|
82
|
-
groupBy?: string[]; // GROUP BY fields
|
|
83
|
-
having?: WhereGroup; // HAVING conditions
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// ============================================
|
|
87
|
-
// RESULT TYPES
|
|
88
|
-
// ============================================
|
|
89
|
-
|
|
90
|
-
/** Paginated result */
|
|
91
|
-
export interface PaginatedResult<T> {
|
|
92
|
-
data: T[];
|
|
93
|
-
page: number;
|
|
94
|
-
limit: number;
|
|
95
|
-
total: number;
|
|
96
|
-
totalPages: number;
|
|
97
|
-
hasMore: boolean;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/** Query key (for cache) */
|
|
101
|
-
export type QueryKey = (string | number | object)[];
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DB Module
|
|
3
|
-
* Universal data management with adapter pattern + React Query
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// Core
|
|
7
|
-
export { DataManager } from "./core/DataManager";
|
|
8
|
-
export type {
|
|
9
|
-
QueryOptions,
|
|
10
|
-
OrderBy,
|
|
11
|
-
PaginatedResult,
|
|
12
|
-
// Complex query types
|
|
13
|
-
WhereOperator,
|
|
14
|
-
WhereCondition,
|
|
15
|
-
WhereGroup,
|
|
16
|
-
JoinType,
|
|
17
|
-
JoinClause,
|
|
18
|
-
} from "./core/types";
|
|
19
|
-
|
|
20
|
-
// Adapters
|
|
21
|
-
export type { IDataAdapter } from "./adapters/IDataAdapter";
|
|
22
|
-
export { SqliteAdapter } from "./adapters/SqliteAdapter";
|
|
23
|
-
|
|
24
|
-
// Config
|
|
25
|
-
export { getAdapter, createAdapter, resetAdapter } from "./config";
|
|
26
|
-
export type { DataConfig, AdapterType } from "./config";
|
|
27
|
-
|
|
28
|
-
// React exports (re-export from react/index.ts)
|
|
29
|
-
export * from "./react";
|
|
30
|
-
|
|
31
|
-
// Re-export for convenience
|
|
32
|
-
export { DBQueryProvider as QueryProvider } from "./react";
|
|
33
|
-
|
|
34
|
-
// Utility exports (parsers for client-side data transformation)
|
|
35
|
-
export {
|
|
36
|
-
parseCommaSeparatedString,
|
|
37
|
-
parseJSONStringToArray,
|
|
38
|
-
parseStringToArray,
|
|
39
|
-
parseJSONString,
|
|
40
|
-
parseSQLiteBoolean,
|
|
41
|
-
parseNumberSafe,
|
|
42
|
-
} from "./utils/parsers";
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { QueryClientProvider } from "@tanstack/react-query";
|
|
2
|
-
import { queryClient } from "./queryClient";
|
|
3
|
-
|
|
4
|
-
interface DBQueryProviderProps {
|
|
5
|
-
children: React.ReactNode;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* DBQueryProvider - DB module's React Query provider
|
|
10
|
-
* Wraps components that use db module hooks
|
|
11
|
-
*/
|
|
12
|
-
export function DBQueryProvider({ children }: DBQueryProviderProps) {
|
|
13
|
-
return (
|
|
14
|
-
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
15
|
-
);
|
|
16
|
-
}
|