Skip to content
This repository was archived by the owner on Aug 19, 2025. It is now read-only.

Commit 27e1a36

Browse files
Merge pull request #4 from Altroleum/crud-operations
Crud operations
2 parents b945789 + 6d60dad commit 27e1a36

File tree

19 files changed

+1289
-166
lines changed

19 files changed

+1289
-166
lines changed

index.ts

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ const writeFiles = async (
1313
supabaseFile: File,
1414
hookFiles: HookFile[],
1515
metadataFile: File,
16-
componentFiles: File[]
16+
componentFiles: {
17+
tableComponents: File[];
18+
joinTableComponents: File[];
19+
viewComponents: File[];
20+
}
1721
) => {
1822
await writeFile(
1923
`${DIRECTORY}/${supabaseFile.fileName}`,
@@ -29,14 +33,36 @@ const writeFiles = async (
2933
`${DIRECTORY}/${metadataFile.fileName}`,
3034
metadataFile.content
3135
);
32-
await Promise.all(
33-
componentFiles.map((hookFile) => {
36+
37+
const tableComponentPromises = componentFiles.tableComponents.map(
38+
(componentFile) => {
3439
return writeFile(
35-
`${DIRECTORY}/components/${hookFile.fileName}`,
36-
hookFile.content
40+
`${DIRECTORY}/components/tables/${componentFile.fileName}`,
41+
componentFile.content
3742
);
38-
})
43+
}
44+
);
45+
const joinTableComponentPromises = componentFiles.joinTableComponents.map(
46+
(componentFile) => {
47+
return writeFile(
48+
`${DIRECTORY}/components/joinTables/${componentFile.fileName}`,
49+
componentFile.content
50+
);
51+
}
52+
);
53+
const viewComponentPromises = componentFiles.viewComponents.map(
54+
(componentFile) => {
55+
return writeFile(
56+
`${DIRECTORY}/components/views/${componentFile.fileName}`,
57+
componentFile.content
58+
);
59+
}
3960
);
61+
await Promise.all([
62+
...tableComponentPromises,
63+
...joinTableComponentPromises,
64+
...viewComponentPromises,
65+
]);
4066
};
4167

4268
const run = async () => {
@@ -45,7 +71,9 @@ const run = async () => {
4571

4672
await remove(DIRECTORY);
4773
await ensureDir(`${DIRECTORY}/hooks`);
48-
await ensureDir(`${DIRECTORY}/components`);
74+
await ensureDir(`${DIRECTORY}/components/tables`);
75+
await ensureDir(`${DIRECTORY}/components/joinTables`);
76+
await ensureDir(`${DIRECTORY}/components/views`);
4977
await writeFile(`${DIRECTORY}/${types.fileName}`, types.content);
5078

5179
const supabaseFile = await parseSupabaseFile();

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@backengine/codegen",
3-
"version": "1.0.16",
3+
"version": "2.0.0",
44
"description": "Generate code for Backengine projects.",
55
"bin": "build/index.js",
66
"files": [

src/components/index.ts

Lines changed: 22 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,28 @@
1-
import comment from "../comment";
1+
import { fetchTables } from "../pgMeta/fetchTables";
22
import type { File, HookFile } from "../types";
3-
import prettier from "prettier";
4-
import { parseNameFormats } from "../utils";
3+
import { parseComponentFilesForTables } from "./tables";
4+
import { parseComponentFilesForJoinTables } from "./joinTables";
5+
import { parseComponentFilesForViews } from "./views";
56

6-
const mapHookFileToComponent = async (hookFile: HookFile): Promise<File> => {
7-
const {
8-
file: { fileName },
9-
} = hookFile;
10-
11-
const componentName = fileName.replace("use", "");
12-
const { camelCasePlural } = parseNameFormats(componentName);
13-
14-
const content = `
15-
${comment}
16-
17-
"use client";
18-
19-
import ${fileName} from "../hooks/${fileName}";
20-
21-
export default function ${componentName}() {
22-
const { ${camelCasePlural} } = ${fileName}();
23-
24-
return (
25-
<div
26-
style={{
27-
paddingTop: "20px",
28-
}}
29-
>
30-
<code>${camelCasePlural}</code>
31-
<pre
32-
className="border rounded-md text-xs"
33-
style={{
34-
marginTop: "4px",
35-
padding: "16px",
36-
height: "200px",
37-
overflowY: "auto",
38-
}}
39-
>
40-
{JSON.stringify(${camelCasePlural}, null, 2)}
41-
</pre>
42-
</div>
43-
)
44-
};
45-
`;
46-
47-
const formattedContent = await prettier.format(content, {
48-
parser: "typescript",
49-
});
7+
export const parseComponentFiles = async (
8+
hookFiles: HookFile[]
9+
): Promise<{
10+
tableComponents: File[];
11+
joinTableComponents: File[];
12+
viewComponents: File[];
13+
}> => {
14+
const { tables, joinTables } = await fetchTables();
15+
16+
const tableComponents = await parseComponentFilesForTables(hookFiles, tables);
17+
const joinTableComponents = await parseComponentFilesForJoinTables(
18+
hookFiles,
19+
joinTables
20+
);
21+
const viewComponents = await parseComponentFilesForViews(hookFiles);
5022

5123
return {
52-
fileName: `${componentName}.tsx`,
53-
content: formattedContent,
24+
tableComponents,
25+
joinTableComponents,
26+
viewComponents,
5427
};
5528
};
56-
57-
export const parseComponentFiles = async (
58-
hookFiles: HookFile[]
59-
): Promise<File[]> => {
60-
const componentPromises = hookFiles.map(mapHookFileToComponent);
61-
const files = await Promise.all(componentPromises);
62-
return files;
63-
};

src/components/joinTables/get.ts

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import prettier from "prettier";
2+
import comment from "../../comment";
3+
import { TablesResponse } from "../../pgMeta/fetchTables";
4+
import type { File, HookFile } from "../../types";
5+
import { parseFetchFunctionNamesForJoinTable } from "./utils";
6+
7+
export const mapHookFileToGetComponent = async (
8+
hookFile: HookFile,
9+
joinTables: TablesResponse
10+
): Promise<File> => {
11+
const {
12+
entityName,
13+
file: { fileName },
14+
} = hookFile;
15+
16+
const componentName = `${fileName.replace("use", "")}`;
17+
18+
const { tableOneFetchFunctionName, tableTwoFetchFunctionName } =
19+
parseFetchFunctionNamesForJoinTable(joinTables, entityName);
20+
21+
const content = `
22+
${comment}
23+
24+
import { useState } from "react";
25+
import type { TableOneRow, TableTwoRow } from "../../hooks/${fileName}";
26+
27+
export default function Get${componentName}({
28+
${tableOneFetchFunctionName},
29+
${tableTwoFetchFunctionName}
30+
}:
31+
{
32+
${tableOneFetchFunctionName}: (id: TableOneRow["id"]) => Promise<TableTwoRow[]>,
33+
${tableTwoFetchFunctionName}: (id: TableTwoRow["id"]) => Promise<TableOneRow[]>
34+
}) {
35+
const [id, setId] = useState("");
36+
const [data, setData] = useState<TableOneRow[] | TableTwoRow[]>();
37+
38+
return (
39+
<div
40+
style={{
41+
paddingTop: "20px",
42+
}}
43+
>
44+
<pre
45+
className="border rounded-md text-xs"
46+
style={{
47+
marginTop: "4px",
48+
padding: "16px",
49+
height: "200px",
50+
overflowY: "auto",
51+
}}
52+
>
53+
{JSON.stringify(data, null, 2)}
54+
</pre>
55+
<div
56+
className="flex items-center"
57+
style={{
58+
marginTop: "10px",
59+
}}
60+
>
61+
<label
62+
htmlFor="ID"
63+
style={{
64+
flexBasis: "120px",
65+
}}
66+
>
67+
ID
68+
</label>
69+
<input
70+
type="text"
71+
id="ID"
72+
style={{
73+
background: "#000",
74+
color: "#fff",
75+
border: "1px solid #34383A",
76+
marginLeft: "10px",
77+
flex: "1",
78+
borderRadius: "0.375rem",
79+
padding: "4px 16px",
80+
}}
81+
value={id}
82+
onChange={(event) => setId(event.target.value)}
83+
/>
84+
</div>
85+
<div style={{
86+
display: "flex",
87+
marginTop: "10px",
88+
}}>
89+
<button
90+
style={{
91+
background: "#fff",
92+
color: "#000",
93+
padding: "8px 10px",
94+
minWidth: "200px",
95+
borderRadius: "0.375rem",
96+
display: "flex",
97+
alignItems: "center",
98+
justifyContent: "center",
99+
marginRight: "20px",
100+
}}
101+
onClick={() => ${tableOneFetchFunctionName}(id as any).then((data) => setData(data))}
102+
>
103+
<div style={{ marginRight: "10px" }}>Run ${tableOneFetchFunctionName}</div>
104+
<svg
105+
fill="none"
106+
viewBox="0 0 24 24"
107+
strokeWidth={1.5}
108+
stroke="currentColor"
109+
style={{
110+
height: "20px",
111+
}}
112+
>
113+
<path
114+
strokeLinecap="round"
115+
strokeLinejoin="round"
116+
d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z"
117+
/>
118+
</svg>
119+
</button>
120+
<button
121+
style={{
122+
background: "#fff",
123+
color: "#000",
124+
padding: "8px 10px",
125+
minWidth: "200px",
126+
borderRadius: "0.375rem",
127+
display: "flex",
128+
alignItems: "center",
129+
justifyContent: "center",
130+
}}
131+
onClick={() => ${tableTwoFetchFunctionName}(id as any).then((data) => setData(data))}
132+
>
133+
<div style={{ marginRight: "10px" }}>Run ${tableTwoFetchFunctionName}</div>
134+
<svg
135+
fill="none"
136+
viewBox="0 0 24 24"
137+
strokeWidth={1.5}
138+
stroke="currentColor"
139+
style={{
140+
height: "20px",
141+
}}
142+
>
143+
<path
144+
strokeLinecap="round"
145+
strokeLinejoin="round"
146+
d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z"
147+
/>
148+
</svg>
149+
</button>
150+
</div>
151+
</div>
152+
)
153+
};
154+
`;
155+
156+
const formattedContent = await prettier.format(content, {
157+
parser: "typescript",
158+
});
159+
160+
return {
161+
fileName: `Get${componentName}.tsx`,
162+
content: formattedContent,
163+
};
164+
};

src/components/joinTables/index.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import prettier from "prettier";
2+
import comment from "../../comment";
3+
import type { TablesResponse } from "../../pgMeta/fetchTables";
4+
import type { File, HookFile } from "../../types";
5+
import { mapHookFileToGetComponent } from "./get";
6+
import { parseFetchFunctionNamesForJoinTable } from "./utils";
7+
8+
export const mapHookFileToComponent = async (
9+
hookFile: HookFile,
10+
joinTables: TablesResponse
11+
): Promise<File> => {
12+
const {
13+
entityName,
14+
file: { fileName },
15+
} = hookFile;
16+
17+
const componentName = fileName.replace("use", "");
18+
const getComponentName = `Get${componentName}`;
19+
20+
const { tableOneFetchFunctionName, tableTwoFetchFunctionName } =
21+
parseFetchFunctionNamesForJoinTable(joinTables, entityName);
22+
23+
const content = `
24+
${comment}
25+
26+
"use client";
27+
28+
import ${fileName} from "../../hooks/${fileName}";
29+
import ${getComponentName} from "./${getComponentName}";
30+
31+
export default function ${componentName}() {
32+
const { ${tableOneFetchFunctionName}, ${tableTwoFetchFunctionName} } = ${fileName}();
33+
34+
return (
35+
<div>
36+
<${getComponentName} ${tableOneFetchFunctionName}={${tableOneFetchFunctionName}} ${tableTwoFetchFunctionName}={${tableTwoFetchFunctionName}} />
37+
</div>
38+
)
39+
};
40+
`;
41+
42+
const formattedContent = await prettier.format(content, {
43+
parser: "typescript",
44+
});
45+
46+
return {
47+
fileName: `${componentName}.tsx`,
48+
content: formattedContent,
49+
};
50+
};
51+
52+
export const parseComponentFilesForJoinTables = async (
53+
hookFiles: HookFile[],
54+
joinTables: TablesResponse
55+
): Promise<File[]> => {
56+
const joinTableHookFiles = hookFiles.filter(
57+
(hookFile) => hookFile.entityType === "JOIN_TABLE"
58+
);
59+
60+
const componentPromises = joinTableHookFiles.map((joinTableHookFile) =>
61+
mapHookFileToComponent(joinTableHookFile, joinTables)
62+
);
63+
const getComponentPromises = joinTableHookFiles.map((joinTableHookFile) =>
64+
mapHookFileToGetComponent(joinTableHookFile, joinTables)
65+
);
66+
67+
const files = await Promise.all([
68+
...componentPromises,
69+
...getComponentPromises,
70+
]);
71+
return files;
72+
};

0 commit comments

Comments
 (0)