omni-rest 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -698,10 +698,7 @@ function resolveOutputDir(frontendDir, framework, outFlag) {
698
698
  if (structure.usesSrc) {
699
699
  return path3.resolve(frontendDir, "src");
700
700
  }
701
- if (framework === "nextjs" && structure.usesAppRouter) {
702
- return path3.resolve(frontendDir, "app");
703
- }
704
- return path3.resolve(frontendDir, "src");
701
+ return frontendDir;
705
702
  }
706
703
  var BASE_PACKAGES = [
707
704
  "@tanstack/react-query",
@@ -1104,15 +1101,19 @@ function generateTableFile(config, modelConfig) {
1104
1101
  lines.push(`'use client'`);
1105
1102
  lines.push(``);
1106
1103
  }
1107
- lines.push(`import { DataTable } from "../data-table";`);
1108
- lines.push(`import { ${columnsVar} } from "./${Model}Columns";`);
1109
1104
  const hookImports = [useListHook, useDeleteHook];
1110
1105
  if (bulkDelete) {
1111
1106
  hookImports.push(useBulkDeleteHook);
1112
1107
  }
1113
- lines.push(`import { ${hookImports.join(", ")} } from "../hooks/use${Model}";`);
1108
+ lines.push(`import { useState } from "react";`);
1109
+ lines.push(`import DataTable from "../data-table";`);
1110
+ lines.push(`import { ${columnsVar} } from "./${Model}Columns";`);
1111
+ lines.push(`import { ${hookImports.join(", ")} } from "../../hooks/use${Model}";`);
1112
+ lines.push(`import { ${Model}Form } from "./${Model}Form";`);
1113
+ lines.push(`import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "../ui/dialog";`);
1114
1114
  lines.push(``);
1115
1115
  lines.push(`export function ${Model}Table() {`);
1116
+ lines.push(` const [isCreateOpen, setIsCreateOpen] = useState(false);`);
1116
1117
  lines.push(` const { data } = ${useListHook}();`);
1117
1118
  lines.push(` const ${varName}Delete = ${useDeleteHook}();`);
1118
1119
  if (bulkDelete) {
@@ -1120,22 +1121,40 @@ function generateTableFile(config, modelConfig) {
1120
1121
  }
1121
1122
  lines.push(``);
1122
1123
  lines.push(` return (`);
1124
+ lines.push(` <>`);
1123
1125
  const dtProps = [
1124
- ` columns={${columnsVar}}`,
1125
- ` data={data?.data ?? []}`,
1126
- ` onRowDelete={(row) => ${varName}Delete.mutate(row.id)}`
1126
+ ` title="${models}"`,
1127
+ ` description="Manage ${models.toLowerCase()} in your system"`,
1128
+ ` columns={${columnsVar}}`,
1129
+ ` data={data?.data ?? []}`,
1130
+ ` toggleAction={() => setIsCreateOpen(true)}`,
1131
+ ` actionText="Create ${Model}"`,
1132
+ ` onRowDelete={(row: any) => ${varName}Delete.mutate(row.id)}`
1127
1133
  ];
1128
1134
  if (bulkDelete) {
1129
- dtProps.push(` onMultiDelete={(rows) => ${varName}BulkDelete.mutate(rows.map((r) => r.id))}`);
1135
+ dtProps.push(` onMultiDelete={(rows: any[]) => ${varName}BulkDelete.mutate(rows.map((r) => r.id))}`);
1130
1136
  }
1131
1137
  if (canExport) {
1132
- dtProps.push(` canExport={true}`);
1138
+ dtProps.push(` canExport={true}`);
1133
1139
  }
1134
- lines.push(` <DataTable`);
1140
+ lines.push(` <DataTable`);
1135
1141
  for (const prop of dtProps) {
1136
1142
  lines.push(prop);
1137
1143
  }
1138
- lines.push(` />`);
1144
+ lines.push(` />`);
1145
+ lines.push(``);
1146
+ lines.push(` <Dialog open={isCreateOpen} onOpenChange={setIsCreateOpen}>`);
1147
+ lines.push(` <DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto">`);
1148
+ lines.push(` <DialogHeader>`);
1149
+ lines.push(` <DialogTitle>Create New ${Model}</DialogTitle>`);
1150
+ lines.push(` <DialogDescription>`);
1151
+ lines.push(` Fill in the information below to create a new ${varName}.`);
1152
+ lines.push(` </DialogDescription>`);
1153
+ lines.push(` </DialogHeader>`);
1154
+ lines.push(` <${Model}Form onSuccess={() => setIsCreateOpen(false)} />`);
1155
+ lines.push(` </DialogContent>`);
1156
+ lines.push(` </Dialog>`);
1157
+ lines.push(` </>`);
1139
1158
  lines.push(` );`);
1140
1159
  lines.push(`}`);
1141
1160
  lines.push(``);
@@ -1164,17 +1183,17 @@ function generateFormFile(config, modelConfig) {
1164
1183
  }
1165
1184
  }
1166
1185
  lines.push(`import { FormGenerator } from "../form-generator";`);
1167
- lines.push(`import { ${name}Schema } from "src/schemas.generated";`);
1186
+ lines.push(`import { ${name}CreateSchema } from "../../schemas.generated";`);
1168
1187
  lines.push(
1169
- `import { useCreate${name}, useUpdate${name} } from "../hooks/use${name}";`
1188
+ `import { useCreate${name}, useUpdate${name} } from "../../hooks/use${name}";`
1170
1189
  );
1171
1190
  for (const { relatedModel } of relationalFieldMeta) {
1172
1191
  lines.push(
1173
- `import { use${relatedModel}s } from "../hooks/use${relatedModel}";`
1192
+ `import { use${relatedModel}s } from "../../hooks/use${relatedModel}";`
1174
1193
  );
1175
1194
  }
1176
1195
  lines.push(``);
1177
- lines.push(`export function ${name}Form({ id }: { id?: string }) {`);
1196
+ lines.push(`export function ${name}Form({ id, onSuccess }: { id?: string; onSuccess?: () => void }) {`);
1178
1197
  lines.push(` const create${name} = useCreate${name}();`);
1179
1198
  lines.push(` const update${name} = useUpdate${name}();`);
1180
1199
  for (const { fieldName, relatedModel } of relationalFieldMeta) {
@@ -1224,24 +1243,36 @@ function generateFormFile(config, modelConfig) {
1224
1243
  });
1225
1244
  lines.push(` ];`);
1226
1245
  lines.push(``);
1246
+ lines.push(` const handleSubmit = (data: any) => {`);
1247
+ lines.push(` const mutation = id ? update${name}.mutate({ id, data }) : create${name}.mutate(data);`);
1248
+ lines.push(` if (onSuccess) {`);
1249
+ lines.push(` // Call onSuccess after mutation completes`);
1250
+ lines.push(` Promise.resolve(mutation).then(() => onSuccess()).catch(() => {});`);
1251
+ lines.push(` }`);
1252
+ lines.push(` };`);
1253
+ lines.push(``);
1227
1254
  lines.push(` return (`);
1228
1255
  lines.push(` <FormGenerator`);
1229
1256
  lines.push(` fields={fields}`);
1230
- lines.push(` schema={${name}Schema}`);
1231
- lines.push(
1232
- ` onSubmit={(data) => id ? update${name}.mutate({ id, data }) : create${name}.mutate(data)}`
1233
- );
1257
+ lines.push(` schema={${name}CreateSchema}`);
1258
+ lines.push(` onSubmit={handleSubmit}`);
1234
1259
  lines.push(` steps={steps}`);
1235
1260
  lines.push(` />`);
1236
1261
  lines.push(` );`);
1237
1262
  } else {
1263
+ lines.push(` const handleSubmit = (data: any) => {`);
1264
+ lines.push(` const mutation = id ? update${name}.mutate({ id, data }) : create${name}.mutate(data);`);
1265
+ lines.push(` if (onSuccess) {`);
1266
+ lines.push(` // Call onSuccess after mutation completes`);
1267
+ lines.push(` Promise.resolve(mutation).then(() => onSuccess()).catch(() => {});`);
1268
+ lines.push(` }`);
1269
+ lines.push(` };`);
1270
+ lines.push(``);
1238
1271
  lines.push(` return (`);
1239
1272
  lines.push(` <FormGenerator`);
1240
1273
  lines.push(` fields={fields}`);
1241
- lines.push(` schema={${name}Schema}`);
1242
- lines.push(
1243
- ` onSubmit={(data) => id ? update${name}.mutate({ id, data }) : create${name}.mutate(data)}`
1244
- );
1274
+ lines.push(` schema={${name}CreateSchema}`);
1275
+ lines.push(` onSubmit={handleSubmit}`);
1245
1276
  lines.push(` />`);
1246
1277
  lines.push(` );`);
1247
1278
  }
@@ -1317,6 +1348,35 @@ function generateMenuData(config) {
1317
1348
  lines.push(``);
1318
1349
  return lines.join("\n");
1319
1350
  }
1351
+
1352
+ // src/frontend/codegen/providers.ts
1353
+ function generateProvidersFile(config) {
1354
+ const { staleTime, gcTime } = config;
1355
+ const lines = [];
1356
+ lines.push(`'use client'`);
1357
+ lines.push(``);
1358
+ lines.push(`import { QueryClient, QueryClientProvider } from '@tanstack/react-query'`);
1359
+ lines.push(`import { useState } from 'react'`);
1360
+ lines.push(``);
1361
+ lines.push(`export function Providers({ children }: { children: React.ReactNode }) {`);
1362
+ lines.push(` const [queryClient] = useState(() => new QueryClient({`);
1363
+ lines.push(` defaultOptions: {`);
1364
+ lines.push(` queries: {`);
1365
+ lines.push(` staleTime: ${staleTime},`);
1366
+ lines.push(` gcTime: ${gcTime},`);
1367
+ lines.push(` },`);
1368
+ lines.push(` },`);
1369
+ lines.push(` }))`);
1370
+ lines.push(``);
1371
+ lines.push(` return (`);
1372
+ lines.push(` <QueryClientProvider client={queryClient}>`);
1373
+ lines.push(` {children}`);
1374
+ lines.push(` </QueryClientProvider>`);
1375
+ lines.push(` )`);
1376
+ lines.push(`}`);
1377
+ lines.push(``);
1378
+ return lines.join("\n");
1379
+ }
1320
1380
  var GREEN = "\x1B[32m";
1321
1381
  var YELLOW = "\x1B[33m";
1322
1382
  var BLUE = "\x1B[34m";
@@ -1427,6 +1487,11 @@ async function generateAll(config) {
1427
1487
  }
1428
1488
  const baseResults = await copyBaseComponents(outputDir, packageRoot);
1429
1489
  results.push(...baseResults);
1490
+ if (framework === "nextjs" && structure.usesAppRouter) {
1491
+ const providersContent = generateProvidersFile(config);
1492
+ const providersPath = path3.join(outputDir, "components", "providers.tsx");
1493
+ results.push(await writeFile(providersPath, providersContent));
1494
+ }
1430
1495
  if (generateMenu) {
1431
1496
  const menuContent = generateMenuData(config);
1432
1497
  const menuPath = path3.join(outputDir, "lib", "menu-data.ts");