Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
dist
.DS_Store
tester/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ To run locally:

```sh
pnpm i
pnpm run dev
pnpm run build

npm install -g . (in a second terminal - this will then make kirimase available across your machine using "kirimase *command*")
```
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "npx tsc",
"build": "npx tsc && rm -rf dist/templates && cp -r src/templates dist/templates",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if there is a better way to do this, but I figured this is at least a quick and dirty way to pull templates into the dist folder.

Copy link

@OmegaHawkeye OmegaHawkeye Mar 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally used a npm package called typescript-cp for it and then just using the watch flag in dev and without it when building it.

Edit: I'm also using npm-run-all to run the dev scripts in parallel. I dont like concurrently so I used npm-run-all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

"dev2": "node dist/index.js",
"dev": "tsc -w"
},
Expand All @@ -30,6 +30,7 @@
"chalk": "^5.3.0",
"commander": "^11.0.0",
"consola": "^3.2.3",
"eta": "^3.2.0",
"execa": "^8.0.1",
"figlet": "^1.7.0",
"ora": "^8.0.1",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions src/commands/add/componentLib/shadcn-ui/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { consola } from "consola";
// import { execa } from "execa";
import { existsSync } from "fs";
import { eta } from "../../../../eta.js";
import {
addPackageToConfig,
createFile,
Expand Down Expand Up @@ -47,6 +48,7 @@ const manualInstallShadCn = async (

addToInstallList({
regular: [
"@tanstack/react-table",
"tailwindcss-animate",
"class-variance-authority",
"clsx",
Expand Down Expand Up @@ -85,6 +87,16 @@ const manualInstallShadCn = async (
rootPath.concat("components/ui/ThemeToggle.tsx"),
generateThemeToggler()
);

// generate base Data Table
createFile(
rootPath.concat("components/ui/DataTable/index.tsx"),
eta.render("DataTable/index.eta", {})
);
createFile(
rootPath.concat("components/ui/DataTable/pagination.tsx"),
eta.render("DataTable/pagination.eta", {})
);
// add context provider to layout
addContextProviderToRootLayout("ThemeProvider");
};
Expand Down Expand Up @@ -131,6 +143,8 @@ export const installShadcnUI = async (
// "label",
// ]);
addToShadcnComponentList([
"table",
"pagination",
"button",
"sonner",
"avatar",
Expand Down
2 changes: 1 addition & 1 deletion src/commands/add/orm/drizzle/generators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ export const addScriptsToPackageJson = (
"db:migrate": `tsx ${libPath}/db/migrate.ts`,
"db:drop": "drizzle-kit drop",
"db:pull": `drizzle-kit introspect:${driver}`,
...(driver !== "pg" ? { "db:push": `drizzle-kit push:${driver}` } : {}),
"db:push": `drizzle-kit push:${driver}`,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the guardrails around db:push for pg, now that it's supported.

"db:studio": "drizzle-kit studio",
"db:check": `drizzle-kit check:${driver}`,
};
Expand Down
1 change: 0 additions & 1 deletion src/commands/add/orm/drizzle/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ ${nanoidContent.split("\n")[1].trim()}
replaceFile(utilsPath, newContent);
}
};

export const checkTimestampsInUtils = () => {
const timestampsContent = `export const timestamps: { createdAt: true; updatedAt: true } = {
createdAt: true,
Expand Down
14 changes: 13 additions & 1 deletion src/commands/generate/generators/views-with-server-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { formatTableName, toCamelCase } from "../utils.js";
import { existsSync, readFileSync } from "fs";
import { consola } from "consola";
import { addToShadcnComponentList } from "../../add/utils.js";
import eta from "../../../eta.js";

export const scaffoldViewsAndComponentsWithServerActions = async (
schema: ExtendedSchema
Expand Down Expand Up @@ -80,6 +81,15 @@ export const scaffoldViewsAndComponentsWithServerActions = async (
createListComponent(schema)
);

// create columns
createFile(
formatFilePath(
`app/(app)/${tableNameKebabCase}/columns.tsx`,
{ prefix: "rootPath", removeExtension: false }
),
eta.render('DataTable/columns.eta', { fields: schema.fields })
);

// create components/tableName/TableNameForm.tsx
createFile(
formatFilePath(
Expand Down Expand Up @@ -251,7 +261,8 @@ const generateView = (schema: Schema) => {
const relationsFormatted = formatRelations(relations);

return `import { Suspense } from "react";

import { DataTable } from "${formatFilePath(`components/ui/DataTable`, {prefix: "alias", removeExtension: false})}";
import { columns } from "./columns";
import Loading from "${formatFilePath("app/loading", {
prefix: "alias",
removeExtension: false,
Expand Down Expand Up @@ -313,6 +324,7 @@ const ${tableNameCapitalised} = async () => {
.join(" ")
: ""
} />
<DataTable data={${tableNameCamelCase}} columns={columns} />
</Suspense>
);
};
Expand Down
9 changes: 9 additions & 0 deletions src/commands/generate/generators/views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
toNormalEnglish,
} from "../utils.js";
import { addToShadcnComponentList } from "../../add/utils.js";
import eta from "../../../eta.js";

export const scaffoldViewsAndComponents = async (schema: Schema) => {
const { hasSrc, packages } = readConfigFile();
Expand Down Expand Up @@ -46,6 +47,11 @@ export const scaffoldViewsAndComponents = async (schema: Schema) => {
),
createFormComponent(schema)
);
// create components/tableName/columns.tsx
createFile(
rootPath.concat(`components/${tableNameCamelCase}/columns.tsx`),
eta.render('DataTable/columns.eta', { fields: schema.fields });
);
// create components/tableName/TableNameModal.tsx
createFile(
rootPath.concat(
Expand Down Expand Up @@ -101,6 +107,8 @@ import { api } from "${formatFilePath(trpc.trpcApiTs, {
})}";`
: ""
}
import { DataTable } from "${alias}/components/ui/dataTable";
import { columns } from "./columns";

export default async function ${tableNameCapitalised}() {
${
Expand All @@ -113,6 +121,7 @@ export default async function ${tableNameCapitalised}() {
<h1 className="font-semibold text-2xl my-2">${tableNameNormalEnglishCapitalised}</h1>
<New${tableNameSingularCapitalised}Modal />
</div>
<DataTable data={${tableNameCamelCase}} columns={columns} />
<${tableNameSingularCapitalised}List ${tableNameCamelCase}={${tableNameCamelCase}} />
</main>
);
Expand Down
2 changes: 1 addition & 1 deletion src/commands/init/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,4 +268,4 @@ export const toggleAnalytics = (input: { toggle?: boolean }) => {
`Anonymous analytics are currently ${analytics ? "on" : "off"}`
);
}
};
};
9 changes: 9 additions & 0 deletions src/eta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Eta } from "eta"
import path from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export const eta = new Eta({ views: path.join(__dirname, "templates") });
export default eta;
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ addCommonOptions(program.command("init"))

program
.command("generate")
.alias("g")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alias 😎

.description("Generate a new resource")
.action(buildSchema);

Expand Down
44 changes: 44 additions & 0 deletions src/templates/DataTable/columns.eta
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"use client"
import { MoreHorizontal } from "lucide-react"
import {
ColumnDef,
} from "@tanstack/react-table"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { Button } from "@/components/ui/button"

export const columns: ColumnDef<TData, TValue>[] = [
<% it.fields.map(function (field) { %>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

templating in action

{
accessorKey: "<%_ = field.name _%>",
header: "<%_ = field.name _%>",
},
<% }) %>
{
id: "actions",
enableHiding: false,
cell: ({ row }) => {
const resource = row.original
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="square-8 p-0">
<span className="sr-only">Open menu</span>
<MoreHorizontal className="square-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem>Edit</DropdownMenuItem>
<DropdownMenuItem>Delete</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
},
},
]
133 changes: 133 additions & 0 deletions src/templates/DataTable/index.eta
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
"use client"
import * as React from "react"
import {
VisibilityState,
flexRender,
getCoreRowModel,
getPaginationRowModel,
useReactTable,
} from "@tanstack/react-table"
import { ArrowUpDown, ChevronDown, MoreHorizontal } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import { DataTablePagination } from './pagination'

export interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
}

export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({})

const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onColumnVisibilityChange: setColumnVisibility,
state: {
columnVisibility,
},
})

return (
<div className="w-full">
<div className="flex items-center py-4">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="ml-auto">
Columns <ChevronDown className="ml-2 h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{table
.getAllColumns()
.filter((column) => column.getCanHide())
.map((column) => {
return (
<DropdownMenuCheckboxItem
key={column.id}
className="capitalize"
checked={column.getIsVisible()}
onCheckedChange={(value) =>
column.toggleVisibility(!!value)
}
>
{column.id}
</DropdownMenuCheckboxItem>
)
})}
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
)
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<DataTablePagination table={table} />
</div>
)
}
Loading