This commit is contained in:
Rizky 2024-07-25 16:19:52 +07:00
parent b55b3d793c
commit 2b6c39c550
4 changed files with 97 additions and 14 deletions

11
pkgs/utils/db/types.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
export type HasManyType = {
type: "has-many";
to: { table: string; fields: string[] };
from: { table: string; fields: string[] };
};
export type HasOneType = {
type: "has-one";
to: { table: string; fields: string[] };
from: { table: string; fields: string[] };
};

View File

@ -0,0 +1,62 @@
import { createPrismaSchemaBuilder, Field } from "@mrleebo/prisma-ast";
import { get } from "utils/get";
import { HasManyType } from "./types";
export const upsertRelMany = (arg: {
row: any;
k: string;
schema: ReturnType<typeof createPrismaSchemaBuilder>;
rel: HasManyType;
}) => {
const { row, k, schema, rel } = arg;
if (Array.isArray(row[k])) {
const create_many: any[] = row[k].map((e) => {
const item = {} as any;
const rel_fields = schema.findByType("model", {
name: rel.to.table,
});
if (rel_fields && rel_fields.properties.length > 0) {
const fields: Record<string, Field> = {};
for (const f of Object.values(rel_fields.properties)) {
if (f.type === "field") {
fields[f.name] = f;
}
}
for (const [k, v] of Object.entries(e)) {
const f = fields[k];
if (f && k !== rel.from.table) {
const is_rel = f.attributes?.find(
(e) => e.kind === "field" && e.name === "relation"
);
if (is_rel) {
let to_field_raw = is_rel.args?.find(
(e) =>
e.type === "attributeArgument" && get(e, "value.value.args.0")
);
if (to_field_raw) {
const to_field = get(
to_field_raw,
"value.value.args.0"
) as string;
if (typeof v === "object" && (v as any)?.connect) {
const pk = Object.values((v as any).connect)[0];
if (pk) {
delete item[k];
item[to_field] = pk;
}
}
}
} else {
item[k] = v;
}
}
}
}
return item;
});
row[k] = { createMany: { data: create_many } };
}
};

16
pkgs/utils/get.ts Normal file
View File

@ -0,0 +1,16 @@
type Path = string | Array<string | number>;
export function get<T, K>(object: T, path: Path, defaultValue?: K): K | undefined {
const pathArray = Array.isArray(path)
? path
: path.match(/([^[.\]])+/g) || [];
return (
pathArray.reduce((acc, key) => {
if (acc && typeof acc === "object") {
return (acc as any)[key];
}
return undefined;
}, object as any) ?? defaultValue
);
}

View File

@ -1,8 +1,9 @@
import { Property, createPrismaSchemaBuilder } from "@mrleebo/prisma-ast";
import { readAsync } from "fs-jetpack";
import { HasManyType, HasOneType } from "./db/types";
import { dir } from "./dir";
import { gunzipAsync } from "./gzip";
import { upsertRelMany } from "./db/upsert-rel-many";
export type DBArg = {
db: string;
table: string;
@ -63,6 +64,7 @@ export const execQuery = async (args: DBArg, prisma: any) => {
const updates = [] as any[];
const inserts = [] as any[];
const deletes = [] as any[];
const delete_has_many = [] as { table: string; where: any }[];
const exists_idx = new Set<number>();
const marker = {} as any;
@ -110,6 +112,8 @@ export const execQuery = async (args: DBArg, prisma: any) => {
let newv = { connect: { [to]: v[to] } };
row[k] = newv;
}
} else if (rel.type === "has-many") {
upsertRelMany({ schema, k, rel, row });
}
}
}
@ -144,6 +148,8 @@ export const execQuery = async (args: DBArg, prisma: any) => {
let newv = { connect: { [to]: v[to] } };
row[k] = newv;
}
} else if (rel.type === "has-many") {
upsertRelMany({ schema, k, rel, row });
}
}
}
@ -402,19 +408,7 @@ const getRels = ({
table: any;
tables: string[];
}) => {
const rels = {} as Record<
string,
| {
type: "has-many";
to: { table: string; fields: string[] };
from: { table: string; fields: string[] };
}
| {
type: "has-one";
to: { table: string; fields: string[] };
from: { table: string; fields: string[] };
}
>;
const rels = {} as Record<string, HasManyType | HasOneType>;
for (const col of schema_table.properties) {
if (
col.type === "field" &&