prisma-guard 1.30.0 → 1.31.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.
@@ -13,6 +13,7 @@ interface FieldMeta {
13
13
  isEnum?: boolean;
14
14
  isUnique?: boolean;
15
15
  isUnsupported?: boolean;
16
+ relationFromFields?: readonly string[];
16
17
  }
17
18
  interface GuardLogger {
18
19
  warn(message: string): void;
@@ -228,6 +229,7 @@ interface FieldMetaConst {
228
229
  readonly isEnum?: boolean;
229
230
  readonly isUnique?: boolean;
230
231
  readonly isUnsupported?: boolean;
232
+ readonly relationFromFields?: readonly string[];
231
233
  }
232
234
  interface UniqueConstraintConst {
233
235
  readonly selector: string;
@@ -13,6 +13,7 @@ interface FieldMeta {
13
13
  isEnum?: boolean;
14
14
  isUnique?: boolean;
15
15
  isUnsupported?: boolean;
16
+ relationFromFields?: readonly string[];
16
17
  }
17
18
  interface GuardLogger {
18
19
  warn(message: string): void;
@@ -228,6 +229,7 @@ interface FieldMetaConst {
228
229
  readonly isEnum?: boolean;
229
230
  readonly isUnique?: boolean;
230
231
  readonly isUnsupported?: boolean;
232
+ readonly relationFromFields?: readonly string[];
231
233
  }
232
234
  interface UniqueConstraintConst {
233
235
  readonly selector: string;
@@ -4110,12 +4110,39 @@ function validateAllowedKeys(value, allowed, method, kind) {
4110
4110
  return `Shape key "${key}" not valid for ${method}. Allowed: ${[...allowed].join(", ")}`;
4111
4111
  });
4112
4112
  }
4113
+ var RELATION_OPS_COVERING_FK = /* @__PURE__ */ new Set([
4114
+ "connect",
4115
+ "connectOrCreate",
4116
+ "create"
4117
+ ]);
4118
+ function collectRelationCoveredFks(modelFields, dataConfig) {
4119
+ const covered = /* @__PURE__ */ new Set();
4120
+ for (const [fieldName, value] of Object.entries(dataConfig)) {
4121
+ const meta = modelFields[fieldName];
4122
+ if (!meta || !meta.isRelation)
4123
+ continue;
4124
+ const fks = meta.relationFromFields;
4125
+ if (!fks || fks.length === 0)
4126
+ continue;
4127
+ if (!isPlainObject(value))
4128
+ continue;
4129
+ const covers = Object.keys(value).some(
4130
+ (op) => RELATION_OPS_COVERING_FK.has(op)
4131
+ );
4132
+ if (!covers)
4133
+ continue;
4134
+ for (const fk of fks)
4135
+ covered.add(fk);
4136
+ }
4137
+ return covered;
4138
+ }
4113
4139
  function validateCreateCompleteness(modelName, dataConfig, typeMap, scopeFks, zodDefaults) {
4114
4140
  const modelFields = typeMap[modelName];
4115
4141
  if (!modelFields)
4116
4142
  return;
4117
4143
  const zodDefaultFields = zodDefaults[modelName];
4118
4144
  const zodDefaultSet = zodDefaultFields ? new Set(zodDefaultFields) : void 0;
4145
+ const relationCoveredFks = collectRelationCoveredFks(modelFields, dataConfig);
4119
4146
  for (const [fieldName, meta] of Object.entries(modelFields)) {
4120
4147
  if (meta.isRelation)
4121
4148
  continue;
@@ -4129,10 +4156,12 @@ function validateCreateCompleteness(modelName, dataConfig, typeMap, scopeFks, zo
4129
4156
  continue;
4130
4157
  if (scopeFks.has(fieldName))
4131
4158
  continue;
4159
+ if (relationCoveredFks.has(fieldName))
4160
+ continue;
4132
4161
  if (zodDefaultSet && zodDefaultSet.has(fieldName))
4133
4162
  continue;
4134
4163
  throw new ShapeError(
4135
- `Required field "${fieldName}" on model "${modelName}" is missing from create data shape, has no default, and is not a scope FK`
4164
+ `Required field "${fieldName}" on model "${modelName}" is missing from create data shape, has no default, is not a scope FK, and is not covered by a relation write in the shape`
4136
4165
  );
4137
4166
  }
4138
4167
  }