@promakeai/cli 0.4.7 → 0.5.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.
Files changed (61) hide show
  1. package/README.md +71 -0
  2. package/dist/index.js +161 -168
  3. package/dist/registry/blog-core.json +7 -26
  4. package/dist/registry/blog-list-page.json +2 -2
  5. package/dist/registry/blog-section.json +1 -1
  6. package/dist/registry/cart-drawer.json +1 -1
  7. package/dist/registry/cart-page.json +1 -1
  8. package/dist/registry/category-section.json +1 -1
  9. package/dist/registry/checkout-page.json +1 -1
  10. package/dist/registry/contact-page-centered.json +1 -1
  11. package/dist/registry/contact-page-map-overlay.json +1 -1
  12. package/dist/registry/contact-page-map-split.json +1 -1
  13. package/dist/registry/contact-page-split.json +1 -1
  14. package/dist/registry/contact-page.json +1 -1
  15. package/dist/registry/docs/blog-core.md +12 -13
  16. package/dist/registry/docs/blog-list-page.md +1 -1
  17. package/dist/registry/docs/ecommerce-core.md +10 -13
  18. package/dist/registry/docs/featured-products.md +1 -1
  19. package/dist/registry/docs/post-detail-page.md +2 -2
  20. package/dist/registry/docs/product-detail-page.md +2 -2
  21. package/dist/registry/docs/products-page.md +1 -1
  22. package/dist/registry/ecommerce-core.json +5 -25
  23. package/dist/registry/featured-products.json +2 -2
  24. package/dist/registry/forgot-password-page-split.json +1 -1
  25. package/dist/registry/forgot-password-page.json +1 -1
  26. package/dist/registry/header-centered-pill.json +1 -1
  27. package/dist/registry/header-ecommerce.json +1 -1
  28. package/dist/registry/index.json +0 -1
  29. package/dist/registry/login-page-split.json +1 -1
  30. package/dist/registry/login-page.json +1 -1
  31. package/dist/registry/newsletter-section.json +1 -1
  32. package/dist/registry/post-card.json +1 -1
  33. package/dist/registry/post-detail-block.json +1 -1
  34. package/dist/registry/post-detail-page.json +3 -3
  35. package/dist/registry/product-card-detailed.json +1 -1
  36. package/dist/registry/product-card.json +1 -1
  37. package/dist/registry/product-detail-block.json +1 -1
  38. package/dist/registry/product-detail-page.json +3 -3
  39. package/dist/registry/product-detail-section.json +1 -1
  40. package/dist/registry/product-quick-view.json +1 -1
  41. package/dist/registry/products-page.json +2 -2
  42. package/dist/registry/register-page-split.json +1 -1
  43. package/dist/registry/register-page.json +1 -1
  44. package/dist/registry/related-products-block.json +1 -1
  45. package/dist/registry/reset-password-page-split.json +1 -1
  46. package/package.json +4 -2
  47. package/template/README.md +39 -58
  48. package/template/package.json +4 -3
  49. package/template/public/data/database.db +0 -0
  50. package/template/public/data/database.db-shm +0 -0
  51. package/template/public/data/database.db-wal +0 -0
  52. package/template/scripts/init-db.ts +13 -126
  53. package/template/src/App.tsx +8 -5
  54. package/template/src/components/FormField.tsx +5 -11
  55. package/template/src/db/index.ts +20 -0
  56. package/template/src/db/provider.tsx +77 -0
  57. package/template/src/db/schema.json +259 -0
  58. package/template/src/db/types.ts +195 -0
  59. package/template/src/hooks/use-debounced-value.ts +12 -0
  60. package/dist/registry/db.json +0 -129
  61. package/template/src/PasswordInput.tsx +0 -61
@@ -1,131 +1,18 @@
1
- import fs from "fs";
1
+ import { execSync } from "child_process";
2
2
  import path from "path";
3
- import initSqlJs from "sql.js";
4
3
 
5
- async function createDatabase() {
6
- const SQL = await initSqlJs();
7
- const db = new SQL.Database();
4
+ const cwd = process.cwd();
5
+ const schemaPath = path.join(cwd, "src", "db", "schema.json");
6
+ const outputDir = path.join(cwd, "src", "db");
7
+ const dbPath = path.join(cwd, "public", "data", "database.db");
8
8
 
9
- // ============================================
10
- // BLOG SISTEMI
11
- // ============================================
9
+ const cmd = `dbcli generate --schema "${schemaPath}" --database "${dbPath}" --output "${outputDir}"`;
12
10
 
13
- db.exec(`
14
- CREATE TABLE blog_categories (
15
- id INTEGER PRIMARY KEY AUTOINCREMENT,
16
- name TEXT NOT NULL,
17
- slug TEXT UNIQUE NOT NULL,
18
- description TEXT,
19
- image TEXT,
20
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
21
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
22
- );
23
- `);
24
-
25
- db.exec(`
26
- CREATE TABLE posts (
27
- id INTEGER PRIMARY KEY AUTOINCREMENT,
28
- title TEXT NOT NULL,
29
- slug TEXT UNIQUE NOT NULL,
30
- content TEXT NOT NULL,
31
- excerpt TEXT,
32
- featured_image TEXT,
33
- images TEXT,
34
- author TEXT,
35
- author_avatar TEXT,
36
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
37
- published_at DATETIME DEFAULT CURRENT_TIMESTAMP,
38
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
39
- tags TEXT,
40
- read_time INTEGER DEFAULT 0,
41
- view_count INTEGER DEFAULT 0,
42
- featured INTEGER DEFAULT 0,
43
- published INTEGER DEFAULT 1,
44
- meta_description TEXT,
45
- meta_keywords TEXT
46
- );
47
- `);
48
-
49
- db.exec(`
50
- CREATE TABLE post_categories (
51
- id INTEGER PRIMARY KEY AUTOINCREMENT,
52
- post_id INTEGER NOT NULL,
53
- category_id INTEGER NOT NULL,
54
- is_primary INTEGER DEFAULT 0,
55
- FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
56
- FOREIGN KEY (category_id) REFERENCES blog_categories(id) ON DELETE CASCADE
57
- );
58
- `);
59
-
60
- // ============================================
61
- // E-COMMERCE SISTEMI
62
- // ============================================
63
-
64
- db.exec(`
65
- CREATE TABLE product_categories (
66
- id INTEGER PRIMARY KEY AUTOINCREMENT,
67
- name TEXT NOT NULL,
68
- slug TEXT UNIQUE NOT NULL,
69
- description TEXT,
70
- image TEXT,
71
- parent_id INTEGER,
72
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
73
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
74
- FOREIGN KEY (parent_id) REFERENCES product_categories(id) ON DELETE SET NULL
75
- );
76
- `);
77
-
78
- db.exec(`
79
- CREATE TABLE products (
80
- id INTEGER PRIMARY KEY AUTOINCREMENT,
81
- name TEXT NOT NULL,
82
- slug TEXT UNIQUE NOT NULL,
83
- description TEXT,
84
- price REAL NOT NULL,
85
- sale_price REAL,
86
- on_sale INTEGER DEFAULT 0,
87
- images TEXT,
88
- brand TEXT,
89
- sku TEXT,
90
- stock INTEGER DEFAULT 0,
91
- tags TEXT,
92
- rating REAL DEFAULT 0,
93
- review_count INTEGER DEFAULT 0,
94
- featured INTEGER DEFAULT 0,
95
- is_new INTEGER DEFAULT 0,
96
- published INTEGER DEFAULT 1,
97
- specifications TEXT,
98
- variants TEXT,
99
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
100
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
101
- meta_description TEXT,
102
- meta_keywords TEXT
103
- );
104
- `);
105
-
106
- db.exec(`
107
- CREATE TABLE product_category_relations (
108
- id INTEGER PRIMARY KEY AUTOINCREMENT,
109
- product_id INTEGER NOT NULL,
110
- category_id INTEGER NOT NULL,
111
- is_primary INTEGER DEFAULT 0,
112
- FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE,
113
- FOREIGN KEY (category_id) REFERENCES product_categories(id) ON DELETE CASCADE
114
- );
115
- `);
116
-
117
- // Database'i dosyaya kaydet
118
- const data = db.export();
119
- const buffer = Buffer.from(data);
120
-
121
- const outputPath = path.join(process.cwd(), "public/data/database.db");
122
- fs.mkdirSync(path.dirname(outputPath), { recursive: true });
123
- fs.writeFileSync(outputPath, buffer);
124
-
125
- console.log(`Database olusturuldu: ${outputPath}`);
126
- console.log("Tablolar (6):");
127
- console.log(" - blog_categories, posts, post_categories");
128
- console.log(" - product_categories, products, product_category_relations");
11
+ try {
12
+ console.log("Generating database with dbcli...");
13
+ execSync(cmd, { stdio: "inherit" });
14
+ console.log(`Database created: ${dbPath}`);
15
+ } catch (err) {
16
+ console.error("Failed to generate database. Ensure dbcli is installed globally.");
17
+ throw err;
129
18
  }
130
-
131
- createDatabase().catch(console.error);
@@ -1,15 +1,18 @@
1
1
  import { TooltipProvider } from "@/components/ui/tooltip";
2
2
  import { GoogleAnalytics } from "@/components/GoogleAnalytics";
3
3
  import { ScriptInjector } from "@/components/ScriptInjector";
4
+ import { AppDbProvider } from "@/db";
4
5
  import { Router } from "./router";
5
6
 
6
7
  const App = () => {
7
8
  return (
8
- <TooltipProvider>
9
- <GoogleAnalytics />
10
- <ScriptInjector />
11
- <Router />
12
- </TooltipProvider>
9
+ <AppDbProvider>
10
+ <TooltipProvider>
11
+ <GoogleAnalytics />
12
+ <ScriptInjector />
13
+ <Router />
14
+ </TooltipProvider>
15
+ </AppDbProvider>
13
16
  );
14
17
  };
15
18
 
@@ -1,17 +1,15 @@
1
1
  import { Stack } from "./Stack";
2
2
  import { Label } from "./ui/label";
3
3
 
4
- // FormField.tsx
5
4
  export interface FormFieldProps {
6
- label: React.ReactNode;
5
+ label: string;
7
6
  htmlFor?: string;
8
7
  error?: string;
9
8
  required?: boolean;
10
9
  description?: string;
11
10
  children: React.ReactNode;
12
- gap?: 0 | 1 | 2 | 3 | 4 | 6 | 8 | 10 | 12;
11
+ gap?: 0 | 1 | 2 | 3 | 4 | 6 | 8 | 10 | 12; // Stack gap override
13
12
  className?: string;
14
- labelAction?: React.ReactNode; // YENİ
15
13
  }
16
14
 
17
15
  export function FormField({
@@ -23,16 +21,12 @@ export function FormField({
23
21
  description,
24
22
  gap = 2,
25
23
  className,
26
- labelAction, // YENİ
27
24
  }: FormFieldProps) {
28
25
  return (
29
26
  <Stack gap={gap} className={className}>
30
- <div className="flex items-center justify-between">
31
- <Label htmlFor={htmlFor}>
32
- {label} {required && <span className="text-destructive">*</span>}
33
- </Label>
34
- {labelAction}
35
- </div>
27
+ <Label htmlFor={htmlFor}>
28
+ {label} {required && <span className="text-destructive">*</span>}
29
+ </Label>
36
30
  {children}
37
31
  {description && (
38
32
  <p className="text-sm text-muted-foreground">
@@ -0,0 +1,20 @@
1
+ export { AppDbProvider } from "./provider";
2
+
3
+ import { parseJSONSchema } from "@promakeai/dbreact";
4
+ import schemaJson from "./schema.json";
5
+ export const schema = parseJSONSchema(schemaJson as any);
6
+
7
+ export {
8
+ useDb,
9
+ useAdapter,
10
+ useDbLang,
11
+ useDbList,
12
+ useDbGet,
13
+ useDbCreate,
14
+ useDbUpdate,
15
+ useDbDelete,
16
+ SqliteAdapter,
17
+ parseJSONSchema,
18
+ } from "@promakeai/dbreact";
19
+
20
+ export * from "./types";
@@ -0,0 +1,77 @@
1
+ import { useEffect, useState, type ReactNode } from "react";
2
+ import { useTranslation } from "react-i18next";
3
+ import { DbProvider, SqliteAdapter, parseJSONSchema } from "@promakeai/dbreact";
4
+ import constants from "@/constants/constants.json";
5
+ import schemaJson from "./schema.json";
6
+
7
+ const schema = parseJSONSchema(schemaJson as any);
8
+
9
+ interface AppDbProviderProps {
10
+ children: ReactNode;
11
+ }
12
+
13
+ const DEFAULT_LANG = constants?.site?.defaultLanguage || "en";
14
+
15
+ export function AppDbProvider({ children }: AppDbProviderProps) {
16
+ const { i18n } = useTranslation();
17
+ const [adapter, setAdapter] = useState<SqliteAdapter | null>(null);
18
+ const [error, setError] = useState<Error | null>(null);
19
+
20
+ useEffect(() => {
21
+ let cancelled = false;
22
+
23
+ async function loadDb() {
24
+ try {
25
+ const response = await fetch("/data/database.db");
26
+ if (!response.ok) {
27
+ throw new Error(
28
+ `Failed to load database: ${response.status} ${response.statusText}`
29
+ );
30
+ }
31
+
32
+ const buffer = await response.arrayBuffer();
33
+ if (cancelled) return;
34
+
35
+ const dbAdapter = new SqliteAdapter({
36
+ schema,
37
+ defaultLang: DEFAULT_LANG,
38
+ });
39
+
40
+ await dbAdapter.connect();
41
+ await dbAdapter.import(new Uint8Array(buffer));
42
+
43
+ if (!cancelled) {
44
+ setAdapter(dbAdapter);
45
+ }
46
+ } catch (err) {
47
+ if (!cancelled) {
48
+ setError(err instanceof Error ? err : new Error(String(err)));
49
+ }
50
+ }
51
+ }
52
+
53
+ loadDb();
54
+
55
+ return () => {
56
+ cancelled = true;
57
+ };
58
+ }, []);
59
+
60
+ if (error) {
61
+ console.error(error);
62
+ }
63
+
64
+ if (!adapter) {
65
+ return null;
66
+ }
67
+
68
+ return (
69
+ <DbProvider
70
+ adapter={adapter}
71
+ lang={i18n?.language || DEFAULT_LANG}
72
+ fallbackLang={DEFAULT_LANG}
73
+ >
74
+ {children}
75
+ </DbProvider>
76
+ );
77
+ }
@@ -0,0 +1,259 @@
1
+ {
2
+ "name": "promake",
3
+ "languages": [
4
+ "en",
5
+ "tr"
6
+ ],
7
+ "defaultLanguage": "en",
8
+ "tables": {
9
+ "blog_categories": {
10
+ "id": {
11
+ "type": "id"
12
+ },
13
+ "name": {
14
+ "type": "string",
15
+ "nullable": false,
16
+ "translatable": true
17
+ },
18
+ "slug": {
19
+ "type": "string",
20
+ "nullable": false,
21
+ "unique": true
22
+ },
23
+ "description": {
24
+ "type": "text",
25
+ "translatable": true
26
+ },
27
+ "image": {
28
+ "type": "text"
29
+ },
30
+ "created_at": {
31
+ "type": "timestamp"
32
+ },
33
+ "updated_at": {
34
+ "type": "timestamp"
35
+ }
36
+ },
37
+ "posts": {
38
+ "id": {
39
+ "type": "id"
40
+ },
41
+ "title": {
42
+ "type": "string",
43
+ "nullable": false,
44
+ "translatable": true
45
+ },
46
+ "slug": {
47
+ "type": "string",
48
+ "nullable": false,
49
+ "unique": true
50
+ },
51
+ "content": {
52
+ "type": "text",
53
+ "nullable": false,
54
+ "translatable": true
55
+ },
56
+ "excerpt": {
57
+ "type": "text",
58
+ "translatable": true
59
+ },
60
+ "featured_image": {
61
+ "type": "text"
62
+ },
63
+ "images": {
64
+ "type": [
65
+ "string"
66
+ ]
67
+ },
68
+ "author": {
69
+ "type": "string",
70
+ "translatable": true
71
+ },
72
+ "author_avatar": {
73
+ "type": "text"
74
+ },
75
+ "created_at": {
76
+ "type": "timestamp"
77
+ },
78
+ "published_at": {
79
+ "type": "timestamp"
80
+ },
81
+ "updated_at": {
82
+ "type": "timestamp"
83
+ },
84
+ "tags": {
85
+ "type": [
86
+ "string"
87
+ ]
88
+ },
89
+ "categories": {
90
+ "type": [
91
+ "number"
92
+ ],
93
+ "ref": "blog_categories"
94
+ },
95
+ "read_time": {
96
+ "type": "int",
97
+ "default": 0
98
+ },
99
+ "view_count": {
100
+ "type": "int",
101
+ "default": 0
102
+ },
103
+ "featured": {
104
+ "type": "bool",
105
+ "default": false
106
+ },
107
+ "published": {
108
+ "type": "bool",
109
+ "default": true
110
+ },
111
+ "meta_description": {
112
+ "type": "text",
113
+ "translatable": true
114
+ },
115
+ "meta_keywords": {
116
+ "type": "text",
117
+ "translatable": true
118
+ }
119
+ },
120
+ "product_categories": {
121
+ "id": {
122
+ "type": "id"
123
+ },
124
+ "name": {
125
+ "type": "string",
126
+ "nullable": false,
127
+ "translatable": true
128
+ },
129
+ "slug": {
130
+ "type": "string",
131
+ "nullable": false,
132
+ "unique": true
133
+ },
134
+ "description": {
135
+ "type": "text",
136
+ "translatable": true
137
+ },
138
+ "image": {
139
+ "type": "text"
140
+ },
141
+ "parent_id": {
142
+ "type": "int",
143
+ "ref": "product_categories"
144
+ },
145
+ "created_at": {
146
+ "type": "timestamp"
147
+ },
148
+ "updated_at": {
149
+ "type": "timestamp"
150
+ }
151
+ },
152
+ "products": {
153
+ "id": {
154
+ "type": "id"
155
+ },
156
+ "name": {
157
+ "type": "string",
158
+ "nullable": false,
159
+ "translatable": true
160
+ },
161
+ "slug": {
162
+ "type": "string",
163
+ "nullable": false,
164
+ "unique": true
165
+ },
166
+ "description": {
167
+ "type": "text",
168
+ "translatable": true
169
+ },
170
+ "price": {
171
+ "type": "decimal",
172
+ "nullable": false
173
+ },
174
+ "sale_price": {
175
+ "type": "decimal"
176
+ },
177
+ "on_sale": {
178
+ "type": "bool",
179
+ "default": false
180
+ },
181
+ "images": {
182
+ "type": [
183
+ "string"
184
+ ]
185
+ },
186
+ "brand": {
187
+ "type": "string",
188
+ "translatable": true
189
+ },
190
+ "sku": {
191
+ "type": "string"
192
+ },
193
+ "stock": {
194
+ "type": "int",
195
+ "default": 0
196
+ },
197
+ "tags": {
198
+ "type": [
199
+ "string"
200
+ ]
201
+ },
202
+ "categories": {
203
+ "type": [
204
+ "number"
205
+ ],
206
+ "ref": "product_categories"
207
+ },
208
+ "rating": {
209
+ "type": "decimal",
210
+ "default": 0
211
+ },
212
+ "review_count": {
213
+ "type": "int",
214
+ "default": 0
215
+ },
216
+ "featured": {
217
+ "type": "bool",
218
+ "default": false
219
+ },
220
+ "is_new": {
221
+ "type": "bool",
222
+ "default": false
223
+ },
224
+ "published": {
225
+ "type": "bool",
226
+ "default": true
227
+ },
228
+ "specifications": {
229
+ "type": "json"
230
+ },
231
+ "variants": {
232
+ "type": [
233
+ {
234
+ "id": "string",
235
+ "name": "string",
236
+ "value": "string",
237
+ "price?": "number",
238
+ "image?": "string",
239
+ "stockQuantity": "number"
240
+ }
241
+ ]
242
+ },
243
+ "created_at": {
244
+ "type": "timestamp"
245
+ },
246
+ "updated_at": {
247
+ "type": "timestamp"
248
+ },
249
+ "meta_description": {
250
+ "type": "text",
251
+ "translatable": true
252
+ },
253
+ "meta_keywords": {
254
+ "type": "text",
255
+ "translatable": true
256
+ }
257
+ }
258
+ }
259
+ }