sitepaige-mcp-server 1.1.0 → 1.2.1

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 (51) hide show
  1. package/components/headerlogin.tsx +10 -28
  2. package/components/profile.tsx +302 -46
  3. package/components/slideshow.tsx +1 -9
  4. package/defaultapp/api/Auth/resend-verification/route.ts +3 -3
  5. package/defaultapp/api/Auth/route.ts +2 -2
  6. package/defaultapp/api/Auth/signup/route.ts +3 -3
  7. package/defaultapp/api/Auth/verify-email/route.ts +5 -5
  8. package/defaultapp/api/admin/users/route.ts +3 -3
  9. package/defaultapp/{db-users.ts → api/db-users.ts} +1 -1
  10. package/defaultapp/api/profile/route.ts +154 -0
  11. package/defaultapp/profile/page.tsx +6 -0
  12. package/dist/blueprintWriter.js.map +1 -1
  13. package/dist/components/headerlogin.tsx +10 -28
  14. package/dist/components/profile.tsx +302 -46
  15. package/dist/components/slideshow.tsx +1 -9
  16. package/dist/defaultapp/api/Auth/resend-verification/route.ts +3 -3
  17. package/dist/defaultapp/api/Auth/route.ts +2 -2
  18. package/dist/defaultapp/api/Auth/signup/route.ts +3 -3
  19. package/dist/defaultapp/api/Auth/verify-email/route.ts +5 -5
  20. package/dist/defaultapp/api/admin/users/route.ts +3 -3
  21. package/dist/defaultapp/api/csrf.ts +111 -0
  22. package/dist/defaultapp/api/db-mysql.ts +183 -0
  23. package/dist/defaultapp/api/db-password-auth.ts +362 -0
  24. package/dist/defaultapp/api/db-postgres.ts +189 -0
  25. package/dist/defaultapp/api/db-sqlite.ts +335 -0
  26. package/dist/defaultapp/api/db-users.ts +520 -0
  27. package/dist/defaultapp/api/db.ts +149 -0
  28. package/dist/defaultapp/api/profile/route.ts +154 -0
  29. package/dist/defaultapp/api/storage/email.ts +162 -0
  30. package/dist/defaultapp/api/storage/files.ts +160 -0
  31. package/dist/defaultapp/db-users.ts +1 -1
  32. package/dist/defaultapp/profile/page.tsx +6 -0
  33. package/dist/generators/env-example-template.txt +4 -3
  34. package/dist/generators/skeleton.js +3 -5
  35. package/dist/generators/skeleton.js.map +1 -1
  36. package/dist/generators/sql.js +60 -0
  37. package/dist/generators/sql.js.map +1 -1
  38. package/dist/sitepaige.js +2 -1
  39. package/dist/sitepaige.js.map +1 -1
  40. package/package.json +1 -1
  41. package/defaultapp/admin/page.tsx +0 -6
  42. package/defaultapp/api/example-secure/route.ts +0 -100
  43. package/defaultapp/migrate.ts +0 -142
  44. /package/defaultapp/{csrf.ts → api/csrf.ts} +0 -0
  45. /package/defaultapp/{db-mysql.ts → api/db-mysql.ts} +0 -0
  46. /package/defaultapp/{db-password-auth.ts → api/db-password-auth.ts} +0 -0
  47. /package/defaultapp/{db-postgres.ts → api/db-postgres.ts} +0 -0
  48. /package/defaultapp/{db-sqlite.ts → api/db-sqlite.ts} +0 -0
  49. /package/defaultapp/{db.ts → api/db.ts} +0 -0
  50. /package/defaultapp/{storage → api/storage}/email.ts +0 -0
  51. /package/defaultapp/{storage → api/storage}/files.ts +0 -0
@@ -0,0 +1,335 @@
1
+ /*
2
+ Sitepaige v1.0.0
3
+ SQLite database implementation
4
+ WARNING: This file is automatically generated and should not be modified.
5
+ */
6
+
7
+ import Database from 'better-sqlite3';
8
+ import * as path from 'path';
9
+ import * as fs from 'fs';
10
+ import { promises as fsPromises } from 'fs';
11
+ import type { Model, ModelField } from './db';
12
+
13
+ // Map to store multiple database connections by path
14
+ const dbConnections: Map<string, Database.Database> = new Map();
15
+
16
+ /**
17
+ * Get the default database path
18
+ */
19
+ function getDefaultDbPath(): string {
20
+ // First check if DATABASE_URL is provided
21
+ const databaseUrl = process.env.DATABASE_URL;
22
+ if (databaseUrl) {
23
+ // DATABASE_URL can be either a direct file path or a sqlite:// URL
24
+ if (databaseUrl.startsWith('sqlite://')) {
25
+ // Remove the sqlite:// prefix and return the path
26
+ return databaseUrl.slice(9);
27
+ } else {
28
+ // Assume it's a direct file path
29
+ return databaseUrl;
30
+ }
31
+ }
32
+
33
+ // Use EFS_MOUNT_PATH for production (in container with EFS)
34
+ // Use SQLITE_DIR for local development
35
+ const efsMountPath = process.env.EFS_MOUNT_PATH;
36
+ const sqliteDir = process.env.SQLITE_DIR || '.';
37
+
38
+ if (efsMountPath) {
39
+ // In production with EFS
40
+ return path.join(efsMountPath, 'data', 'app.db');
41
+ } else {
42
+ // In local development
43
+ return path.join(sqliteDir, 'app.db');
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Initialize database connection
49
+ * Uses DATABASE_URL if provided, otherwise uses default database path based on
50
+ * EFS_MOUNT_PATH (production) or SQLITE_DIR (development).
51
+ * If the file doesn't exist, it will be created automatically.
52
+ * @returns Database client
53
+ */
54
+ export async function db_init(): Promise<Database.Database> {
55
+
56
+
57
+ // Always use the default path - no parameter needed
58
+ const actualPath = getDefaultDbPath();
59
+
60
+ // Check if we already have a connection to this database
61
+ const existingConnection = dbConnections.get(actualPath);
62
+ if (existingConnection) {
63
+ return existingConnection;
64
+ }
65
+
66
+ try {
67
+ // Ensure the directory exists (using async method)
68
+ const dir = path.dirname(actualPath);
69
+ if (dir && dir !== '.' && dir !== '/') {
70
+ await fsPromises.mkdir(dir, { recursive: true });
71
+ }
72
+
73
+ // Create database connection (SQLite will create the file if it doesn't exist)
74
+ const newDb = new Database(actualPath);
75
+
76
+ // Enable foreign keys for proper constraint enforcement
77
+ newDb.pragma('foreign_keys = ON');
78
+
79
+ // Store the connection
80
+ dbConnections.set(actualPath, newDb);
81
+
82
+ return newDb;
83
+ } catch (error) {
84
+ throw error;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Execute a SQL query using the provided SQLite database client
90
+ * @param client Database client from db_init()
91
+ * @param query SQL query string (SQLite syntax with ? parameter placeholders)
92
+ * @param params Optional array of parameters for the query
93
+ * @returns Array of selected rows or execution results
94
+ */
95
+ export async function db_query(
96
+ client: Database.Database,
97
+ query: string,
98
+ params?: any[]
99
+ ): Promise<any[]> {
100
+
101
+
102
+ try {
103
+ // Convert booleans to integers for SQLite3 compatibility
104
+ const queryParams = (params || []).map(param =>
105
+ typeof param === 'boolean' ? (param ? 1 : 0) : param
106
+ );
107
+
108
+ // Check if the query contains multiple statements (separated by semicolons)
109
+ const statements = query.split(';').map(s => s.trim()).filter(s => s.length > 0);
110
+
111
+ if (statements.length > 1) {
112
+ // Handle multiple statements
113
+ const results: any[] = [];
114
+
115
+ for (const statement of statements) {
116
+ const queryType = statement.trim().toUpperCase().split(' ')[0];
117
+
118
+ if (queryType === 'SELECT') {
119
+ // For SELECT queries, return results array
120
+ const stmt = client.prepare(statement);
121
+ const stmtResults = stmt.all(...queryParams);
122
+ results.push(...stmtResults);
123
+ } else {
124
+ // For INSERT, UPDATE, DELETE queries, execute and return info
125
+ const stmt = client.prepare(statement);
126
+ const result = stmt.run(...queryParams);
127
+
128
+ // Add standardized result info
129
+ results.push({
130
+ changes: result.changes,
131
+ lastInsertRowid: result.lastInsertRowid
132
+ });
133
+ }
134
+ }
135
+
136
+ return results;
137
+ } else {
138
+ // Handle single statement (original logic)
139
+ const singleQuery = statements[0] || query.trim();
140
+ const queryType = singleQuery.trim().toUpperCase().split(' ')[0];
141
+
142
+ if (queryType === 'SELECT') {
143
+ // For SELECT queries, return results array
144
+ const stmt = client.prepare(singleQuery);
145
+ const results = stmt.all(...queryParams);
146
+ return results;
147
+ } else {
148
+ // For INSERT, UPDATE, DELETE queries, execute and return info
149
+ const stmt = client.prepare(singleQuery);
150
+ const result = stmt.run(...queryParams);
151
+
152
+ // Return standardized result info
153
+ return [{
154
+ changes: result.changes,
155
+ lastInsertRowid: result.lastInsertRowid
156
+ }];
157
+ }
158
+ }
159
+
160
+ } catch (error) {
161
+ // If table doesn't exist for SELECT, return empty array
162
+ if (error instanceof Error && error.message.includes('no such table') && query.trim().toUpperCase().startsWith('SELECT')) {
163
+ return [];
164
+ }
165
+ throw error;
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Generates a CREATE TABLE SQL string for the specified table and fields
171
+ * @param model The model definition
172
+ * @param dbType Database type (for compatibility, not used in SQLite)
173
+ * @returns SQL string for creating the table
174
+ */
175
+ export function db_migrate(model: Model, dbType: string): string {
176
+ // Special handling for auth tables - create them first
177
+
178
+ const sanitizedTableName = model.name.toLowerCase().replace(/\s+/g, '_');
179
+
180
+ // Start with the model's fields
181
+ let fields = [...model.fields];
182
+
183
+ // Add userid field if data is user specific
184
+ if (model.data_is_user_specific === "true") {
185
+ fields.push({
186
+ name: 'userid',
187
+ datatype: 'TEXT',
188
+ datatypesize: null,
189
+ key: 'foreign',
190
+ required: 'true',
191
+ default: undefined
192
+ });
193
+ }
194
+
195
+ // Map SQL data types for SQLite
196
+ const sqlTypeMap: { [key: string]: string } = {
197
+ 'UUID': 'TEXT',
198
+ 'TINYINT': 'INTEGER',
199
+ 'SMALLINT': 'INTEGER',
200
+ 'BIGINT': 'INTEGER',
201
+ 'INT128': 'TEXT',
202
+ 'VARCHAR': 'TEXT',
203
+ 'TEXT': 'TEXT',
204
+ 'BINARY': 'BLOB',
205
+ 'DATE': 'TEXT',
206
+ 'TIME': 'TEXT',
207
+ 'DATETIME': 'TEXT',
208
+ 'DOUBLE': 'REAL',
209
+ 'FLOAT': 'REAL',
210
+ 'BOOLEAN': 'INTEGER'
211
+ };
212
+
213
+ // Build column definitions
214
+ const columnDefs = fields.sort((a, b) => (b.key === 'primary' ? 1 : 0) - (a.key === 'primary' ? 1 : 0)).map(field => {
215
+ let def = `"${field.name}" ${sqlTypeMap[field.datatype.toUpperCase()]}`;
216
+
217
+ // Add NOT NULL if required
218
+ if (field.required === "true") {
219
+ def += ' NOT NULL';
220
+ }
221
+
222
+ // Add default if specified
223
+ if (field.default !== undefined) {
224
+ if (field.datatype === 'VARCHAR' || field.datatype === 'TEXT') {
225
+ def += ` DEFAULT '${field.default}'`;
226
+ } else {
227
+ def += ` DEFAULT ${field.default}`;
228
+ }
229
+ }
230
+
231
+ // Add primary key constraint
232
+ if (field.key === 'primary') {
233
+ def += ' PRIMARY KEY';
234
+ }
235
+
236
+ return def;
237
+ }).join(',\n ');
238
+
239
+ // Build the CREATE TABLE statement
240
+ const sql = `CREATE TABLE IF NOT EXISTS "${sanitizedTableName}" (\n ${columnDefs}\n);`;
241
+
242
+ return sql;
243
+ }
244
+
245
+ /**
246
+ * Get or create a database connection for the specified path
247
+ * This is a convenience wrapper for working with arbitrary database files
248
+ * Note: For the main application database, use db_init() instead
249
+ * @param dbPath Path to the database file (including database name)
250
+ * @returns Database client ready for use
251
+ */
252
+ export async function getDatabase(dbPath: string): Promise<Database.Database> {
253
+ // Skip database operations during build time
254
+ if (typeof window === 'undefined' && !process.env.HOSTNAME && process.env.NODE_ENV === 'production') {
255
+ return {} as Database.Database;
256
+ }
257
+
258
+ // Check if we already have a connection to this database
259
+ const existingConnection = dbConnections.get(dbPath);
260
+ if (existingConnection) {
261
+ return existingConnection;
262
+ }
263
+
264
+ try {
265
+ // Ensure the directory exists (using async method)
266
+ const dir = path.dirname(dbPath);
267
+ if (dir && dir !== '.' && dir !== '/') {
268
+ await fsPromises.mkdir(dir, { recursive: true });
269
+ }
270
+
271
+ // Create database connection
272
+ const newDb = new Database(dbPath);
273
+ newDb.pragma('foreign_keys = ON');
274
+ dbConnections.set(dbPath, newDb);
275
+
276
+ return newDb;
277
+ } catch (error) {
278
+ throw error;
279
+ }
280
+ }
281
+
282
+ /**
283
+ * Check if a database file exists at the specified path
284
+ * @param dbPath Path to the database file
285
+ * @returns true if the database file exists, false otherwise
286
+ */
287
+ export async function databaseExists(dbPath: string): Promise<boolean> {
288
+ try {
289
+ await fsPromises.access(dbPath, fs.constants.F_OK);
290
+ return true;
291
+ } catch (error) {
292
+ return false;
293
+ }
294
+ }
295
+
296
+ /**
297
+ * Get information about the database at the specified path
298
+ * @param dbPath Path to the database file
299
+ * @returns Object with database information or null if database doesn't exist
300
+ */
301
+ export async function getDatabaseInfo(dbPath: string): Promise<{
302
+ exists: boolean;
303
+ tables?: string[];
304
+ size?: number;
305
+ } | null> {
306
+ // Skip during build time
307
+ if (typeof window === 'undefined' && !process.env.HOSTNAME && process.env.NODE_ENV === 'production') {
308
+ return { exists: false };
309
+ }
310
+
311
+ const exists = await databaseExists(dbPath);
312
+
313
+ if (!exists) {
314
+ return { exists: false };
315
+ }
316
+
317
+ try {
318
+ const stats = await fsPromises.stat(dbPath);
319
+ const client = await getDatabase(dbPath);
320
+
321
+ // Get list of tables
322
+ const tables = await db_query(
323
+ client,
324
+ "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"
325
+ );
326
+
327
+ return {
328
+ exists: true,
329
+ tables: tables.map(t => t.name),
330
+ size: stats.size
331
+ };
332
+ } catch (error) {
333
+ return null;
334
+ }
335
+ }