Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
dist
.DS_Store
bun.lockb
tester/
bun.lockb
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
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
},
"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
Copy Markdown
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
Copy Markdown

@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
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

👌

"reinstall": "bun run build && npm i -g .",
"createTesterApp": "rm -rf tester/ && bunx create-next-app tester && cd tester/ && kirimase init",
"dev2": "node dist/index.js",
"dev": "tsc -w"
},
Expand All @@ -29,6 +31,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
Copy Markdown
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
27 changes: 13 additions & 14 deletions 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, tableNameKebabCase })
);

// 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 Expand Up @@ -469,19 +481,6 @@ export default function ${tableNameSingularCapitalised}List({
+
</Button>
</div>
{optimistic${tableNamePluralCapitalised}.length === 0 ? (
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

remove this list since it's taken care of by the table

<EmptyState openModal={openModal} />
) : (
<ul>
{optimistic${tableNamePluralCapitalised}.map((${tableNameSingular}) => (
<${tableNameSingularCapitalised}
${tableNameSingular}={${tableNameSingular}}
key={${entityName}.id}
openModal={openModal}
/>
))}
</ul>
)}
</div>
);
}
Expand Down
61 changes: 58 additions & 3 deletions src/commands/generate/generators/views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ import {
toCamelCase,
toNormalEnglish,
} from "../utils.js";
import fs from 'fs';
import { addToShadcnComponentList } from "../../add/utils.js";
import eta from "../../../eta.js";

export const scaffoldViewsAndComponents = async (schema: Schema) => {
const { hasSrc, packages } = readConfigFile();
const {
tableNameCamelCase,
tableNameSingularCapitalised,
tableNameSingular,
tableNameKebabCase,
} = formatTableName(schema.tableName);
// require trpc for these views
Expand All @@ -32,20 +35,34 @@ export const scaffoldViewsAndComponents = async (schema: Schema) => {
rootPath.concat(`app/(app)/${tableNameKebabCase}/page.tsx`),
generateView(schema)
);

// create tableName/[id]/page.tsx
createFile(
formatFilePath(
`app/(app)/${tableNameKebabCase}/[${tableNameSingular}Id]/page.tsx`,
{ removeExtension: false, prefix: "rootPath" }
),
createShowPage(schema)
);
// create components/tableName/TableNameList.tsx
createFile(
rootPath.concat(
`components/${tableNameCamelCase}/${tableNameSingularCapitalised}List.tsx`
),
),
createListComponent(schema)
);
);
// create components/tableName/TableNameForm.tsx
createFile(
rootPath.concat(
`components/${tableNameCamelCase}/${tableNameSingularCapitalised}Form.tsx`
),
createFormComponent(schema)
);
// create components/tableName/columns.tsx
createFile(
rootPath.concat(`components/${tableNameCamelCase}/columns.tsx`),
eta.render('DataTable/columns.eta', { fields: schema.fields, tableNameKebabCase })
);
// create components/tableName/TableNameModal.tsx
createFile(
rootPath.concat(
Expand Down Expand Up @@ -101,6 +118,8 @@ import { api } from "${formatFilePath(trpc.trpcApiTs, {
})}";`
: ""
}
import { DataTable } from "${alias}/components/ui/DataTable";
import { columns } from "${alias}/components/${tableNameCamelCase}/columns";

export default async function ${tableNameCapitalised}() {
${
Expand All @@ -113,13 +132,49 @@ export default async function ${tableNameCapitalised}() {
<h1 className="font-semibold text-2xl my-2">${tableNameNormalEnglishCapitalised}</h1>
<New${tableNameSingularCapitalised}Modal />
</div>
<${tableNameSingularCapitalised}List ${tableNameCamelCase}={${tableNameCamelCase}} />
<DataTable data={${tableNameCamelCase}} columns={columns} />
</main>
);
}
`;
};

const createShowPage = (schema: Schema) => {
const {
tableNameCamelCase,
tableNameSingularCapitalised,
tableNameKebabCase,
tableNameSingular,
tableNameNormalEnglishCapitalised,
} = formatTableName(schema.tableName);
const { trpc } = getFilePaths();
const { alias } = readConfigFile();
const trpcRoute = formatFilePath(trpc.trpcApiTs, {
prefix: "alias",
removeExtension: true,
})
const { fields } = schema;
if (!fs.existsSync(`src/compononents/ui/breadcrumbs.tsx`)) {
createFile(
`src/components/ui/breadcrumbs.tsx`,
eta.render('components/ui/breadcrumbs.eta', {})
)
}

return eta.render(
'resources/show.eta', {
fields,
tableNameSingular,
tableNameSingularCapitalised,
tableNameCamelCase,
tableNameKebabCase,
tableNameNormalEnglishCapitalised,
alias,
trpcRoute
}
)
}

const queryHasJoins = (tableName: string) => {
// const { hasSrc } = readConfigFile();
const { shared } = getFilePaths();
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
Copy Markdown
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
54 changes: 54 additions & 0 deletions src/templates/DataTable/columns.eta
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"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"
import Link from 'next/link'

export const columns: ColumnDef<TData, TValue>[] = [
<% it.fields.map(function (field) { %>
Copy link
Copy Markdown
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 _%>",
enableHiding: false,
cell: ({ row }) => {
const resource = row.original
return (
<Link href={`/<%= it.tableNameKebabCase %>/${resource.id}`}>
{resource.<%_ = field.name _%>}
</Link>
)
},
},
<% }) %>
{
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>
)
},
},
]
Loading