Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#3748 Add custom template option back to blitz generate command #3866

Merged
merged 25 commits into from
Oct 12, 2022
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c139faa
Update generate.ts
siddhsuresh Sep 26, 2022
3131586
add custom template back to toolkit
siddhsuresh Sep 26, 2022
c85f85d
cleanup
siddhsuresh Sep 26, 2022
d260c09
update blitz-server.ts when user generates custom templates
siddhsuresh Sep 27, 2022
5388347
Merge branch 'add-custom-template' of https://github.com/siddhsuresh/…
siddhsuresh Sep 27, 2022
19d2ba6
add to help
siddhsuresh Sep 27, 2022
6985dd9
fix blitz-server loading in javascript
siddhsuresh Sep 27, 2022
78fcc2a
Create slow-impalas-tap.md
siddhsuresh Sep 27, 2022
1c20794
Merge branch 'main' into add-custom-template
Sep 28, 2022
5409cf1
convert flag to command, default export to named export cliConfig
siddhsuresh Sep 29, 2022
4189312
fix types
siddhsuresh Sep 29, 2022
f62d248
update changeset
siddhsuresh Sep 29, 2022
fea099e
update changeset
siddhsuresh Sep 29, 2022
3e996c9
Merge branch 'main' into add-custom-template
siddhsuresh Sep 29, 2022
9cdafa4
update type from BlitzServerConfig to BlitzCliConfig
siddhsuresh Sep 29, 2022
c5cdcc6
Merge branch 'main' into add-custom-template
siddhsuresh Sep 29, 2022
5de52e0
Merge branch 'main' into add-custom-template
siddhsuresh Sep 30, 2022
b59ab74
Merge branch 'main' into add-custom-template
siddhsuresh Oct 3, 2022
b719d8e
Merge branch 'main' into add-custom-template
Oct 3, 2022
6677040
Merge branch 'main' into add-custom-template
siddhsuresh Oct 4, 2022
a17db35
Merge branch 'main' into add-custom-template
siddhsuresh Oct 4, 2022
16ce7ad
Update .changeset/slow-impalas-tap.md
siddhsuresh Oct 11, 2022
b4db9d3
Merge branch 'main' into add-custom-template
siddhsuresh Oct 11, 2022
7690ad2
update pnpm-lock
siddhsuresh Oct 11, 2022
490ea3f
Merge branch 'main' into add-custom-template
siddhsuresh Oct 12, 2022
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
6 changes: 6 additions & 0 deletions .changeset/slow-impalas-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"blitz": patch
"@blitzjs/generator": patch
---

#3748 Add custom template usage back to toolkit, and a new command `blitz generate custom-templates` to provide an easy starting point for users to customize the default templates.
siddhsuresh marked this conversation as resolved.
Show resolved Hide resolved
5 changes: 5 additions & 0 deletions apps/toolkit-app/app/blitz-server.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { BlitzCliConfig } from "blitz"
import { setupBlitzServer } from "@blitzjs/next"
import { AuthServerPlugin, PrismaStorage } from "@blitzjs/auth"
import db from "db"
Expand All @@ -14,3 +15,7 @@ const { gSSP, gSP, api } = setupBlitzServer({
})

export { gSSP, gSP, api }

export const cliConfig: BlitzCliConfig = {
customTemplates: "app/templates",
}
59 changes: 59 additions & 0 deletions packages/blitz/src/cli/commands/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import {
MutationsGenerator,
ModelGenerator,
QueryGenerator,
addCustomTemplatesBlitzConfig,
} from "@blitzjs/generator"
import {log} from "../../logging"

const getIsTypeScript = async () =>
require("fs").existsSync(require("path").join(process.cwd(), "tsconfig.json"))
Expand All @@ -30,6 +32,7 @@ enum ResourceType {
Mutations = "mutations",
Mutation = "mutation",
Resource = "resource",
CustomTemplates = "custom-templates",
}

function modelName(input: string = "") {
Expand All @@ -45,6 +48,39 @@ function ModelNames(input: string = "") {
return pluralPascal(input)
}

const createCustomTemplates = async () => {
const continuePrompt = await prompts({
type: "confirm",
name: "value",
message: `This will copy the default templates to your app/templates folder. Do you want to continue?`,
})
if (!continuePrompt.value) {
process.exit(0)
}
const templatesPath = await prompts({
type: "text",
name: "value",
message: `Enter the path to save the custom templates folder`,
initial: "app/templates",
})
const templatesPathValue: string = templatesPath.value
const isTypeScript = await getIsTypeScript()
addCustomTemplatesBlitzConfig(templatesPathValue, isTypeScript)
log.success(`🚀 Custom templates path added/updated in app/blitz-server file`)
const customTemplatesPath = require("path").join(process.cwd(), templatesPathValue)
const fsExtra = await import("fs-extra")
const blitzGeneratorPath = require.resolve("@blitzjs/generator")
const templateFolder = ["form", "page", "query", "mutation", "queries", "mutations"]
for (const template of templateFolder) {
await fsExtra.copy(
require("path").join(blitzGeneratorPath, "..", "templates", template),
require("path").join(customTemplatesPath, template),
)
}
log.success(`🚀 Custom templates created in ${templatesPathValue} directory`)
process.exit(0)
}

const generatorMap = {
[ResourceType.All]: [
PageGenerator,
Expand All @@ -61,6 +97,7 @@ const generatorMap = {
[ResourceType.Mutations]: [MutationsGenerator],
[ResourceType.Mutation]: [MutationGenerator],
[ResourceType.Resource]: [QueriesGenerator, MutationsGenerator, ModelGenerator],
[ResourceType.CustomTemplates]: [],
}

const args = arg(
Expand Down Expand Up @@ -199,6 +236,13 @@ const getHelp = async () => {

> blitz generate all tasks --parent=projects

# To customize the templates used by the blitz generate command,

> blitz generate custom-templates

This command will copy the default templates to your app and update the app/blitz-server file to enable
the custom templating feature of the blitz CLI

# Database models can also be generated directly from the CLI.
Model fields can be specified with any generator that generates a database model ("all", "model", "resource").
Both of the commands below will generate the proper database model for a Task.
Expand All @@ -216,6 +260,9 @@ const getHelp = async () => {
const generate: CliCommand = async () => {
await getHelp()
await determineType()
if (selectedType === "custom-templates") {
await createCustomTemplates()
}
if (!selectedModelName) {
await determineName()
}
Expand All @@ -227,9 +274,21 @@ const generate: CliCommand = async () => {

const generators = generatorMap[selectedType as keyof typeof generatorMap]

const isTypeScript = await getIsTypeScript()
const blitzServerPath = isTypeScript ? "app/blitz-server.ts" : "app/blitz-server.js"
const blitzServer = require("path").join(process.cwd(), blitzServerPath)
const {register} = require("esbuild-register/dist/node")
const {unregister} = register({
target: "es6",
})
const blitzConfig = require(blitzServer)
const {cliConfig} = blitzConfig
unregister()

for (const GeneratorClass of generators) {
const generator = new GeneratorClass({
destinationRoot: require("path").resolve(),
templateDir: cliConfig?.customTemplates,
extraArgs: args["_"].slice(3) as string[],
modelName: singularRootContext,
modelNames: modelNames(singularRootContext),
Expand Down
4 changes: 4 additions & 0 deletions packages/blitz/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ export interface RouteUrlObject extends Pick<UrlObject, "pathname" | "query"> {
pathname: string
}

export type BlitzCliConfig = {
customTemplates?: string
}

export const isRouteUrlObject = (x: any): x is RouteUrlObject => {
return typeof x === "object" && "pathname" in x && typeof x.pathname === "string"
}
Expand Down
82 changes: 82 additions & 0 deletions packages/generator/src/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,88 @@ import {readdirRecursive} from "./utils/readdir-recursive"
import prettier from "prettier"
const debug = require("debug")("blitz:generator")

export const addCustomTemplatesBlitzConfig = (
customTemplatesPath: string,
isTypeScript: boolean,
) => {
const blitzServer = isTypeScript ? "app/blitz-server.ts" : "app/blitz-server.js"
const blitzServerPath = require("path").join(process.cwd(), blitzServer)
const userConfigModuleSource = fs.readFileSync(blitzServerPath, {encoding: "utf-8"})
const userConfigModule = j(userConfigModuleSource, {parser: customTsParser})
const program = userConfigModule.get()
const cliConfigDeclaration = userConfigModule
.find(j.ExportNamedDeclaration, {
declaration: {
type: "VariableDeclaration",
beerose marked this conversation as resolved.
Show resolved Hide resolved
declarations: [
{
id: {
name: "cliConfig",
},
},
],
},
})
.paths()
.at(0)
if (!cliConfigDeclaration) {
const config = j.identifier("cliConfig")
const configVariable = j.variableDeclaration("const", [
j.variableDeclarator(
config,
j.objectExpression([
j.objectProperty(j.identifier("customTemplates"), j.literal(customTemplatesPath)),
]),
),
])
if (isTypeScript) {
const type = j.tsTypeAnnotation(j.tsTypeReference(j.identifier("BlitzCliConfig")))
const declaration: any = configVariable?.declarations
declaration[0].id.typeAnnotation = type
const typeImport = j.importDeclaration(
[j.importSpecifier(j.identifier("BlitzCliConfig"))],
j.literal("blitz"),
)
typeImport.importKind = "type"
program.node.program.body.unshift(typeImport)
}
const exportConfig = j.exportNamedDeclaration(configVariable)
program.node.program.body.push(exportConfig)
} else {
const configType = cliConfigDeclaration.value.declaration?.type
if (configType === "VariableDeclaration") {
const config = cliConfigDeclaration.value.declaration.declarations[0]
if (config?.type === "VariableDeclarator") {
const configProperties = config.init
if (configProperties?.type === "ObjectExpression") {
const customTemplatesProperty = configProperties.properties.find((property) => {
if (property.type === "ObjectProperty") {
const key = property.key
if (key.type === "Identifier") {
return key.name === "customTemplates"
}
}
})
if (!customTemplatesProperty) {
configProperties.properties.push(
j.objectProperty(j.identifier("customTemplates"), j.literal(customTemplatesPath)),
)
} else {
if (customTemplatesProperty.type === "ObjectProperty") {
const customValue = customTemplatesProperty.value
if (customValue.type === "StringLiteral") {
customValue.value = customTemplatesPath
}
}
}
}
}
}
}
const newSource = userConfigModule.toSource()
fs.writeFileSync(blitzServerPath, newSource)
}

export const customTsParser = {
parse(source: string, options?: Overrides) {
const babelOptions = getBabelOptions(options)
Expand Down