suparisma 0.0.2 → 0.0.3

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.
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ // THIS FILE IS AUTO-GENERATED - DO NOT EDIT DIRECTLY
3
+ // Edit the generator script instead: scripts/generate-realtime-hooks.ts
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ const useSuparismaUser_1 = require("./useSuparismaUser");
6
+ /**
7
+ * Main Suparisma hook object with dot notation access to all model hooks.
8
+ *
9
+ * @example
10
+ * // Get hooks for different models
11
+ * import useSuparisma from './hooks/generated';
12
+ *
13
+ * // Access user model with all hook methods
14
+ * const users = useSuparisma.user();
15
+ * const { data, loading, error } = users;
16
+ *
17
+ * // Create a new record
18
+ * await users.create({ name: "John" });
19
+ *
20
+ * // Delete a record
21
+ * await users.delete({ id: "123" });
22
+ *
23
+ * @example
24
+ * // Use with filtering and options
25
+ * const admins = useSuparisma.user({
26
+ * where: { role: 'admin' },
27
+ * orderBy: { created_at: 'desc' }
28
+ * });
29
+ */
30
+ const useSuparisma = {
31
+ user: useSuparismaUser_1.useSuparismaUser,
32
+ };
33
+ exports.default = useSuparisma;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ // THIS FILE IS AUTO-GENERATED - DO NOT EDIT DIRECTLY
3
+ // Edit the generator script instead: scripts/generate-realtime-hooks.ts
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.useSuparismaUser = void 0;
6
+ const core_1 = require("./core");
7
+ /**
8
+ * A Prisma-like hook for interacting with User records with real-time capabilities.
9
+ *
10
+ * This hook provides CRUD operations, real-time updates, and search functionality.
11
+ *
12
+ * @param options - Optional configuration options for the hook
13
+ * @returns An object with data state and methods for interacting with User records
14
+ *
15
+ * @example
16
+ * // Basic usage - get all User records with realtime updates
17
+ * const user = useSuparismaUser();
18
+ * const { data, loading, error } = user;
19
+ *
20
+ * @example
21
+ * // With filtering and ordering
22
+ * const user = useSuparismaUser({
23
+ * where: { active: true },
24
+ * orderBy: { created_at: 'desc' },
25
+ * limit: 10
26
+ * });
27
+ *
28
+ * @example
29
+ * // Create a new record
30
+ * const result = await user.create({
31
+ * name: "Example Name",
32
+ * // other fields...
33
+ * });
34
+ *
35
+ * @example
36
+ * // Update a record
37
+ * const result = await user.update({
38
+ * where: { id: "123" },
39
+ * data: { name: "Updated Name" }
40
+ * });
41
+ *
42
+ * @example
43
+ * // Delete a record
44
+ * const result = await user.delete({ id: "123" });
45
+ *
46
+ * @example
47
+ * // Find records with specific criteria
48
+ * const result = await user.findMany({
49
+ * where: { // filters },
50
+ * orderBy: { // ordering },
51
+ * take: 20 // limit
52
+ * });
53
+ */
54
+ exports.useSuparismaUser = (0, core_1.createSuparismaHook)({
55
+ tableName: 'User',
56
+ hasCreatedAt: true,
57
+ hasUpdatedAt: true,
58
+ // Default values from schema
59
+ defaultValues: { "id": "uuid(", "createdAt": "now(" }
60
+ });
package/dist/index.js CHANGED
@@ -39,12 +39,59 @@ const typeGenerator_1 = require("./generators/typeGenerator");
39
39
  const hookGenerator_1 = require("./generators/hookGenerator");
40
40
  const indexGenerator_1 = require("./generators/indexGenerator");
41
41
  const supabaseClientGenerator_1 = require("./generators/supabaseClientGenerator");
42
+ /**
43
+ * Prints the help message showing available commands
44
+ */
45
+ function printHelp() {
46
+ console.log(`
47
+ Suparisma - Typesafe React realtime CRUD hooks generator for Supabase, powered by Prisma.
48
+
49
+ Usage:
50
+ npx suparisma <command>
51
+
52
+ Commands:
53
+ generate Generate hooks based on your Prisma schema (runs in current directory)
54
+ help Show this help message
55
+
56
+ Example:
57
+ npx suparisma generate
58
+ `);
59
+ }
60
+ /**
61
+ * Checks for essential environment variables and throws an error if any are missing.
62
+ */
63
+ function checkEnvironmentVariables() {
64
+ const requiredEnvVars = [
65
+ 'DATABASE_URL',
66
+ 'NEXT_PUBLIC_SUPABASE_URL',
67
+ 'NEXT_PUBLIC_SUPABASE_ANON_KEY',
68
+ ];
69
+ const missingVars = requiredEnvVars.filter(varName => !process.env[varName]);
70
+ if (missingVars.length > 0) {
71
+ let errorMessage = 'Error: Missing required environment variables:\n';
72
+ missingVars.forEach(varName => {
73
+ errorMessage += `- ${varName}: This variable is essential for the generator to function correctly. `;
74
+ if (varName === 'DATABASE_URL') {
75
+ errorMessage += 'It is used by Prisma to connect to your database. Please ensure it is set in your .env file or as an environment variable (e.g., postgresql://user:password@host:port/database).\n';
76
+ }
77
+ else if (varName === 'NEXT_PUBLIC_SUPABASE_URL') {
78
+ errorMessage += 'This is your Supabase project URL. It is required by the Supabase client. Please set it in your .env file or as an environment variable (e.g., https://your-project-id.supabase.co).\n';
79
+ }
80
+ else if (varName === 'NEXT_PUBLIC_SUPABASE_ANON_KEY') {
81
+ errorMessage += 'This is your Supabase project public anonymous key. It is required by the Supabase client. Please set it in your .env file or as an environment variable.\n';
82
+ }
83
+ });
84
+ errorMessage += '\nPlease add these variables to your .env file or ensure they are available in your environment and try again.';
85
+ throw new Error(errorMessage);
86
+ }
87
+ console.log('✅ All required environment variables are set.');
88
+ }
42
89
  function analyzePrismaSchema(schemaPath) {
43
90
  try {
44
91
  const schemaContent = fs_1.default.readFileSync(schemaPath, 'utf8');
45
92
  const modelInfos = [];
46
93
  // Regular expression to match model definitions with comments
47
- const modelRegex = /(?:\/\/\s*@enableRealtime\s*)?\s*model\s+(\w+)\s*{([\s\S]*?)}/g;
94
+ const modelRegex = /(?:\/\/\s*@disableRealtime\s*)?\s*model\s+(\w+)\s*{([\s\S]*?)}/g;
48
95
  let modelMatch;
49
96
  while ((modelMatch = modelRegex.exec(schemaContent)) !== null) {
50
97
  const modelName = modelMatch[1];
@@ -56,8 +103,9 @@ function analyzePrismaSchema(schemaPath) {
56
103
  const tableName = modelMatch[0].includes('@map')
57
104
  ? modelMatch[0].match(/@map\s*\(\s*["'](.+?)["']\s*\)/)?.at(1) || modelName
58
105
  : modelName;
59
- // Check if model has @enableRealtime comment
60
- const enableRealtime = modelMatch[0].includes('// @enableRealtime');
106
+ // Check if model has @disableRealtime comment
107
+ // Default is to enable realtime unless explicitly disabled
108
+ const enableRealtime = !modelMatch[0].includes('// @disableRealtime');
61
109
  // Find fields with @enableSearch comment
62
110
  const searchFields = [];
63
111
  const fieldRegex = /(\w+)\s+(\w+)(?:\?.+?)?\s+(?:@.+?)?\s*(?:\/\/\s*@enableSearch)?/g;
@@ -86,7 +134,7 @@ function analyzePrismaSchema(schemaPath) {
86
134
  }
87
135
  /**
88
136
  * Configure database tables for proper realtime functionality and search
89
- * 1. Sets REPLICA IDENTITY FULL and enables realtime for models with @enableRealtime
137
+ * 1. Sets REPLICA IDENTITY FULL and enables realtime for all models (unless they have @disableRealtime)
90
138
  * 2. Creates search functions for fields with @enableSearch
91
139
  */
92
140
  async function configurePrismaTablesForSuparisma(schemaPath) {
@@ -98,8 +146,7 @@ async function configurePrismaTablesForSuparisma(schemaPath) {
98
146
  // Get direct PostgreSQL connection URL
99
147
  const directUrl = process.env.DIRECT_URL;
100
148
  if (!directUrl) {
101
- console.warn('⚠️ DIRECT_URL environment variable not found. Skipping database configuration.');
102
- return;
149
+ throw new Error(' Error: DIRECT_URL environment variable not found. This is required for database configuration (e.g., setting up realtime). Please define it in your .env file or as an environment variable and try again. This should be a direct PostgreSQL connection string.\n');
103
150
  }
104
151
  // Analyze Prisma schema for models, realtime and search annotations
105
152
  const modelInfos = analyzePrismaSchema(schemaPath);
@@ -129,6 +176,7 @@ async function configurePrismaTablesForSuparisma(schemaPath) {
129
176
  // Use the exact case of the table as it exists in the database
130
177
  const actualTableName = matchingTable.table_name;
131
178
  console.log(`🔍 Model ${model.name} -> Actual table: ${actualTableName}`);
179
+ console.log(`ℹ️ Model ${model.name}: enableRealtime is ${model.enableRealtime}`);
132
180
  if (model.enableRealtime) {
133
181
  // Explicitly use double quotes for mixed case identifiers
134
182
  // try {
@@ -138,10 +186,10 @@ async function configurePrismaTablesForSuparisma(schemaPath) {
138
186
  // console.error(`❌ Failed to set REPLICA IDENTITY on "${actualTableName}": ${err.message}`);
139
187
  // }
140
188
  // Directly add the table to Supabase Realtime publication
189
+ const alterPublicationQuery = `ALTER PUBLICATION supabase_realtime ADD TABLE "${actualTableName}";`;
190
+ console.log(`ℹ️ Executing SQL: ${alterPublicationQuery}`);
141
191
  try {
142
- await pool.query(`
143
- ALTER PUBLICATION supabase_realtime ADD TABLE "${actualTableName}";
144
- `);
192
+ await pool.query(alterPublicationQuery);
145
193
  console.log(`✅ Added "${actualTableName}" to supabase_realtime publication`);
146
194
  }
147
195
  catch (err) {
@@ -150,7 +198,7 @@ async function configurePrismaTablesForSuparisma(schemaPath) {
150
198
  console.log(`ℹ️ Table "${actualTableName}" was already in supabase_realtime publication`);
151
199
  }
152
200
  else {
153
- console.error(`❌ Failed to add "${actualTableName}" to supabase_realtime: ${err.message}`);
201
+ console.error(`❌ Failed to add "${actualTableName}" to supabase_realtime. Full error:`, err);
154
202
  }
155
203
  }
156
204
  }
@@ -222,38 +270,68 @@ async function configurePrismaTablesForSuparisma(schemaPath) {
222
270
  }
223
271
  }
224
272
  /**
225
- * Main execution function
273
+ * Main execution function for hook generation
226
274
  */
227
- async function main() {
275
+ async function generateHooks() {
228
276
  try {
229
- console.log('Generating Supabase realtime hooks with improved architecture...');
230
- // Ensure output directory exists
231
- if (!fs_1.default.existsSync(config_1.OUTPUT_DIR)) {
232
- fs_1.default.mkdirSync(config_1.OUTPUT_DIR, { recursive: true });
277
+ console.log('🚀 Starting Suparisma hook generation...');
278
+ checkEnvironmentVariables();
279
+ console.log(`Prisma schema path: ${config_1.PRISMA_SCHEMA_PATH}`);
280
+ console.log(`Output directory: ${config_1.OUTPUT_DIR}`);
281
+ // Delete the entire output directory if it exists to clean up any stale files
282
+ if (fs_1.default.existsSync(config_1.OUTPUT_DIR)) {
283
+ console.log(`🧹 Cleaning up previous generated files in ${config_1.OUTPUT_DIR}...`);
284
+ fs_1.default.rmSync(config_1.OUTPUT_DIR, { recursive: true, force: true });
285
+ console.log(`✅ Removed previous generated directory`);
233
286
  }
234
- // Generate Supabase client file first
287
+ // Ensure all specific output directories exist, OUTPUT_DIR is the root and will be created if needed by sub-creations.
288
+ const dirsToEnsure = [config_1.TYPES_DIR, config_1.HOOKS_DIR, config_1.UTILS_DIR];
289
+ dirsToEnsure.forEach(dir => {
290
+ if (!fs_1.default.existsSync(dir)) {
291
+ fs_1.default.mkdirSync(dir, { recursive: true });
292
+ console.log(`Created directory: ${dir}`);
293
+ }
294
+ });
295
+ // Generate Supabase client file (goes to UTILS_DIR)
235
296
  (0, supabaseClientGenerator_1.generateSupabaseClientFile)();
236
- // First, generate the core hook factory
297
+ // Generate the core hook factory (goes to UTILS_DIR)
237
298
  (0, coreGenerator_1.generateCoreFile)();
238
- // Parse models from Prisma schema
239
299
  const models = (0, parser_1.parsePrismaSchema)(config_1.PRISMA_SCHEMA_PATH);
240
- // Configure database tables for real-time and search functionality
241
300
  await configurePrismaTablesForSuparisma(config_1.PRISMA_SCHEMA_PATH);
242
- // Generate type definitions and hooks for each model
243
301
  const modelInfos = [];
244
302
  for (const model of models) {
245
303
  const modelInfo = (0, typeGenerator_1.generateModelTypesFile)(model);
246
304
  (0, hookGenerator_1.generateModelHookFile)(modelInfo);
247
305
  modelInfos.push(modelInfo);
248
306
  }
249
- // Generate the main module file
250
307
  (0, indexGenerator_1.generateMainIndexFile)(modelInfos);
251
- console.log('✅ Successfully generated all suparisma hooks!');
308
+ console.log(`✅ Successfully generated all suparisma hooks and types in "${config_1.OUTPUT_DIR}"!`);
252
309
  }
253
310
  catch (error) {
254
311
  console.error('❌ Error generating hooks:', error);
255
312
  process.exit(1);
256
313
  }
257
314
  }
258
- // Execute main function
259
- main();
315
+ /**
316
+ * Main CLI entry point
317
+ */
318
+ function run() {
319
+ const args = process.argv.slice(2);
320
+ const command = args[0];
321
+ switch (command) {
322
+ case 'generate':
323
+ generateHooks();
324
+ break;
325
+ case 'help':
326
+ case '--help':
327
+ case '-h':
328
+ printHelp();
329
+ break;
330
+ default:
331
+ console.log(`Unknown command: ${command}`);
332
+ printHelp();
333
+ process.exit(1);
334
+ }
335
+ }
336
+ // Execute the CLI command
337
+ run();
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ // THIS FILE IS AUTO-GENERATED - DO NOT EDIT DIRECTLY
3
+ // Edit the generator script instead: scripts/generate-realtime-hooks.ts
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.useSuparismaUser = void 0;
6
+ // Corrected import for core hook factory
7
+ const core_1 = require("../utils/core");
8
+ /**
9
+ * A Prisma-like hook for interacting with User records with real-time capabilities.
10
+ *
11
+ * This hook provides CRUD operations, real-time updates, and search functionality.
12
+ *
13
+ * @param options - Optional configuration options for the hook
14
+ * @returns An object with data state and methods for interacting with User records
15
+ *
16
+ * @example
17
+ * // Basic usage - get all User records with realtime updates
18
+ * const user = useSuparismaUser();
19
+ * const { data, loading, error } = user;
20
+ *
21
+ * @example
22
+ * // With filtering and ordering
23
+ * const user = useSuparismaUser({
24
+ * where: { active: true },
25
+ * orderBy: { created_at: 'desc' },
26
+ * limit: 10
27
+ * });
28
+ *
29
+ * @example
30
+ * // Create a new record
31
+ * const result = await user.create({
32
+ * name: "Example Name",
33
+ * // other fields...
34
+ * });
35
+ *
36
+ * @example
37
+ * // Update a record
38
+ * const result = await user.update({
39
+ * where: { id: "123" },
40
+ * data: { name: "Updated Name" }
41
+ * });
42
+ *
43
+ * @example
44
+ * // Delete a record
45
+ * const result = await user.delete({ id: "123" });
46
+ *
47
+ * @example
48
+ * // Find records with specific criteria
49
+ * const result = await user.findMany({
50
+ * where: { // filters },
51
+ * orderBy: { // ordering },
52
+ * take: 20 // limit
53
+ * });
54
+ */
55
+ exports.useSuparismaUser = (0, core_1.createSuparismaHook)({
56
+ tableName: 'User',
57
+ hasCreatedAt: true,
58
+ hasUpdatedAt: true,
59
+ // Default values from schema
60
+ defaultValues: { "id": "uuid(", "createdAt": "now(" }
61
+ });
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ // THIS FILE IS AUTO-GENERATED - DO NOT EDIT DIRECTLY
3
+ // Edit the generator script instead: scripts/generate-realtime-hooks.ts
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ const useSuparismaUser_1 = require("./hooks/useSuparismaUser");
6
+ /**
7
+ * Main Suparisma hook object with dot notation access to all model hooks.
8
+ *
9
+ * @example
10
+ * // Get hooks for different models
11
+ * import useSuparisma from './your-output-dir'; // e.g., from './suparisma/generated'
12
+ *
13
+ * // Access user model with all hook methods
14
+ * const users = useSuparisma.user();
15
+ * const { data, loading, error } = users;
16
+ *
17
+ * // Create a new record
18
+ * await users.create({ name: "John" });
19
+ *
20
+ * // Delete a record
21
+ * await users.delete({ id: "123" });
22
+ *
23
+ * @example
24
+ * // Use with filtering and options
25
+ * const admins = useSuparisma.user({
26
+ * where: { role: 'admin' },
27
+ * orderBy: { created_at: 'desc' }
28
+ * });
29
+ */
30
+ const useSuparisma = {
31
+ user: useSuparismaUser_1.useSuparismaUser,
32
+ };
33
+ exports.default = useSuparisma;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // THIS FILE IS AUTO-GENERATED - DO NOT EDIT DIRECTLY
3
+ // Edit the generator script instead
4
+ Object.defineProperty(exports, "__esModule", { value: true });