create-fullstack-scaffold 0.6.0 → 0.6.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-fullstack-scaffold",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "create-fullstack-scaffold": "dist/cli/index.js"
@@ -9,7 +9,7 @@ Todo Application Template - A full-stack React + Hono application demonstrating
9
9
  ## Commands
10
10
 
11
11
  ```bash
12
- npm run dev # Start Vite dev server on port 3010 with Hono backend
12
+ npm run dev # Vite dev server (auto port, usually 5173) with Hono backend
13
13
  npm run build # Production build
14
14
  npm run preview # Preview production build
15
15
  npm run test # Run all Vitest tests
@@ -68,7 +68,7 @@ src/
68
68
 
69
69
  ### Single-Port Development
70
70
 
71
- Uses "@hono/vite-dev-server" to run both frontend and backend on port 3010:
71
+ Uses "@hono/vite-dev-server" to run both frontend and backend on one Vite-assigned port:
72
72
 
73
73
  - No CORS issues in development
74
74
  - Type safety across the boundary
@@ -169,7 +169,7 @@ import { useTodoStore } from '@client/stores/todoStore'
169
169
  Required variables (see `.env.example`):
170
170
 
171
171
  ```bash
172
- API_BASE_URL=http://localhost:3010
172
+ API_BASE_URL=http://localhost:5173
173
173
  ```
174
174
 
175
175
  ### Module Manifest System
@@ -147,7 +147,7 @@ The project has clear separation between framework and business layers:
147
147
 
148
148
  - ✅ Monorepo-style structure with client/server separation
149
149
  - ✅ Shared types for end-to-end type safety
150
- - ✅ Single-port development (3010) using @hono/vite-dev-server
150
+ - ✅ Single-port development (Vite-assigned, usually 5173) using @hono/vite-dev-server
151
151
  - ✅ Modular backend with feature-based organization
152
152
  - ✅ Framework layer vs Business layer separation
153
153
 
@@ -15,10 +15,10 @@ npm install
15
15
  ## Development
16
16
 
17
17
  ```bash
18
- # Start development server (port 3010)
18
+ # Start development server (Vite-assigned port, usually 5173)
19
19
  npm run dev
20
20
 
21
- # The app will be available at http://localhost:3010
21
+ # The app URL is printed by the dev server (usually http://localhost:5173)
22
22
  ```
23
23
 
24
24
  ## Project Structure
@@ -276,7 +276,7 @@ git commit --no-verify -m "message"
276
276
  ### Port Already in Use
277
277
 
278
278
  ```bash
279
- # Kill process on port 3010
279
+ # Kill process on the dev port (adjust as printed; 5173 shown)
280
280
  lsof -ti:3010 | xargs kill -9
281
281
  ```
282
282
 
@@ -52,7 +52,7 @@ npm install
52
52
  npm run dev
53
53
  ```
54
54
 
55
- The application will be available at http://localhost:3010
55
+ Dev 端口由 Vite 自动分配(通常 5173,以启动日志为准);生产模式 `PORT=3010 npm start` 才是 3010
56
56
 
57
57
  ### Build
58
58
 
@@ -83,7 +83,7 @@ npm run test:integration
83
83
 
84
84
  ### Single-Port Development
85
85
 
86
- Uses "@hono/vite-dev-server" to run both frontend and backend on port 3010.
86
+ Uses "@hono/vite-dev-server" to run both frontend and backend on a single Vite-assigned port (usually 5173; see dev output).
87
87
 
88
88
  ### Framework Layer vs Business Layer
89
89
 
@@ -0,0 +1,390 @@
1
+ CREATE TABLE `todos` (
2
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
3
+ `tenant_id` integer,
4
+ `title` text NOT NULL,
5
+ `description` text,
6
+ `status` text DEFAULT 'pending' NOT NULL,
7
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
8
+ `updated_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
9
+ );
10
+ --> statement-breakpoint
11
+ CREATE INDEX `todos_status_idx` ON `todos` (`status`);--> statement-breakpoint
12
+ CREATE INDEX `todos_tenant_idx` ON `todos` (`tenant_id`);--> statement-breakpoint
13
+ CREATE INDEX `todos_created_at_idx` ON `todos` (`created_at`);--> statement-breakpoint
14
+ CREATE INDEX `todos_updated_at_idx` ON `todos` (`updated_at`);--> statement-breakpoint
15
+ CREATE TABLE `todo_attachments` (
16
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
17
+ `todo_id` integer NOT NULL,
18
+ `file_name` text NOT NULL,
19
+ `original_name` text NOT NULL,
20
+ `mime_type` text NOT NULL,
21
+ `size` integer NOT NULL,
22
+ `path` text NOT NULL,
23
+ `uploaded_by` text,
24
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
25
+ FOREIGN KEY (`todo_id`) REFERENCES `todos`(`id`) ON UPDATE no action ON DELETE cascade
26
+ );
27
+ --> statement-breakpoint
28
+ CREATE TABLE `notifications` (
29
+ `id` text PRIMARY KEY NOT NULL,
30
+ `type` text NOT NULL,
31
+ `title` text NOT NULL,
32
+ `message` text NOT NULL,
33
+ `read` integer DEFAULT false NOT NULL,
34
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
35
+ );
36
+ --> statement-breakpoint
37
+ CREATE INDEX `notifications_created_at_idx` ON `notifications` (`created_at`);--> statement-breakpoint
38
+ CREATE TABLE `permissions` (
39
+ `id` text PRIMARY KEY NOT NULL,
40
+ `code` text NOT NULL,
41
+ `name` text NOT NULL,
42
+ `label` text NOT NULL,
43
+ `category` text NOT NULL,
44
+ `description` text,
45
+ `sort_order` integer DEFAULT 0,
46
+ `is_active` integer DEFAULT true,
47
+ `created_at` integer,
48
+ `updated_at` integer
49
+ );
50
+ --> statement-breakpoint
51
+ CREATE UNIQUE INDEX `permissions_code_unique` ON `permissions` (`code`);--> statement-breakpoint
52
+ CREATE TABLE `roles` (
53
+ `id` text PRIMARY KEY NOT NULL,
54
+ `code` text NOT NULL,
55
+ `name` text NOT NULL,
56
+ `label` text NOT NULL,
57
+ `description` text,
58
+ `is_system` integer DEFAULT false,
59
+ `is_active` integer DEFAULT true,
60
+ `sort_order` integer DEFAULT 0,
61
+ `created_at` integer,
62
+ `updated_at` integer
63
+ );
64
+ --> statement-breakpoint
65
+ CREATE UNIQUE INDEX `roles_code_unique` ON `roles` (`code`);--> statement-breakpoint
66
+ CREATE TABLE `role_permissions` (
67
+ `role_id` text NOT NULL,
68
+ `permission_id` text NOT NULL,
69
+ `created_at` integer,
70
+ PRIMARY KEY(`role_id`, `permission_id`),
71
+ FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON UPDATE no action ON DELETE cascade,
72
+ FOREIGN KEY (`permission_id`) REFERENCES `permissions`(`id`) ON UPDATE no action ON DELETE cascade
73
+ );
74
+ --> statement-breakpoint
75
+ CREATE TABLE `user_roles` (
76
+ `id` text PRIMARY KEY NOT NULL,
77
+ `user_id` text NOT NULL,
78
+ `role_id` text NOT NULL,
79
+ `assigned_by` text,
80
+ `assigned_at` integer,
81
+ `expires_at` integer,
82
+ `is_active` integer DEFAULT true,
83
+ FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON UPDATE no action ON DELETE cascade
84
+ );
85
+ --> statement-breakpoint
86
+ CREATE TABLE `routes` (
87
+ `id` text PRIMARY KEY NOT NULL,
88
+ `path` text NOT NULL,
89
+ `method` text NOT NULL,
90
+ `name` text,
91
+ `description` text,
92
+ `module` text,
93
+ `is_public` integer DEFAULT false,
94
+ `is_active` integer DEFAULT true,
95
+ `created_at` integer,
96
+ `updated_at` integer
97
+ );
98
+ --> statement-breakpoint
99
+ CREATE UNIQUE INDEX `routes_path_method_unique` ON `routes` (`path`,`method`);--> statement-breakpoint
100
+ CREATE TABLE `permission_routes` (
101
+ `permission_id` text NOT NULL,
102
+ `route_id` text NOT NULL,
103
+ `created_at` integer,
104
+ PRIMARY KEY(`permission_id`, `route_id`),
105
+ FOREIGN KEY (`permission_id`) REFERENCES `permissions`(`id`) ON UPDATE no action ON DELETE cascade,
106
+ FOREIGN KEY (`route_id`) REFERENCES `routes`(`id`) ON UPDATE no action ON DELETE cascade
107
+ );
108
+ --> statement-breakpoint
109
+ CREATE TABLE `permission_audit_logs` (
110
+ `id` text PRIMARY KEY NOT NULL,
111
+ `user_id` text NOT NULL,
112
+ `action` text NOT NULL,
113
+ `resource_type` text NOT NULL,
114
+ `resource_id` text,
115
+ `old_value` text,
116
+ `new_value` text,
117
+ `ip_address` text,
118
+ `user_agent` text,
119
+ `created_at` integer
120
+ );
121
+ --> statement-breakpoint
122
+ CREATE TABLE `orders` (
123
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
124
+ `order_no` text NOT NULL,
125
+ `customer_name` text NOT NULL,
126
+ `customer_email` text NOT NULL,
127
+ `product_name` text NOT NULL,
128
+ `amount` integer NOT NULL,
129
+ `status` text DEFAULT 'pending' NOT NULL,
130
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
131
+ `updated_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
132
+ );
133
+ --> statement-breakpoint
134
+ CREATE INDEX `orders_status_idx` ON `orders` (`status`);--> statement-breakpoint
135
+ CREATE INDEX `orders_created_at_idx` ON `orders` (`created_at`);--> statement-breakpoint
136
+ CREATE TABLE `ticket_replies` (
137
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
138
+ `ticket_id` integer NOT NULL,
139
+ `content` text NOT NULL,
140
+ `author` text NOT NULL,
141
+ `is_customer` integer DEFAULT false NOT NULL,
142
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
143
+ FOREIGN KEY (`ticket_id`) REFERENCES `tickets`(`id`) ON UPDATE no action ON DELETE cascade
144
+ );
145
+ --> statement-breakpoint
146
+ CREATE INDEX `ticket_replies_ticket_id_idx` ON `ticket_replies` (`ticket_id`);--> statement-breakpoint
147
+ CREATE TABLE `tickets` (
148
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
149
+ `ticket_no` text NOT NULL,
150
+ `customer_name` text NOT NULL,
151
+ `customer_email` text NOT NULL,
152
+ `subject` text NOT NULL,
153
+ `description` text NOT NULL,
154
+ `status` text DEFAULT 'open' NOT NULL,
155
+ `priority` text DEFAULT 'medium' NOT NULL,
156
+ `category` text NOT NULL,
157
+ `assigned_to` text,
158
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
159
+ `updated_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
160
+ );
161
+ --> statement-breakpoint
162
+ CREATE INDEX `tickets_status_idx` ON `tickets` (`status`);--> statement-breakpoint
163
+ CREATE INDEX `tickets_created_at_idx` ON `tickets` (`created_at`);--> statement-breakpoint
164
+ CREATE TABLE `disputes` (
165
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
166
+ `dispute_no` text NOT NULL,
167
+ `order_id` text NOT NULL,
168
+ `order_no` text NOT NULL,
169
+ `customer_name` text NOT NULL,
170
+ `customer_email` text NOT NULL,
171
+ `type` text NOT NULL,
172
+ `status` text DEFAULT 'pending' NOT NULL,
173
+ `description` text NOT NULL,
174
+ `resolution` text,
175
+ `amount` integer NOT NULL,
176
+ `resolved_at` integer,
177
+ `resolved_by` text,
178
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
179
+ `updated_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
180
+ );
181
+ --> statement-breakpoint
182
+ CREATE INDEX `disputes_status_idx` ON `disputes` (`status`);--> statement-breakpoint
183
+ CREATE INDEX `disputes_order_id_idx` ON `disputes` (`order_id`);--> statement-breakpoint
184
+ CREATE INDEX `disputes_created_at_idx` ON `disputes` (`created_at`);--> statement-breakpoint
185
+ CREATE TABLE `contents` (
186
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
187
+ `title` text NOT NULL,
188
+ `body` text NOT NULL,
189
+ `excerpt` text,
190
+ `category` text NOT NULL,
191
+ `tags` text,
192
+ `status` text DEFAULT 'draft' NOT NULL,
193
+ `author` text NOT NULL,
194
+ `view_count` integer DEFAULT 0 NOT NULL,
195
+ `like_count` integer DEFAULT 0 NOT NULL,
196
+ `published_at` integer,
197
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
198
+ `updated_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
199
+ );
200
+ --> statement-breakpoint
201
+ CREATE INDEX `contents_status_idx` ON `contents` (`status`);--> statement-breakpoint
202
+ CREATE INDEX `contents_category_idx` ON `contents` (`category`);--> statement-breakpoint
203
+ CREATE INDEX `contents_created_at_idx` ON `contents` (`created_at`);--> statement-breakpoint
204
+ CREATE TABLE `developers` (
205
+ `id` text PRIMARY KEY NOT NULL,
206
+ `username` text NOT NULL,
207
+ `email` text NOT NULL,
208
+ `password_hash` text NOT NULL,
209
+ `role` text DEFAULT 'developer' NOT NULL,
210
+ `api_key` text NOT NULL,
211
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
212
+ `updated_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
213
+ );
214
+ --> statement-breakpoint
215
+ CREATE UNIQUE INDEX `developers_username_unique` ON `developers` (`username`);--> statement-breakpoint
216
+ CREATE UNIQUE INDEX `developers_email_unique` ON `developers` (`email`);--> statement-breakpoint
217
+ CREATE UNIQUE INDEX `developers_api_key_unique` ON `developers` (`api_key`);--> statement-breakpoint
218
+ CREATE TABLE `plugin_categories` (
219
+ `id` text PRIMARY KEY NOT NULL,
220
+ `name` text NOT NULL,
221
+ `slug` text NOT NULL,
222
+ `description` text,
223
+ `icon` text,
224
+ `sort_order` integer DEFAULT 0 NOT NULL
225
+ );
226
+ --> statement-breakpoint
227
+ CREATE UNIQUE INDEX `plugin_categories_name_unique` ON `plugin_categories` (`name`);--> statement-breakpoint
228
+ CREATE UNIQUE INDEX `plugin_categories_slug_unique` ON `plugin_categories` (`slug`);--> statement-breakpoint
229
+ CREATE INDEX `plugin_categories_slug_idx` ON `plugin_categories` (`slug`);--> statement-breakpoint
230
+ CREATE TABLE `plugin_category_mappings` (
231
+ `plugin_id` text NOT NULL,
232
+ `category_id` text NOT NULL,
233
+ FOREIGN KEY (`plugin_id`) REFERENCES `plugins`(`id`) ON UPDATE no action ON DELETE cascade,
234
+ FOREIGN KEY (`category_id`) REFERENCES `plugin_categories`(`id`) ON UPDATE no action ON DELETE cascade
235
+ );
236
+ --> statement-breakpoint
237
+ CREATE UNIQUE INDEX `plugin_category_mapping_unique` ON `plugin_category_mappings` (`plugin_id`,`category_id`);--> statement-breakpoint
238
+ CREATE INDEX `plugin_category_mappings_category_id_idx` ON `plugin_category_mappings` (`category_id`);--> statement-breakpoint
239
+ CREATE INDEX `plugin_category_mappings_plugin_id_idx` ON `plugin_category_mappings` (`plugin_id`);--> statement-breakpoint
240
+ CREATE TABLE `plugin_reviews` (
241
+ `id` text PRIMARY KEY NOT NULL,
242
+ `plugin_id` text NOT NULL,
243
+ `user_id` text NOT NULL,
244
+ `user_name` text NOT NULL,
245
+ `rating` integer NOT NULL,
246
+ `title` text,
247
+ `content` text,
248
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
249
+ FOREIGN KEY (`plugin_id`) REFERENCES `plugins`(`id`) ON UPDATE no action ON DELETE cascade
250
+ );
251
+ --> statement-breakpoint
252
+ CREATE UNIQUE INDEX `plugin_review_user_unique` ON `plugin_reviews` (`plugin_id`,`user_id`);--> statement-breakpoint
253
+ CREATE TABLE `plugin_versions` (
254
+ `id` text PRIMARY KEY NOT NULL,
255
+ `plugin_id` text NOT NULL,
256
+ `version` text NOT NULL,
257
+ `changelog` text,
258
+ `package_url` text,
259
+ `file_size` integer,
260
+ `checksum` text,
261
+ `status` text DEFAULT 'pending' NOT NULL,
262
+ `published_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
263
+ FOREIGN KEY (`plugin_id`) REFERENCES `plugins`(`id`) ON UPDATE no action ON DELETE cascade
264
+ );
265
+ --> statement-breakpoint
266
+ CREATE UNIQUE INDEX `plugin_version_unique` ON `plugin_versions` (`plugin_id`,`version`);--> statement-breakpoint
267
+ CREATE INDEX `plugin_versions_plugin_id_idx` ON `plugin_versions` (`plugin_id`);--> statement-breakpoint
268
+ CREATE TABLE `plugins` (
269
+ `id` text PRIMARY KEY NOT NULL,
270
+ `name` text NOT NULL,
271
+ `slug` text NOT NULL,
272
+ `description` text DEFAULT '' NOT NULL,
273
+ `readme` text,
274
+ `author_id` text NOT NULL,
275
+ `author_name` text NOT NULL,
276
+ `repository_url` text,
277
+ `homepage_url` text,
278
+ `npm_package` text,
279
+ `license` text,
280
+ `version` text DEFAULT '0.0.1' NOT NULL,
281
+ `status` text DEFAULT 'pending' NOT NULL,
282
+ `download_count` integer DEFAULT 0 NOT NULL,
283
+ `view_count` integer DEFAULT 0 NOT NULL,
284
+ `featured` integer DEFAULT false NOT NULL,
285
+ `screenshot_url` text,
286
+ `site_urls` text,
287
+ `tags` text,
288
+ `commands` text,
289
+ `reject_reason` text,
290
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
291
+ `updated_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
292
+ );
293
+ --> statement-breakpoint
294
+ CREATE UNIQUE INDEX `plugins_slug_unique` ON `plugins` (`slug`);--> statement-breakpoint
295
+ CREATE INDEX `plugins_status_idx` ON `plugins` (`status`);--> statement-breakpoint
296
+ CREATE INDEX `plugins_slug_idx` ON `plugins` (`slug`);--> statement-breakpoint
297
+ CREATE INDEX `plugins_author_id_idx` ON `plugins` (`author_id`);--> statement-breakpoint
298
+ CREATE INDEX `plugins_created_at_idx` ON `plugins` (`created_at`);--> statement-breakpoint
299
+ CREATE TABLE `tenants` (
300
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
301
+ `name` text NOT NULL,
302
+ `slug` text NOT NULL,
303
+ `status` text DEFAULT 'trial' NOT NULL,
304
+ `plan` text DEFAULT 'free' NOT NULL,
305
+ `max_users` integer DEFAULT 5 NOT NULL,
306
+ `settings` text,
307
+ `created_at` text NOT NULL,
308
+ `updated_at` text NOT NULL
309
+ );
310
+ --> statement-breakpoint
311
+ CREATE UNIQUE INDEX `tenants_slug_unique` ON `tenants` (`slug`);--> statement-breakpoint
312
+ CREATE TABLE `tenant_roles` (
313
+ `id` text PRIMARY KEY NOT NULL,
314
+ `tenant_id` integer NOT NULL,
315
+ `code` text NOT NULL,
316
+ `name` text NOT NULL,
317
+ `label` text NOT NULL,
318
+ `description` text,
319
+ `permissions` text NOT NULL,
320
+ `is_system` integer DEFAULT false NOT NULL,
321
+ `is_active` integer DEFAULT true NOT NULL,
322
+ `sort_order` integer DEFAULT 0 NOT NULL,
323
+ `created_at` text NOT NULL,
324
+ `updated_at` text NOT NULL,
325
+ FOREIGN KEY (`tenant_id`) REFERENCES `tenants`(`id`) ON UPDATE no action ON DELETE cascade
326
+ );
327
+ --> statement-breakpoint
328
+ CREATE UNIQUE INDEX `tenant_roles_tenant_id_code_unique` ON `tenant_roles` (`tenant_id`,`code`);--> statement-breakpoint
329
+ CREATE TABLE `tenant_members` (
330
+ `id` text PRIMARY KEY NOT NULL,
331
+ `tenant_id` integer NOT NULL,
332
+ `user_id` text NOT NULL,
333
+ `role_id` text NOT NULL,
334
+ `status` text DEFAULT 'active' NOT NULL,
335
+ `invited_by` text,
336
+ `invited_at` text,
337
+ `joined_at` text NOT NULL,
338
+ `last_active_at` text,
339
+ FOREIGN KEY (`tenant_id`) REFERENCES `tenants`(`id`) ON UPDATE no action ON DELETE cascade,
340
+ FOREIGN KEY (`role_id`) REFERENCES `tenant_roles`(`id`) ON UPDATE no action ON DELETE cascade
341
+ );
342
+ --> statement-breakpoint
343
+ CREATE UNIQUE INDEX `tenant_members_user_id_tenant_id_unique` ON `tenant_members` (`user_id`,`tenant_id`);--> statement-breakpoint
344
+ CREATE TABLE `tenant_invitations` (
345
+ `id` text PRIMARY KEY NOT NULL,
346
+ `tenant_id` integer NOT NULL,
347
+ `email` text NOT NULL,
348
+ `role_id` text NOT NULL,
349
+ `inviter_id` text NOT NULL,
350
+ `token` text NOT NULL,
351
+ `status` text DEFAULT 'pending' NOT NULL,
352
+ `expires_at` text NOT NULL,
353
+ `accepted_at` text,
354
+ `created_at` text NOT NULL,
355
+ FOREIGN KEY (`tenant_id`) REFERENCES `tenants`(`id`) ON UPDATE no action ON DELETE cascade,
356
+ FOREIGN KEY (`role_id`) REFERENCES `tenant_roles`(`id`) ON UPDATE no action ON DELETE cascade
357
+ );
358
+ --> statement-breakpoint
359
+ CREATE UNIQUE INDEX `tenant_invitations_token_unique` ON `tenant_invitations` (`token`);--> statement-breakpoint
360
+ CREATE TABLE `merchants` (
361
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
362
+ `user_id` text NOT NULL,
363
+ `tenant_id` integer NOT NULL,
364
+ `business_name` text NOT NULL,
365
+ `business_type` text DEFAULT 'retail' NOT NULL,
366
+ `status` text DEFAULT 'active' NOT NULL,
367
+ `description` text,
368
+ `phone` text,
369
+ `email` text,
370
+ `address` text,
371
+ `password` text NOT NULL,
372
+ `created_at` text NOT NULL,
373
+ `updated_at` text NOT NULL
374
+ );
375
+ --> statement-breakpoint
376
+ CREATE TABLE `products` (
377
+ `id` text PRIMARY KEY NOT NULL,
378
+ `name` text NOT NULL,
379
+ `description` text,
380
+ `price` integer NOT NULL,
381
+ `status` text DEFAULT 'active' NOT NULL,
382
+ `stock` integer DEFAULT 0 NOT NULL,
383
+ `image_url` text,
384
+ `merchant_id` integer NOT NULL,
385
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
386
+ `updated_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
387
+ );
388
+ --> statement-breakpoint
389
+ CREATE INDEX `products_status_idx` ON `products` (`status`);--> statement-breakpoint
390
+ CREATE INDEX `products_merchant_id_idx` ON `products` (`merchant_id`);