prisma-factory icon indicating copy to clipboard operation
prisma-factory copied to clipboard

Handle `ModelCreateNestedManyWithoutParentInput` attrs

Open solomonhawk opened this issue 1 year ago • 0 comments

Hello, thanks for making this - it's super useful!

The Prisma types for nested creates allow for passing an array in the case of a has-many relation, but prisma-factory appears not to handle this case gracefully. Instead, I'm seeing something like the following:

Error: 
    Invalid `prisma[prismaModel].create()` invocation in
    /Users/solomonhawk/Code/Work/mainframe/node_modules/prisma-factory/dist/index.js:109:44

      106   data = hooks.beforeCreate(data);
      107 }
      108 const prismaModel = (0, import_camel_case.camelCase)(modelName);
    → 109 let result = await prisma[prismaModel].create({
            data: {
              name: 'Name',
              slug: 'name',
              description: 'description',
              author: {
                connect: {
                  email: '[email protected]'
                }
              },
              homepageUrl: 'https://known-bike.info',
              sourceUrl: 'https://growing-eavesdropper.biz',
              tags: {
                create: {
                  '0': {
                    name: 'facere',
                    description: 'Rem nemo repudiandae veritatis enim totam aperiam ipsam nam. Inventore tempore exercitationem labore in dicta saepe eveniet asperiores excepturi. Enim voluptatibus commodi molestiae enim odit doloribus in a sunt.'
                  },
                  '1': {
                    name: 'aliquam',
                    description: 'Perferendis porro quas natus. Quasi enim sed enim tempora unde amet eveniet aliquam. Eaque reiciendis vel sit placeat repudiandae a dolore incidunt quasi.'
                  },
          +       name: String,
          ?       id?: String,
          ?       description?: String | null
                }
              }
            },
            include: {
              author: true
            }
          })

    Unknown arg `0` in data.tags.create.0 for type TagCreateWithoutTopicsInput.
    Unknown arg `1` in data.tags.create.1 for type TagCreateWithoutTopicsInput.
    Argument name for data.tags.create.name is missing.

My factory looks like:

export const TopicFactory = createTopicFactory({
  name: () => faker.lorem.word(),
  slug: () => faker.lorem.slug(),
  description: () => faker.lorem.paragraphs({ min: 1, max: 3 }),
  author: () => ({ create: UserFactory.build() }),
  homepageUrl: () => faker.internet.url(),
  sourceUrl: () => faker.internet.url(),
  tags: () => ({ create: () => [TagFactory.build(), TagFactory.build()] }),
});

I also tried without the inner lambda { create: [TagFactory.build(), TagFactory.build()] }, but the result is the same.

Without delving too deep, perhaps the typeof value === 'object' checks here are matching array values erroneously.

The following patch seems to resolve the issue:

diff --git a/node_modules/prisma-factory/dist/index.js b/node_modules/prisma-factory/dist/index.js
index 9293749..de9df4a 100644
--- a/node_modules/prisma-factory/dist/index.js
+++ b/node_modules/prisma-factory/dist/index.js
@@ -46,11 +46,17 @@ var import_camel_case = require("camel-case");
 // src/utils/getAttrs.ts
 var getAttrs = (attrs) => {
   return Object.fromEntries(Object.entries(attrs).map(([key, value]) => {
+    if (Array.isArray(value)) {
+      return [key, value.map(inner => getAttrs(inner))]
+    }
     if (typeof value === "object") {
       return [key, getAttrs(value)];
     }
     if (typeof value === "function") {
       const result = value();
+      if (Array.isArray(value)) {
+        return [key, value.map(inner => getAttrs(inner))]
+      }
       if (typeof result === "object") {
         return [key, getAttrs(result)];
       }
diff --git a/node_modules/prisma-factory/dist/index.mjs b/node_modules/prisma-factory/dist/index.mjs
index a13ad42..470e8d3 100644
--- a/node_modules/prisma-factory/dist/index.mjs
+++ b/node_modules/prisma-factory/dist/index.mjs
@@ -10,11 +10,17 @@ import { camelCase } from "camel-case";
 // src/utils/getAttrs.ts
 var getAttrs = (attrs) => {
   return Object.fromEntries(Object.entries(attrs).map(([key, value]) => {
+    if (Array.isArray(value)) {
+      return [key, value.map(inner => getAttrs(inner))]
+    }
     if (typeof value === "object") {
       return [key, getAttrs(value)];
     }
     if (typeof value === "function") {
       const result = value();
+      if (Array.isArray(value)) {
+        return [key, value.map(inner => getAttrs(inner))]
+      }
       if (typeof result === "object") {
         return [key, getAttrs(result)];
       }

solomonhawk avatar Jul 03 '23 04:07 solomonhawk