suparisma 1.0.8 โ 1.0.9
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/README.md +1 -1
- package/dist/generators/coreGenerator.js +7 -32
- package/dist/generators/hookGenerator.js +0 -1
- package/dist/generators/indexGenerator.js +0 -1
- package/dist/generators/supabaseClientGenerator.js +0 -1
- package/dist/generators/typeGenerator.js +0 -1
- package/dist/index.js +2 -42
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1166,7 +1166,7 @@ async function handleSubmit(event) {
|
|
|
1166
1166
|
name: formData.name,
|
|
1167
1167
|
someNumber: parseInt(formData.number)
|
|
1168
1168
|
});
|
|
1169
|
-
|
|
1169
|
+
// Handle successful creation
|
|
1170
1170
|
} catch (err) {
|
|
1171
1171
|
console.error('Failed to create thing:', err);
|
|
1172
1172
|
}
|
|
@@ -711,7 +711,6 @@ function clientSideFilterCheck<T>(record: any, where: T): boolean {
|
|
|
711
711
|
}
|
|
712
712
|
}
|
|
713
713
|
} else if (record[key as keyof typeof record] !== value) {
|
|
714
|
-
console.log(\`Filter mismatch on \${key}\`, { expected: value, actual: record[key as keyof typeof record] });
|
|
715
714
|
return false;
|
|
716
715
|
}
|
|
717
716
|
}
|
|
@@ -1225,18 +1224,15 @@ export function createSuparismaHook<
|
|
|
1225
1224
|
|
|
1226
1225
|
if (hasComplexArrayFilters) {
|
|
1227
1226
|
// Don't include filter at all for complex array operations
|
|
1228
|
-
console.log(\`Setting up subscription for \${tableName} with NO FILTER (complex array filters detected) - will receive ALL events\`);
|
|
1229
1227
|
} else if (where) {
|
|
1230
1228
|
// Include filter for simple operations
|
|
1231
1229
|
const filter = buildFilterString(where);
|
|
1232
1230
|
if (filter) {
|
|
1233
1231
|
subscriptionConfig.filter = filter;
|
|
1234
1232
|
}
|
|
1235
|
-
console.log(\`Setting up subscription for \${tableName} with database filter: \${filter}\`);
|
|
1236
1233
|
} else if (realtimeFilter) {
|
|
1237
1234
|
// Use custom realtime filter if provided
|
|
1238
1235
|
subscriptionConfig.filter = realtimeFilter;
|
|
1239
|
-
console.log(\`Setting up subscription for \${tableName} with custom filter: \${realtimeFilter}\`);
|
|
1240
1236
|
}
|
|
1241
1237
|
|
|
1242
1238
|
const channel = supabase
|
|
@@ -1245,7 +1241,6 @@ export function createSuparismaHook<
|
|
|
1245
1241
|
'postgres_changes',
|
|
1246
1242
|
subscriptionConfig,
|
|
1247
1243
|
(payload) => {
|
|
1248
|
-
console.log(\`๐ฅ REALTIME EVENT RECEIVED for \${tableName}:\`, payload.eventType, payload);
|
|
1249
1244
|
|
|
1250
1245
|
// Access current options via refs inside the event handler
|
|
1251
1246
|
const currentWhere = whereRef.current;
|
|
@@ -1255,7 +1250,6 @@ export function createSuparismaHook<
|
|
|
1255
1250
|
|
|
1256
1251
|
// Skip realtime updates when search is active
|
|
1257
1252
|
if (isSearchingRef.current) {
|
|
1258
|
-
console.log('โญ๏ธ Skipping realtime update - search is active');
|
|
1259
1253
|
return;
|
|
1260
1254
|
}
|
|
1261
1255
|
|
|
@@ -1264,7 +1258,6 @@ export function createSuparismaHook<
|
|
|
1264
1258
|
setData((prev) => {
|
|
1265
1259
|
try {
|
|
1266
1260
|
const newRecord = payload.new as TWithRelations;
|
|
1267
|
-
console.log(\`Processing INSERT for \${tableName}\`, { newRecord });
|
|
1268
1261
|
|
|
1269
1262
|
// ALWAYS check if this record matches our filter client-side
|
|
1270
1263
|
// This is especially important for complex array filters
|
|
@@ -1272,7 +1265,6 @@ export function createSuparismaHook<
|
|
|
1272
1265
|
const matchesFilter = clientSideFilterCheck(newRecord, currentWhere);
|
|
1273
1266
|
|
|
1274
1267
|
if (!matchesFilter) {
|
|
1275
|
-
console.log('New record does not match filter criteria, skipping');
|
|
1276
1268
|
return prev;
|
|
1277
1269
|
}
|
|
1278
1270
|
}
|
|
@@ -1284,7 +1276,6 @@ export function createSuparismaHook<
|
|
|
1284
1276
|
);
|
|
1285
1277
|
|
|
1286
1278
|
if (exists) {
|
|
1287
|
-
console.log('Record already exists, skipping insertion');
|
|
1288
1279
|
return prev;
|
|
1289
1280
|
}
|
|
1290
1281
|
|
|
@@ -1359,7 +1350,6 @@ export function createSuparismaHook<
|
|
|
1359
1350
|
|
|
1360
1351
|
// If the updated record doesn't match the filter, remove it from the list
|
|
1361
1352
|
if (!matchesFilter) {
|
|
1362
|
-
console.log('Updated record no longer matches filter, removing from list');
|
|
1363
1353
|
return prev.filter((item) =>
|
|
1364
1354
|
// @ts-ignore: Supabase typing issue
|
|
1365
1355
|
!('id' in item && 'id' in updatedRecord && item.id === updatedRecord.id)
|
|
@@ -1418,9 +1408,7 @@ export function createSuparismaHook<
|
|
|
1418
1408
|
});
|
|
1419
1409
|
} else if (payload.eventType === 'DELETE') {
|
|
1420
1410
|
// Process delete event
|
|
1421
|
-
console.log('๐๏ธ Processing DELETE event for', tableName);
|
|
1422
1411
|
setData((prev) => {
|
|
1423
|
-
console.log('๐๏ธ DELETE: Current data before deletion:', prev.length, 'items');
|
|
1424
1412
|
|
|
1425
1413
|
// Access current options via refs
|
|
1426
1414
|
const currentWhere = whereRef.current;
|
|
@@ -1430,7 +1418,6 @@ export function createSuparismaHook<
|
|
|
1430
1418
|
|
|
1431
1419
|
// Skip if search is active
|
|
1432
1420
|
if (isSearchingRef.current) {
|
|
1433
|
-
console.log('โญ๏ธ DELETE: Skipping - search is active');
|
|
1434
1421
|
return prev;
|
|
1435
1422
|
}
|
|
1436
1423
|
|
|
@@ -1440,21 +1427,14 @@ export function createSuparismaHook<
|
|
|
1440
1427
|
// Filter out the deleted item
|
|
1441
1428
|
const filteredData = prev.filter((item) => {
|
|
1442
1429
|
// @ts-ignore: Supabase typing issue
|
|
1443
|
-
|
|
1444
|
-
if (!shouldKeep) {
|
|
1445
|
-
console.log('๐๏ธ DELETE: Removing item with ID:', item.id);
|
|
1446
|
-
}
|
|
1447
|
-
return shouldKeep;
|
|
1430
|
+
return !('id' in item && 'id' in payload.old && item.id === payload.old.id);
|
|
1448
1431
|
});
|
|
1449
1432
|
|
|
1450
|
-
console.log('๐๏ธ DELETE: Data after deletion:', filteredData.length, 'items (was', currentSize, ')');
|
|
1451
|
-
|
|
1452
1433
|
// Fetch the updated count after the data changes
|
|
1453
1434
|
setTimeout(() => fetchTotalCount(), 0);
|
|
1454
1435
|
|
|
1455
1436
|
// If we need to maintain the size with a limit
|
|
1456
1437
|
if (currentLimit && currentLimit > 0 && filteredData.length < currentSize && currentSize === currentLimit) { // Use ref value
|
|
1457
|
-
console.log(\`๐๏ธ DELETE: Record deleted with limit \${currentLimit}, will fetch additional record to maintain size\`);
|
|
1458
1438
|
|
|
1459
1439
|
// Use setTimeout to ensure this state update completes first
|
|
1460
1440
|
setTimeout(() => {
|
|
@@ -1512,19 +1492,16 @@ export function createSuparismaHook<
|
|
|
1512
1492
|
}
|
|
1513
1493
|
}
|
|
1514
1494
|
)
|
|
1515
|
-
.subscribe(
|
|
1516
|
-
console.log(\`Subscription status for \${tableName}\`, status);
|
|
1517
|
-
});
|
|
1495
|
+
.subscribe();
|
|
1518
1496
|
|
|
1519
1497
|
// Store the channel ref
|
|
1520
1498
|
channelRef.current = channel;
|
|
1521
1499
|
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
}
|
|
1500
|
+
return () => {
|
|
1501
|
+
if (channelRef.current) {
|
|
1502
|
+
supabase.removeChannel(channelRef.current); // Correct way to remove channel
|
|
1503
|
+
channelRef.current = null;
|
|
1504
|
+
}
|
|
1528
1505
|
|
|
1529
1506
|
if (searchTimeoutRef.current) {
|
|
1530
1507
|
clearTimeout(searchTimeoutRef.current);
|
|
@@ -1569,7 +1546,6 @@ export function createSuparismaHook<
|
|
|
1569
1546
|
if (initialLoadRef.current) {
|
|
1570
1547
|
// Only reload if options have changed significantly
|
|
1571
1548
|
if (optionsChanged()) {
|
|
1572
|
-
console.log(\`Options changed for \${tableName}, reloading data\`);
|
|
1573
1549
|
findMany({
|
|
1574
1550
|
where,
|
|
1575
1551
|
orderBy,
|
|
@@ -2089,5 +2065,4 @@ export function createSuparismaHook<
|
|
|
2089
2065
|
fs_1.default.mkdirSync(config_1.UTILS_DIR, { recursive: true });
|
|
2090
2066
|
}
|
|
2091
2067
|
fs_1.default.writeFileSync(outputPath, coreContent);
|
|
2092
|
-
console.log(`Generated core utility file at ${outputPath}`);
|
|
2093
2068
|
}
|
|
@@ -113,5 +113,4 @@ export const ${config_1.HOOK_NAME_PREFIX}${modelName} = createSuparismaHook<
|
|
|
113
113
|
fs_1.default.mkdirSync(config_1.HOOKS_DIR, { recursive: true });
|
|
114
114
|
}
|
|
115
115
|
fs_1.default.writeFileSync(outputPath, hookContent);
|
|
116
|
-
console.log(`Generated hook for ${modelName} at ${outputPath}`);
|
|
117
116
|
}
|
|
@@ -687,7 +687,6 @@ ${createInputProps
|
|
|
687
687
|
fs_1.default.mkdirSync(config_1.TYPES_DIR, { recursive: true });
|
|
688
688
|
}
|
|
689
689
|
fs_1.default.writeFileSync(outputPath, typeContent);
|
|
690
|
-
console.log(`Generated type definitions for ${modelName} at ${outputPath}`);
|
|
691
690
|
return {
|
|
692
691
|
modelName,
|
|
693
692
|
tableName,
|
package/dist/index.js
CHANGED
|
@@ -84,7 +84,6 @@ function checkEnvironmentVariables() {
|
|
|
84
84
|
errorMessage += '\nPlease add these variables to your .env file or ensure they are available in your environment and try again.';
|
|
85
85
|
throw new Error(errorMessage);
|
|
86
86
|
}
|
|
87
|
-
console.log('โ
All required environment variables are set.');
|
|
88
87
|
}
|
|
89
88
|
function analyzePrismaSchema(schemaPath) {
|
|
90
89
|
try {
|
|
@@ -148,8 +147,6 @@ function analyzePrismaSchema(schemaPath) {
|
|
|
148
147
|
*/
|
|
149
148
|
async function configurePrismaTablesForSuparisma(schemaPath) {
|
|
150
149
|
try {
|
|
151
|
-
// COMPLETELY BYPASS NORMAL OPERATION FOR SIMPLICITY
|
|
152
|
-
console.log('๐ง Using direct SQL approach to avoid PostgreSQL case sensitivity issues...');
|
|
153
150
|
// Load environment variables
|
|
154
151
|
dotenv.config();
|
|
155
152
|
// Get direct PostgreSQL connection URL
|
|
@@ -162,7 +159,6 @@ async function configurePrismaTablesForSuparisma(schemaPath) {
|
|
|
162
159
|
const pg = await Promise.resolve().then(() => __importStar(require('pg')));
|
|
163
160
|
const { Pool } = pg.default || pg;
|
|
164
161
|
const pool = new Pool({ connectionString: process.env.DIRECT_URL });
|
|
165
|
-
console.log('๐ Connected to PostgreSQL database for configuration.');
|
|
166
162
|
const { rows: allTables } = await pool.query(`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'`);
|
|
167
163
|
for (const model of modelInfos) {
|
|
168
164
|
const matchingTable = allTables.find((t) => t.table_name.toLowerCase() === model.tableName.toLowerCase());
|
|
@@ -171,29 +167,20 @@ async function configurePrismaTablesForSuparisma(schemaPath) {
|
|
|
171
167
|
continue;
|
|
172
168
|
}
|
|
173
169
|
const actualTableName = matchingTable.table_name;
|
|
174
|
-
console.log(`Processing model ${model.name} (table: "${actualTableName}")`);
|
|
175
170
|
// Realtime setup (existing logic)
|
|
176
171
|
if (model.enableRealtime) {
|
|
177
172
|
const alterPublicationQuery = `ALTER PUBLICATION supabase_realtime ADD TABLE "${actualTableName}";`;
|
|
178
173
|
try {
|
|
179
174
|
await pool.query(alterPublicationQuery);
|
|
180
|
-
console.log(` โ
Added "${actualTableName}" to supabase_realtime publication for real-time updates.`);
|
|
181
175
|
}
|
|
182
176
|
catch (err) {
|
|
183
|
-
if (err.message.includes('already member')) {
|
|
184
|
-
console.log(` โน๏ธ Table "${actualTableName}" was already in supabase_realtime publication.`);
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
177
|
+
if (!err.message.includes('already member')) {
|
|
187
178
|
console.error(` โ Failed to add "${actualTableName}" to supabase_realtime: ${err.message}`);
|
|
188
179
|
}
|
|
189
180
|
}
|
|
190
181
|
}
|
|
191
|
-
else {
|
|
192
|
-
console.log(` โน๏ธ Realtime disabled for model ${model.name}.`);
|
|
193
|
-
}
|
|
194
182
|
// Search setup
|
|
195
183
|
if (model.searchFields.length > 0) {
|
|
196
|
-
console.log(` ๐ Setting up full-text search for model ${model.name}:`);
|
|
197
184
|
const { rows: columns } = await pool.query(`SELECT column_name FROM information_schema.columns WHERE table_schema = 'public' AND table_name = $1`, [actualTableName]);
|
|
198
185
|
for (const searchField of model.searchFields) {
|
|
199
186
|
const matchingColumn = columns.find((c) => c.column_name.toLowerCase() === searchField.name.toLowerCase());
|
|
@@ -204,7 +191,6 @@ async function configurePrismaTablesForSuparisma(schemaPath) {
|
|
|
204
191
|
const actualColumnName = matchingColumn.column_name;
|
|
205
192
|
const functionName = `search_${actualTableName.toLowerCase()}_by_${actualColumnName.toLowerCase()}_prefix`;
|
|
206
193
|
const indexName = `idx_gin_search_${actualTableName.toLowerCase()}_${actualColumnName.toLowerCase()}`;
|
|
207
|
-
console.log(` โก๏ธ Configuring field "${actualColumnName}":`);
|
|
208
194
|
try {
|
|
209
195
|
// Create search function
|
|
210
196
|
const createFunctionQuery = `
|
|
@@ -217,7 +203,6 @@ async function configurePrismaTablesForSuparisma(schemaPath) {
|
|
|
217
203
|
END;
|
|
218
204
|
$$ LANGUAGE plpgsql STABLE;`; // Added STABLE for potential performance benefits
|
|
219
205
|
await pool.query(createFunctionQuery);
|
|
220
|
-
console.log(` โ
Created/Replaced RPC function: "${functionName}"(search_prefix text)`);
|
|
221
206
|
// Create GIN index
|
|
222
207
|
const createIndexQuery = `
|
|
223
208
|
DO $$
|
|
@@ -229,39 +214,21 @@ async function configurePrismaTablesForSuparisma(schemaPath) {
|
|
|
229
214
|
AND indexname = '${indexName}'
|
|
230
215
|
) THEN
|
|
231
216
|
CREATE INDEX "${indexName}" ON "public"."${actualTableName}" USING GIN (to_tsvector('english', "${actualColumnName}"));
|
|
232
|
-
RAISE NOTICE ' โ
Created GIN index: "${indexName}" on "${actualTableName}"("${actualColumnName}")';
|
|
233
|
-
ELSE
|
|
234
|
-
RAISE NOTICE ' โน๏ธ GIN index "${indexName}" on "${actualTableName}"("${actualColumnName}") already exists.';
|
|
235
217
|
END IF;
|
|
236
218
|
END;
|
|
237
219
|
$$;`;
|
|
238
|
-
|
|
239
|
-
// Output notices from the DO $$ block (PostgreSQL specific)
|
|
240
|
-
if (indexResult.rows.length > 0 && indexResult.rows[0].notice) {
|
|
241
|
-
console.log(indexResult.rows[0].notice.replace(/^NOTICE: /, ''));
|
|
242
|
-
}
|
|
243
|
-
else if (!indexResult.rows.find((r) => r.notice?.includes('Created GIN index'))) {
|
|
244
|
-
// If DO $$ block doesn't emit specific notice for creation and it didn't say exists.
|
|
245
|
-
// This is a fallback log, actual creation/existence is handled by the DO block.
|
|
246
|
-
// The important part is that the index will be there.
|
|
247
|
-
}
|
|
220
|
+
await pool.query(createIndexQuery);
|
|
248
221
|
}
|
|
249
222
|
catch (err) {
|
|
250
223
|
console.error(` โ Failed to set up search for "${actualTableName}"."${actualColumnName}": ${err.message}`);
|
|
251
224
|
}
|
|
252
225
|
}
|
|
253
226
|
}
|
|
254
|
-
else {
|
|
255
|
-
console.log(` โน๏ธ No fields marked with // @enableSearch for model ${model.name}.`);
|
|
256
|
-
}
|
|
257
|
-
console.log('---------------------------------------------------');
|
|
258
227
|
}
|
|
259
228
|
await pool.end();
|
|
260
|
-
console.log('๐ Database configuration complete.');
|
|
261
229
|
}
|
|
262
230
|
catch (err) {
|
|
263
231
|
console.error('โ Error during database configuration:', err);
|
|
264
|
-
console.log('โ ๏ธ Hook generation will continue, but database features like search or realtime might not be fully configured.');
|
|
265
232
|
}
|
|
266
233
|
}
|
|
267
234
|
/**
|
|
@@ -269,22 +236,16 @@ async function configurePrismaTablesForSuparisma(schemaPath) {
|
|
|
269
236
|
*/
|
|
270
237
|
async function generateHooks() {
|
|
271
238
|
try {
|
|
272
|
-
console.log('๐ Starting Suparisma hook generation...');
|
|
273
239
|
checkEnvironmentVariables();
|
|
274
|
-
console.log(`Prisma schema path: ${config_1.PRISMA_SCHEMA_PATH}`);
|
|
275
|
-
console.log(`Output directory: ${config_1.OUTPUT_DIR}`);
|
|
276
240
|
// Delete the entire output directory if it exists to clean up any stale files
|
|
277
241
|
if (fs_1.default.existsSync(config_1.OUTPUT_DIR)) {
|
|
278
|
-
console.log(`๐งน Cleaning up previous generated files in ${config_1.OUTPUT_DIR}...`);
|
|
279
242
|
fs_1.default.rmSync(config_1.OUTPUT_DIR, { recursive: true, force: true });
|
|
280
|
-
console.log(`โ
Removed previous generated directory`);
|
|
281
243
|
}
|
|
282
244
|
// Ensure all specific output directories exist, OUTPUT_DIR is the root and will be created if needed by sub-creations.
|
|
283
245
|
const dirsToEnsure = [config_1.TYPES_DIR, config_1.HOOKS_DIR, config_1.UTILS_DIR];
|
|
284
246
|
dirsToEnsure.forEach(dir => {
|
|
285
247
|
if (!fs_1.default.existsSync(dir)) {
|
|
286
248
|
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
287
|
-
console.log(`Created directory: ${dir}`);
|
|
288
249
|
}
|
|
289
250
|
});
|
|
290
251
|
// Generate Supabase client file (goes to UTILS_DIR)
|
|
@@ -300,7 +261,6 @@ async function generateHooks() {
|
|
|
300
261
|
modelInfos.push(modelInfo);
|
|
301
262
|
}
|
|
302
263
|
(0, indexGenerator_1.generateMainIndexFile)(modelInfos);
|
|
303
|
-
console.log(`โ
Successfully generated all suparisma hooks and types in "${config_1.OUTPUT_DIR}"!`);
|
|
304
264
|
}
|
|
305
265
|
catch (error) {
|
|
306
266
|
console.error('โ Error generating hooks:', error);
|
package/package.json
CHANGED