@suss/contract-prisma 0.10.0 → 0.12.0

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/index.cjs CHANGED
@@ -118,6 +118,7 @@ function buildModelSummary(opts) {
118
118
  const columns = [];
119
119
  const indexes = [];
120
120
  const physicalTable = physicalTableOf(opts.model);
121
+ let hasRelation = false;
121
122
  for (const property of opts.model.properties) {
122
123
  if (property.type === "field") {
123
124
  const field = property;
@@ -125,6 +126,11 @@ function buildModelSummary(opts) {
125
126
  if (column !== null) {
126
127
  columns.push(column);
127
128
  }
129
+ const related = relationField(field, opts.modelNames);
130
+ if (related !== null) {
131
+ hasRelation = true;
132
+ columns.push(related);
133
+ }
128
134
  } else if (property.type === "attribute") {
129
135
  const attr = property;
130
136
  const index = blockAttributeToIndex(attr);
@@ -133,6 +139,14 @@ function buildModelSummary(opts) {
133
139
  }
134
140
  }
135
141
  }
142
+ if (hasRelation) {
143
+ columns.push({
144
+ name: "_count",
145
+ type: "PrismaCount",
146
+ nullable: false,
147
+ derived: true
148
+ });
149
+ }
136
150
  return {
137
151
  kind: "library",
138
152
  location: {
@@ -166,6 +180,25 @@ function buildModelSummary(opts) {
166
180
  }
167
181
  };
168
182
  }
183
+ function relationField(field, modelNames) {
184
+ if (!modelNames.has(field.fieldType)) {
185
+ return null;
186
+ }
187
+ const key = relationKeyOf(field);
188
+ return {
189
+ name: field.name,
190
+ type: field.array === true ? `${field.fieldType}[]` : field.fieldType,
191
+ nullable: field.optional === true,
192
+ derived: true,
193
+ ...key === null ? {} : { relationKey: key }
194
+ };
195
+ }
196
+ function relationKeyOf(field) {
197
+ const relation = (field.attributes ?? []).find(
198
+ (attr) => attr.name === "relation"
199
+ );
200
+ return relation === void 0 ? null : readKeyedArrayArg(relation, "fields");
201
+ }
169
202
  function fieldToColumn(field, modelNames, enumNames) {
170
203
  if (field.array === true) {
171
204
  return null;
@@ -233,25 +266,39 @@ function blockAttributeToIndex(attr) {
233
266
  return { fields, unique: attr.name !== "index" };
234
267
  }
235
268
  function readArrayArg(attr) {
269
+ for (const arg of attr.args ?? []) {
270
+ const names = arrayNames(arg.value);
271
+ if (names !== null) {
272
+ return names;
273
+ }
274
+ }
275
+ return null;
276
+ }
277
+ function readKeyedArrayArg(attr, key) {
236
278
  for (const arg of attr.args ?? []) {
237
279
  const value = arg.value;
238
- if (value === null || value === void 0) {
280
+ if (value?.type !== "keyValue" || value.key !== key) {
239
281
  continue;
240
282
  }
241
- if (value.type === "array" && Array.isArray(value.args)) {
242
- const out = [];
243
- for (const item of value.args) {
244
- if (typeof item === "string") {
245
- out.push(item);
246
- } else if (typeof item === "object" && item !== null && "name" in item && typeof item.name === "string") {
247
- out.push(item.name);
248
- }
249
- }
250
- return out;
251
- }
283
+ return arrayNames(value.value);
252
284
  }
253
285
  return null;
254
286
  }
287
+ function arrayNames(value) {
288
+ const array = value;
289
+ if (array?.type !== "array" || !Array.isArray(array.args)) {
290
+ return null;
291
+ }
292
+ const out = [];
293
+ for (const item of array.args) {
294
+ if (typeof item === "string") {
295
+ out.push(item);
296
+ } else if (typeof item === "object" && item !== null && "name" in item && typeof item.name === "string") {
297
+ out.push(item.name);
298
+ }
299
+ }
300
+ return out;
301
+ }
255
302
  function readProviderString(ds) {
256
303
  for (const a of ds.assignments) {
257
304
  if (a.key !== "provider") {
package/dist/index.js CHANGED
@@ -83,6 +83,7 @@ function buildModelSummary(opts) {
83
83
  const columns = [];
84
84
  const indexes = [];
85
85
  const physicalTable = physicalTableOf(opts.model);
86
+ let hasRelation = false;
86
87
  for (const property of opts.model.properties) {
87
88
  if (property.type === "field") {
88
89
  const field = property;
@@ -90,6 +91,11 @@ function buildModelSummary(opts) {
90
91
  if (column !== null) {
91
92
  columns.push(column);
92
93
  }
94
+ const related = relationField(field, opts.modelNames);
95
+ if (related !== null) {
96
+ hasRelation = true;
97
+ columns.push(related);
98
+ }
93
99
  } else if (property.type === "attribute") {
94
100
  const attr = property;
95
101
  const index = blockAttributeToIndex(attr);
@@ -98,6 +104,14 @@ function buildModelSummary(opts) {
98
104
  }
99
105
  }
100
106
  }
107
+ if (hasRelation) {
108
+ columns.push({
109
+ name: "_count",
110
+ type: "PrismaCount",
111
+ nullable: false,
112
+ derived: true
113
+ });
114
+ }
101
115
  return {
102
116
  kind: "library",
103
117
  location: {
@@ -131,6 +145,25 @@ function buildModelSummary(opts) {
131
145
  }
132
146
  };
133
147
  }
148
+ function relationField(field, modelNames) {
149
+ if (!modelNames.has(field.fieldType)) {
150
+ return null;
151
+ }
152
+ const key = relationKeyOf(field);
153
+ return {
154
+ name: field.name,
155
+ type: field.array === true ? `${field.fieldType}[]` : field.fieldType,
156
+ nullable: field.optional === true,
157
+ derived: true,
158
+ ...key === null ? {} : { relationKey: key }
159
+ };
160
+ }
161
+ function relationKeyOf(field) {
162
+ const relation = (field.attributes ?? []).find(
163
+ (attr) => attr.name === "relation"
164
+ );
165
+ return relation === void 0 ? null : readKeyedArrayArg(relation, "fields");
166
+ }
134
167
  function fieldToColumn(field, modelNames, enumNames) {
135
168
  if (field.array === true) {
136
169
  return null;
@@ -198,25 +231,39 @@ function blockAttributeToIndex(attr) {
198
231
  return { fields, unique: attr.name !== "index" };
199
232
  }
200
233
  function readArrayArg(attr) {
234
+ for (const arg of attr.args ?? []) {
235
+ const names = arrayNames(arg.value);
236
+ if (names !== null) {
237
+ return names;
238
+ }
239
+ }
240
+ return null;
241
+ }
242
+ function readKeyedArrayArg(attr, key) {
201
243
  for (const arg of attr.args ?? []) {
202
244
  const value = arg.value;
203
- if (value === null || value === void 0) {
245
+ if (value?.type !== "keyValue" || value.key !== key) {
204
246
  continue;
205
247
  }
206
- if (value.type === "array" && Array.isArray(value.args)) {
207
- const out = [];
208
- for (const item of value.args) {
209
- if (typeof item === "string") {
210
- out.push(item);
211
- } else if (typeof item === "object" && item !== null && "name" in item && typeof item.name === "string") {
212
- out.push(item.name);
213
- }
214
- }
215
- return out;
216
- }
248
+ return arrayNames(value.value);
217
249
  }
218
250
  return null;
219
251
  }
252
+ function arrayNames(value) {
253
+ const array = value;
254
+ if (array?.type !== "array" || !Array.isArray(array.args)) {
255
+ return null;
256
+ }
257
+ const out = [];
258
+ for (const item of array.args) {
259
+ if (typeof item === "string") {
260
+ out.push(item);
261
+ } else if (typeof item === "object" && item !== null && "name" in item && typeof item.name === "string") {
262
+ out.push(item.name);
263
+ }
264
+ }
265
+ return out;
266
+ }
220
267
  function readProviderString(ds) {
221
268
  for (const a of ds.assignments) {
222
269
  if (a.key !== "provider") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suss/contract-prisma",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "type": "module",
5
5
  "description": "Generate suss behavioral summaries from Prisma schema declarations.",
6
6
  "keywords": [
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@mrleebo/prisma-ast": "^0.15.0",
50
- "@suss/behavioral-ir": "0.10.0"
50
+ "@suss/behavioral-ir": "0.12.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "tsup": "*",