Open EthanThatOneKid opened 1 year ago
This feels a lot like a task runner, but we already have deno task
. Do you think perhaps this could be rolled into a script in userland, then people could do deno task generate
?
This feels a lot like a task runner, but we already have
deno task
. Do you think perhaps this could be rolled into a script in userland, then people could dodeno task generate
?
I think is very doable to at least move forward with deno task generate
. It sounds like a fun project, and I am more than happy to work on it. This way, other developers will be able to easily adopt the convention and benefit from it.
The userland script is now available under https://deno.land/x/generate! Check it out:
deno task generate
deno.jsonc
{
"tasks": {
"generate": "deno run -Ar https://deno.land/x/generate/cli/main.ts --verbose generator.ts"
}
}
generator.ts
The provided code generates basic TypeScript code using a for loop to export constants.
//deno:generate deno run -A generate.ts
for (let i = 0; i < 10; i++) {
console.log(`export const example${i} = ${i};`);
}
generate.ts
// Create a child process using Deno.Command, running the "generate.ts" script.
const generatorChild = new Deno.Command(Deno.execPath(), {
args: ["run", "generator.ts"],
stdin: "piped",
stdout: "piped",
}).spawn();
// Create another child process, running deno fmt.
const fmtChild = new Deno.Command(Deno.execPath(), {
args: ["fmt", "-"],
stdin: "piped",
stdout: "piped",
}).spawn();
// Pipe the current process stdin to the child process stdin.
generatorChild.stdout.pipeTo(fmtChild.stdin);
// Close the child process stdin.
generatorChild.stdin.close();
// Pipe the child process stdout to a writable file named "generated.ts".
fmtChild.stdout.pipeTo(
Deno.openSync("generated.ts", { write: true, create: true }).writable,
);
@EthanThatOneKid I'm agree there is need for generating code, myself I created small tool for this perpose: https://github.com/elycheikhsmail/templatify-code. But should this tool implemented in deno cli ? or as third party library ? or in deno std ?
I'm agree there is need for generating code, myself I created small tool for this perpose: https://github.com/elycheikhsmail/templatify-code. But should this tool implemented in deno cli ? or as third party library ? or in deno std ?
Thank you for sharing your project templatify-code, @elycheikhsmail! templatify-code is a tool which seems to be compatible with //deno:generate
.
Given that Deno draws inspiration from Go, I believe a deno generate
subcommand should be added to the official Deno CLI. In the Go community, go generate
brings about convenience and wider adoption of code generation.
As someone who embeds stuff often, I've definitely considered features like this. In this proposals current form, I think/agree it would be best as a 3rd party module.
However, I do think there is something more minimal/generic that is worth proposing as a change to deno.
For code generation and file embedding to work seamlessly, I believe we need an at-compile-time hook. JSX is already effectively a compile time hook. But in terms of custom hooks, AFAIK it is currently not possible to have deno run some code (or command) whenever deno bundle
or deno compile
is run, aside from making some hacky shell wrapper around the deno command that intercepts the compile command.
A Deno compile time hook would combine nicely with a 3rd party deno-generate command.
My recommended syntax would be similar to the JSX hook:
/** @deno:onCompile
*
* import { run } from "deno.land/x/deno-generate"
* run`deno run -A generate.ts`
*/
Wanted to pitch in a suggestion. Use case: I use utility functions to parse different measures written in different systems, depending mostly on locale, over 300 such utility functions and counting. I don't want to pass the locale for each call (locale is the same for all calls in a specific context). I also don't want to use a generator function for all the code and lose tree shaking.
It would be great if a deno native code generator would tie in with ESM module resolution and make it easy for me to import utils.ts?locale=en-US
or ./en-US/utils.ts?generate=true
. It would JIT generate only imported code variants and cache them, making code-gen maintenance easier than current solutions.
Code generation has long been a valuable tool for developers, enabling us to automate repetitive tasks and improve the quality of our code. The introduction of the
deno generate
subcommand to the Deno toolchain has the potential to make code generation even more accessible and powerful. This feature could help developers to save time and effort, and to produce more consistent and reliable code.Design overview
Add a
deno generate
subcommand to automate code generation by running procedures defined in comment annotations. Thedeno generate
subcommand should scan entrypoint files for directives, which are lines starting with the comment:Where
command
is the generator corresponding to an executable file that can be run locally. Arguments are passed to the generator as command line arguments.When the
deno generate
command is executed, module graphs are initialized for each valid entry point. Thedeno generate
subcommand will then scan each module graph for directives. If a directive is found, the generator is run with the arguments provided in the directive. The generator is run from the directory containing the directive.Desired features
deno generate
and apply the command on each valid Deno entry point file in the current directory if no entry points are listed. Allow users to list space-separated files as entry points.//deno:generate -command <command> [arguments...]
directive.//deno:generate
commands in VSCode).//deno:generate
generator runs independently, and the failure of one command doesn't stop or impact the execution of other commands. A failed command generates an error message or exit code for itself without affecting the rest of the commands.deno generate
:--files
to specify which files to ignore and include.--run
to specify a command to run.--skip
to specify a command to skip. In the event that a command matches both the--run
and--skip
regular expressions, the command is skipped.--dry-run
to print the commands that would be run without actually running them.--verbose
to print the module specifier and directive text of each directive when running the corresponding generator.--trace
to print the commands as they are run.Help text
I have drafted the following help text for the
deno generate
subcommand:Conventions
Pre-commit
To enhance your development workflow, we recommend implementing a pre-commit hook in your project's Git repository. Follow these steps to set it up:
Run 'deno generate' before committing
deno generate
Check if 'deno generate' generated any changes
git diff --exit-code
Now, when viewing pull requests or generating diffs on GitHub, the marked files will be hidden by default, providing a more streamlined code review process and excluding them from language statistics calculations.
Use cases
The
deno generate
subcommand is a powerful feature, encouraging the use of code generation with a convenient developer experience. Code generation is an important programming technique because generated files can automate repetitive or complex tasks, improve code consistency and maintainability, and save developers time and effort.As for use cases, your imagination is the limit. Here are a few:
deno generate
subcommand to automatically generate code that follows those patterns.deno generate
subcommand to automatically generate tests for their code.Usage
The
deno generate
subcommand is capable of facilitating the generation of code in the Deno ecosystem. Developers use code generation to generate code for all layers of your application.Run any Deno script
Deno scripts should be able to invoke another Deno in its
//deno:generate
statement:generator.ts
generate.ts
Generate OpenAPI types
OpenAPI is a JSON-based specification that represents comprehensive API details, providing a formal and professional representation of the API specifications. One of the most common use cases of OpenAPI is to generate API clients, simplifying the development process by automatically generating code based on the defined API specifications. OpenAPI schemas offer versatile applications and integrations, enabling a wide range of possibilities for API design and development.
Generate static website with Lume
Lume is a website framework for the Deno ecosystem. Entire static websites are generated by Lume with a single command. See more.
Generate
deno_bindgen
bindingsThis tool aims to simplify glue code generation for Deno FFI libraries written in Rust. See more.
Generate deno-embedder file
deno-embedder is a tool that simplifies the development and distribution of Deno applications, particularly when access to static files (.txt, .png, etc.) is required at runtime. It allows you to create an embedder.ts file that encompasses both configuration and the main function call, providing benefits such as IDE-based type-checking. See more.
mod.ts
Bundlee is a deno-embedder alternative.
Generate
deno doc
JSONmod.ts
generate_docs.ts
Generate art
mod.ts
generate_art.ts
Implications on permissions
The
deno generate
feature allows us to run our Deno programs in a slightly different way. Normally, when we use "deno run" to execute our code, we have to explicitly specify the permissions we need, likedeno run --allow-etc.
ordeno run -A
. However, withdeno generate
, we can run our program without explicitly mentioning the permissions.It's important to note that this doesn't change how our program works or behaves. It's simply a different way of running it. However, because Deno is very careful about permissions, it's worth mentioning this aspect.
Ideally, only developers should run
deno generate
. This ensures that we have a clear understanding and control over the permissions granted during the development process.Closing remarks
It is recommended that educational materials be added to Deno to clearly communicate to developers what types of generators they are encouraged and warned to run via the
deno generate
subcommand. This is important because Deno is a powerful tool that can be used to create a variety of applications, and it is important for developers to be aware of the potential risks and benefits of using different generators. By adding educational materials, the Deno team can help to ensure that developers are using the tool safely and effectively.Overall, the
deno generate
subcommand has the potential to improve the development experience for Deno developers and attract new users to the ecosystem. Looking forward to the future of Deno!