suparisma 1.1.2 → 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.
package/dist/parser.js CHANGED
@@ -70,10 +70,10 @@ function parseZodImport(comment) {
70
70
  */
71
71
  function parsePrismaSchema(schemaPath) {
72
72
  const schema = fs_1.default.readFileSync(schemaPath, 'utf-8');
73
- const modelRegex = /model\s+(\w+)\s+{([^}]*)}/gs;
73
+ const modelRegex = /model\s+(\w+)\s+{([^}]*)}/g;
74
74
  const models = [];
75
75
  // Extract enum names from the schema
76
- const enumRegex = /enum\s+(\w+)\s+{[^}]*}/gs;
76
+ const enumRegex = /enum\s+(\w+)\s+{[^}]*}/g;
77
77
  const enumNames = [];
78
78
  let enumMatch;
79
79
  while ((enumMatch = enumRegex.exec(schema)) !== null) {
@@ -95,77 +95,87 @@ function parsePrismaSchema(schemaPath) {
95
95
  const searchFields = [];
96
96
  // Track zod imports at model level
97
97
  const zodImports = [];
98
- const lines = modelBody.split('\n');
99
- let lastFieldName = '';
100
- let lastFieldType = '';
98
+ // Use EXACT same logic as analyzePrismaSchema for consistency
99
+ const bodyLines = modelBody.trim().split('\n');
100
+ let nextFieldShouldBeSearchable = false;
101
101
  let pendingZodDirective;
102
- for (let i = 0; i < lines.length; i++) {
103
- const line = lines[i]?.trim();
102
+ for (let i = 0; i < bodyLines.length; i++) {
103
+ const currentLine = bodyLines[i]?.trim();
104
104
  // Skip blank lines and non-field lines
105
- if (!line || line.startsWith('@@')) {
105
+ if (!currentLine || currentLine.startsWith('@@')) {
106
106
  continue;
107
107
  }
108
- // Check for standalone @enableSearch comment
109
- if (line === '// @enableSearch' && lastFieldName) {
110
- searchFields.push({
111
- name: lastFieldName,
112
- type: lastFieldType,
113
- });
108
+ // Check for /// @enableSearch directive (applies to NEXT field)
109
+ if (currentLine === '/// @enableSearch') {
110
+ nextFieldShouldBeSearchable = true;
114
111
  continue;
115
112
  }
116
- // Check if line is a comment
117
- if (line.startsWith('//')) {
113
+ // Check for standalone // @enableSearch comment (applies to NEXT field)
114
+ if (currentLine === '// @enableSearch') {
115
+ nextFieldShouldBeSearchable = true;
116
+ continue;
117
+ }
118
+ // Check if line is a comment - SKIP ALL TYPES of comments but keep search flag
119
+ if (currentLine.startsWith('///') || currentLine.startsWith('//')) {
118
120
  // Parse zod directives from comments
119
- const zodDirective = parseZodDirective(line);
121
+ const zodDirective = parseZodDirective(currentLine);
120
122
  if (zodDirective) {
121
123
  pendingZodDirective = zodDirective;
122
124
  }
123
125
  // Parse zod imports from comments
124
- const zodImportInfos = parseZodImport(line);
126
+ const zodImportInfos = parseZodImport(currentLine);
125
127
  zodImports.push(...zodImportInfos);
126
128
  continue;
127
129
  }
128
- // Parse field definition - Updated to handle array types
129
- const fieldMatch = line.match(/\s*(\w+)\s+(\w+)(\[\])?(\?)?\s*(?:@[^)]+)?/);
130
+ // Parse field definition - Updated to handle array types and inline comments
131
+ const fieldMatch = currentLine.match(/^\s*(\w+)\s+(\w+)(\[\])?(\?)?\s*/);
130
132
  if (fieldMatch) {
131
133
  const fieldName = fieldMatch[1];
132
- const baseFieldType = fieldMatch[2]; // e.g., "String" from "String[]"
134
+ const baseFieldType = fieldMatch[2];
135
+ // Check if this field should be searchable due to @enableSearch directive
136
+ if (nextFieldShouldBeSearchable && fieldName && baseFieldType) {
137
+ searchFields.push({
138
+ name: fieldName,
139
+ type: baseFieldType,
140
+ });
141
+ nextFieldShouldBeSearchable = false; // Reset flag
142
+ }
143
+ // Check for inline // @enableSearch comment
144
+ if (currentLine.includes('// @enableSearch')) {
145
+ if (fieldName && baseFieldType && !searchFields.some(f => f.name === fieldName)) {
146
+ searchFields.push({
147
+ name: fieldName,
148
+ type: baseFieldType,
149
+ });
150
+ }
151
+ }
152
+ // Continue with field processing for the fields array
133
153
  const isArray = !!fieldMatch[3]; // [] makes it an array
134
154
  const isOptional = !!fieldMatch[4]; // ? makes it optional
135
- // Store for potential standalone @enableSearch comment
136
- lastFieldName = fieldName || '';
137
- lastFieldType = baseFieldType || '';
138
155
  // Detect special fields
139
- const isId = line.includes('@id');
156
+ const isId = currentLine.includes('@id');
140
157
  const isCreatedAt = fieldName === 'created_at' || fieldName === 'createdAt';
141
158
  const isUpdatedAt = fieldName === 'updated_at' || fieldName === 'updatedAt';
142
- const hasDefaultValue = line.includes('@default');
159
+ const hasDefaultValue = currentLine.includes('@default');
143
160
  // Extract default value if present
144
161
  let defaultValue;
145
162
  if (hasDefaultValue) {
146
- const defaultMatch = line.match(/@default\(\s*(.+?)\s*\)/);
163
+ const defaultMatch = currentLine.match(/@default\(\s*(.+?)\s*\)/);
147
164
  if (defaultMatch) {
148
165
  defaultValue = defaultMatch[1];
149
166
  }
150
167
  }
151
168
  // Improved relation detection
152
169
  const primitiveTypes = ['String', 'Int', 'Float', 'Boolean', 'DateTime', 'Json', 'Bytes', 'Decimal', 'BigInt'];
153
- const isRelation = line.includes('@relation') ||
170
+ const isRelation = currentLine.includes('@relation') ||
154
171
  (!!fieldName &&
155
172
  (fieldName.endsWith('_id') || fieldName === 'userId' || fieldName === 'user_id')) ||
156
173
  // Also detect relation fields by checking if the type is not a primitive type and not an enum
157
174
  (!!baseFieldType && !primitiveTypes.includes(baseFieldType) && !enumNames.includes(baseFieldType));
158
- // Check for inline @enableSearch comment
159
- if (line.includes('// @enableSearch')) {
160
- searchFields.push({
161
- name: fieldName || '',
162
- type: baseFieldType || '',
163
- });
164
- }
165
175
  // Check for inline zod directive
166
176
  let fieldZodDirective = pendingZodDirective;
167
- if (line.includes('/// @zod.')) {
168
- const inlineZodDirective = parseZodDirective(line);
177
+ if (currentLine.includes('/// @zod.')) {
178
+ const inlineZodDirective = parseZodDirective(currentLine);
169
179
  if (inlineZodDirective) {
170
180
  fieldZodDirective = inlineZodDirective;
171
181
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "suparisma",
3
- "version": "1.1.2",
3
+ "version": "1.2.1",
4
4
  "description": "Opinionated typesafe React realtime CRUD hooks generator for all your Supabase tables, powered by Prisma.",
5
5
  "main": "dist/index.js",
6
6
  "repository": {
@@ -21,7 +21,9 @@ enum SomeEnum {
21
21
 
22
22
  model User {
23
23
  id String @id @default(uuid())
24
+ // @enableSearch
24
25
  name String
26
+ // @enableSearch
25
27
  email String @unique
26
28
  things Thing[] // One-to-many relation
27
29
  createdAt DateTime @default(now())
@@ -33,11 +35,14 @@ model Thing {
33
35
  id String @id @default(uuid())
34
36
  // @enableSearch
35
37
  name String?
38
+ // @enableSearch
39
+ /// Somehting here
40
+ description String? /// @thing
36
41
  stringArray String[]
37
42
  someEnum SomeEnum @default(ONE)
38
43
  someNumber Int?
39
44
 
40
- /// [Json]
45
+ // @enableSearch
41
46
  someJson Json? /// @zod.custom.use(z.array(LLMNodeSchema).nullable())
42
47
  userId String?
43
48
  user User? @relation(fields: [userId], references: [id])