This commit is contained in:
Rizky 2024-03-07 16:28:15 +07:00
parent 90678d1fae
commit 084675a811
6 changed files with 160 additions and 4 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -19,6 +19,7 @@
"typescript": "^5.0.0" "typescript": "^5.0.0"
}, },
"dependencies": { "dependencies": {
"@mrleebo/prisma-ast": "^0.10.1",
"brotli-wasm": "^2.0.1", "brotli-wasm": "^2.0.1",
"exit-hook": "^4.0.0", "exit-hook": "^4.0.0",
"firebase-admin": "^11.11.0", "firebase-admin": "^11.11.0",

View File

@ -1,10 +1,9 @@
import { apiContext } from "service-srv"; import { apiContext } from "service-srv";
import { execQuery } from "utils/query"; import { execQuery } from "utils/query";
const g = global as any; const g = global as any;
export const _ = { export const _ = {
url: "/_dbs/:tableName", url: "/_dbs/*",
async api(tableName: any) { async api() {
const { req, res } = apiContext(this); const { req, res } = apiContext(this);
if (typeof g.db !== "undefined") { if (typeof g.db !== "undefined") {
const body = req.params; const body = req.params;

View File

@ -59,6 +59,12 @@ export const createServer = async () => {
await scan(dir(`app/srv/api`)); await scan(dir(`app/srv/api`));
await scan(dir(`pkgs/api`)); await scan(dir(`pkgs/api`));
g.createServer = (arg) => {
return async (site_id: string) => {
return arg;
};
};
g.server = Bun.serve({ g.server = Bun.serve({
port: g.port, port: g.port,
maxRequestBodySize: 1024 * 1024 * 128, maxRequestBodySize: 1024 * 1024 * 128,

View File

@ -70,6 +70,9 @@ export const g = global as unknown as {
br: Record<string, Uint8Array>; br: Record<string, Uint8Array>;
br_timeout: Set<string>; br_timeout: Set<string>;
}; };
createServer: (
arg: PrasiServer & { api: any; db: any }
) => (site_id: string) => Promise<PrasiServer & { api: any; db: any }>;
deploy: { deploy: {
init: boolean; init: boolean;
raw: any; raw: any;

View File

@ -1,4 +1,7 @@
import { createPrismaSchemaBuilder } from "@mrleebo/prisma-ast";
import { readAsync } from "fs-jetpack";
import { Prisma } from "../../app/db/db"; import { Prisma } from "../../app/db/db";
import { dir } from "./dir";
export type DBArg = { export type DBArg = {
db: string; db: string;
@ -10,7 +13,125 @@ export type DBArg = {
export const execQuery = async (args: DBArg, prisma: any) => { export const execQuery = async (args: DBArg, prisma: any) => {
const { table, action, params } = args; const { table, action, params } = args;
console.log(args); if (action.startsWith("schema_")) {
const schema_path = dir("app/db/prisma/schema.prisma");
const schema = createPrismaSchemaBuilder(await readAsync(schema_path));
if (action === "schema_tables") {
const tables = schema.findAllByType("model", {}).map((e) => e?.name);
return tables || [];
} else {
const schema_table = schema.findByType("model", { name: table });
const columns = {} as Record<
string,
{
is_pk: boolean;
type: string;
optional: boolean;
db_type: string;
default?: any
}
>;
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[] }
}>
if (schema_table) {
if (action === "schema_rels") {
for (const col of schema_table.properties) {
if (
col.type === "field" &&
(!!col.array ||
col.attributes &&
col.attributes?.length > 0)
) {
if (col.array) {
if (typeof col.fieldType === 'string') {
const target = schema.findByType('model', { name: col.fieldType })
if (target) {
const field = target.properties.find(e => {
if (e.type === 'field'
&& e.fieldType === table) {
return true;
}
});
if (field && field.type === 'field') {
const rel = field.attributes?.find(e => e.kind === 'field');
if (rel && rel.args) {
const { field, ref } = getFieldAndRef(rel, target, table);
if (target && ref) {
rels[col.name] = {
type: 'has-many',
to: field,
from: ref
}
}
}
}
}
}
} else if (col.attributes) {
const rel = col.attributes.find(e => e.type === 'attribute' && e.name === 'relation');
if (rel && typeof col.fieldType === 'string') {
const target = schema.findByType('model', { name: col.fieldType });
const { field, ref } = getFieldAndRef(rel, target, table);
rels[col.name] = {
type: 'has-one',
to: {
table: field.table,
fields: ref.fields
},
from: {
table: ref.table,
fields: field.fields
}
}
}
}
}
}
return rels;
} else if (action === "schema_columns") {
for (const col of schema_table.properties) {
if (
col.type === "field" &&
!col.array &&
col.attributes &&
col.attributes?.length > 0
) {
const attr = col.attributes.find(e => e.name !== 'id' && e.name !== 'default');
const default_val = col.attributes.find(e => e.name === 'default');
const is_pk = col.attributes.find(e => e.name === 'id');
if (attr && attr.name !== "relation") {
let type = "String";
if (typeof col.fieldType === "string") type = col.fieldType;
columns[col.name] = {
is_pk: !!is_pk,
type: type.toLowerCase(),
optional: !!col.optional,
db_type: attr.name,
default: default_val
};
}
}
}
return columns;
}
}
}
}
const tableInstance = prisma[table]; const tableInstance = prisma[table];
@ -42,3 +163,29 @@ export const execQuery = async (args: DBArg, prisma: any) => {
} }
} }
}; };
const getFieldAndRef = (rel: any, target: any, table: string) => {
let field = null as unknown as { table: string, fields: string[] };
let ref = null as unknown as { table: string, fields: string[] };
for (const e of rel.args) {
if (typeof e.value === 'object'
&& !Array.isArray(e.value)
&& e.value.type === 'keyValue'
&& typeof e.value.value === 'object'
&& !Array.isArray(e.value.value)
&& e.value.value.type === 'array') {
if (e.value.key === 'fields') {
field = {
table: target.name,
fields: e.value.value.args
}
} else if (e.value.key === 'references') {
ref = {
table: table,
fields: e.value.value.args
}
}
}
}
return { field, ref };
}