Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes to MikroORM schema, and making the whole thing pass tsc #2

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

boenrobot
Copy link

@boenrobot boenrobot commented Jun 28, 2024

@lroal
Copy link
Member

lroal commented Jun 28, 2024

Thanks.
But I really don't want to change import suffixes to 'js' in all ts files.
How can I add type option on all properties ?
Or perhaps use a separate tsconfig (temporary overwrite) for mikroorm will solve it ?

@boenrobot
Copy link
Author

If you don't want to add .js extensions, you need to change

"type": "module",

from "module" to "commonjs", and also set "module" and "moduleResolution" accordingly.

@lroal
Copy link
Member

lroal commented Jun 28, 2024

If you don't want to add .js extensions, you need to change

"type": "module",

from "module" to "commonjs", and also set "module" and "moduleResolution" accordingly.

That would work.
I also tried with a help from chatgpt to use explicit types. But still getting some errors.

> tsx ./src/mikro-orm/benchmark-pg.ts

MetadataError: Customer.orders is defined as scalar @Property(), but its type is a discovered entity Order. Maybe you want to use @ManyToOne() decorator instead?

schema.ts:

import { EntitySchema } from '@mikro-orm/core';

const CustomerSchema = new EntitySchema({
  name: 'Customer',
  tableName: 'customers',
  properties: {
    id: { type: 'string', primary: true },
    companyName: { type: 'string', fieldName: 'company_name' },
    contactName: { type: 'string', fieldName: 'contact_name' },
    contactTitle: { type: 'string', fieldName: 'contact_title' },
    address: { type: 'string' },
    city: { type: 'string' },
    postalCode: { type: 'string', nullable: true, fieldName: 'postal_code' },
    region: { type: 'string', nullable: true },
    country: { type: 'string' },
    phone: { type: 'string' },
    fax: { type: 'string', nullable: true },
    orders: { reference: '1:m', entity: () => OrderSchema, mappedBy: 'customer' },
  },
});

const OrderDetailSchema = new EntitySchema({
  name: 'OrderDetail',
  tableName: 'order_details',
  indexes: [{ properties: ['orderId', 'productId'], unique: true }],
  properties: {
    unitPrice: { type: 'number', fieldName: 'unit_price' },
    quantity: { type: 'number' },
    discount: { type: 'number' },
    orderId: { type: 'string', primary: true, fieldName: 'order_id' },
    productId: { type: 'string', primary: true, fieldName: 'product_id' },
    order: { reference: 'm:1', entity: () => OrderSchema, fieldName: 'order_id' },
    product: { reference: 'm:1', entity: () => ProductSchema, fieldName: 'product_id' },
  },
});

const EmployeeSchema = new EntitySchema({
  name: 'Employee',
  tableName: 'employees',
  indexes: [{ properties: ['recipientId'] }],
  properties: {
    id: { type: 'string', primary: true },
    lastName: { type: 'string', fieldName: 'last_name' },
    firstName: { type: 'string', nullable: true, fieldName: 'first_name' },
    title: { type: 'string' },
    titleOfCourtesy: { type: 'string', fieldName: 'title_of_courtesy' },
    birthDate: { type: 'Date', fieldName: 'birth_date' },
    hireDate: { type: 'Date', fieldName: 'hire_date' },
    address: { type: 'string' },
    city: { type: 'string' },
    postalCode: { type: 'string', fieldName: 'postal_code' },
    country: { type: 'string' },
    homePhone: { type: 'string', fieldName: 'home_phone' },
    extension: { type: 'number' },
    notes: { type: 'string' },
    recipientId: { type: 'string', nullable: true, fieldName: 'recipient_id' },
    orders: { reference: '1:m', entity: () => OrderSchema, mappedBy: 'employee' },
  },
});

const OrderSchema = new EntitySchema({
  name: 'Order',
  tableName: 'orders',
  indexes: [{ properties: ['customerId'] }, { properties: ['employeeId'] }],
  properties: {
    id: { type: 'string', primary: true },
    orderDate: { type: 'Date', fieldName: 'order_date' },
    requiredDate: { type: 'Date', fieldName: 'required_date' },
    shippedDate: { type: 'Date', nullable: true, fieldName: 'shipped_date' },
    shipVia: { type: 'number', fieldName: 'ship_via' },
    freight: { type: 'number' },
    shipName: { type: 'string', fieldName: 'ship_name' },
    shipCity: { type: 'string', fieldName: 'ship_city' },
    shipRegion: { type: 'string', nullable: true, fieldName: 'ship_region' },
    shipPostalCode: { type: 'string', nullable: true, fieldName: 'ship_postal_code' },
    shipCountry: { type: 'string', fieldName: 'ship_country' },
    customerId: { type: 'string', fieldName: 'customer_id' },
    employeeId: { type: 'string', fieldName: 'employee_id' },
    customer: { reference: 'm:1', entity: () => CustomerSchema, fieldName: 'customer_id' },
    employee: { reference: 'm:1', entity: () => EmployeeSchema, fieldName: 'employee_id' },
    orderDetails: { reference: '1:m', entity: () => OrderDetailSchema, mappedBy: 'order' },
  },
});

const ProductSchema = new EntitySchema({
  name: 'Product',
  tableName: 'products',
  indexes: [{ properties: ['supplierId'] }],
  properties: {
    id: { type: 'string', primary: true },
    name: { type: 'string' },
    qtPerUnit: { type: 'string', fieldName: 'qt_per_unit' },
    unitPrice: { type: 'number', fieldName: 'unit_price' },
    unitsInStock: { type: 'number', fieldName: 'units_in_stock' },
    unitsOnOrder: { type: 'number', fieldName: 'units_on_order' },
    reorderLevel: { type: 'number', fieldName: 'reorder_level' },
    discontinued: { type: 'number' },
    supplierId: { type: 'string', fieldName: 'supplier_id' },
    supplier: { reference: 'm:1', entity: () => SupplierSchema, fieldName: 'supplier_id' },
    orderDetails: { reference: '1:m', entity: () => OrderDetailSchema, mappedBy: 'product' },
  },
});

const SupplierSchema = new EntitySchema({
  name: 'Supplier',
  tableName: 'suppliers',
  properties: {
    id: { type: 'string', primary: true },
    companyName: { type: 'string', fieldName: 'company_name' },
    contactName: { type: 'string', fieldName: 'contact_name' },
    contactTitle: { type: 'string', fieldName: 'contact_title' },
    address: { type: 'string' },
    city: { type: 'string' },
    region: { type: 'string', nullable: true },
    postalCode: { type: 'string', fieldName: 'postal_code' },
    country: { type: 'string' },
    phone: { type: 'string' },
    products: { reference: '1:m', entity: () => ProductSchema, mappedBy: 'supplier' },
  },
});

export default [CustomerSchema, OrderDetailSchema, EmployeeSchema, OrderSchema, ProductSchema, SupplierSchema];

postgres.ts:

import schema from './schema';
import { PostgreSqlDriver } from '@mikro-orm/postgresql';

export default {
  entities: schema,
  dbName: 'my-db-name',
  driver: PostgreSqlDriver,
  clientUrl: `${process.env.POSTGRES_URL}`,
  pool: {
    min: 1,
    max: 1
  },
  debug: false,
};

benchmark-pg.ts:

import { MikroORM } from '@mikro-orm/core';
import dotenv from 'dotenv';
import postgres from './postgres';

dotenv.config();
const ITERATIONS = Number.parseInt(process.env.ITERATIONS);

async function main() {
  const orm = (await MikroORM.init(postgres)).em;

  await benchmark();

  async function benchmark() {
    await warmup();
    await getRowsWithRelations();
  }

  async function warmup() {
    const em = orm.fork().getRepository('Order');
    await em.findOne({});
  }

  async function getRowsWithRelations() {
    const em = orm.fork().getRepository('Order');
    console.time('mikroORM');
    const promises = [];
    for (let i = 0; i < ITERATIONS; i++) {
      const p = em.find({}, { populate: ['customer', 'employee', 'orderDetails.product.supplier'] }).then(JSON.stringify);
      promises.push(p);
    }
    await Promise.all(promises);
    console.timeEnd('mikroORM');
  }
}


main().catch(err => {
  console.error(err);
  process.exit(1);
});


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants