nitzanhen / agrippa Goto Github PK
View Code? Open in Web Editor NEWThe CLI for frontend component generation
Home Page: https://agrippa.dev
License: MIT License
The CLI for frontend component generation
Home Page: https://agrippa.dev
License: MIT License
I'd love to see some example usages. This would help me understand better how the tool works. The only other way right now is to go over the documentation to read each of the options and try it out.
I believe there could be some examples such as:
npx agrippa gen button --ts --styling css --export-type default --base-dir app/javascript/agrippa --flat
And then show the output:
Two files:
app/javascript/agrippa/Button.tsx
app/javascript/agrippa/button.module.css
// app/javascript/agrippa/Button.tsx
import React from 'react';
import classes from './button.module.css';
export interface ButtonProps {}
const Button: React.VFC<ButtonProps> = () => {
return (
<div></div>
);
};
export default Button;
Relies on #11, as the function passed to memo()
should be a named function
.
Could you introduce the option to have an export default Navbar
at the end? I hope you understand what I mean ๐๐
And print an appropriate message if a new version exists.
I'm coming from this generator:
https://github.com/arminbro/generate-react-cli
And I love that it automatically generates the test file for the component-
When I generate a component in agrippa eg: agrippa gen radio
The files are generated as:-
radio.tsx
radio .module.css
instead of radio.module.css
It is a minor bug but it need to be corrected
Add a flag, such as declaration
, which can receive the values const
or function
.
const
is the default, and is the current behaviour.
function
will generate the component with a function declaration:
function Button(props: ButtonProps) {
//The usual
}
This will be implemented after (or during) the code generation refactors, as described in #9
Agrippa simply writes <div>children</div>
instead of <div>{children}</div>
This is a good suggestion! I want to use Agrippa, but we have a component file structure that I can't create with Agrippa.
Below is the default structure of each component. I have a template folder on my desktop that I just copy when I want to create a new component.
Folder structure
src/components/component-name
Content of a component
component-name.interfaces.ts component-name.styles.ts component-name.tsx index.ts
File content
component-name.interfaces.ts
export interface OptionalStyleProps { } export interface RequiredStyleProps { } export interface ComponentProps { } export interface Props extends ComponentProps, Partial<RequiredStyleProps>, OptionalStyleProps {}
component-name.styles.ts
import tw from 'twin.macro' export const StyledComponentName = tw.div``
component-name.tsx
import { Props } from './component-name.interfaces' import { StyledComponentName } from './component-name.styles' /** * Primary UI component for user interaction */ export function ComponentName(props: Props) { return ( <StyledComponentName> {children} </StyledComponentName> ) }
index.ts
export * from './component-name' export type { Props as ComponentNameProps } from './component-name.interfaces'
Would it be possible to add support for some configuration so that Agrippa could generate something this?
(Quote is a reply on #2 by @nonameolsson)
Hi
In my company we are working with nextjs, react and storyblok as cms.
I would like to create only a .tsx file at /base/dir/FileName.tsx.
Curently i am only able to create the File like this: /base/dir/FileName/FileName.tsx.
I also dont need the index.ts file that is generated every time.
I would love to see this be configurable in the configfile
best regards k4linx let me know if you need any more information
Needed schema changes:
debug
flagreact-native
option to styling
react-native
flagseparate-index
flagThere are some properties mentioned in JSON schema but missing from docs:
props
children
flat
stylingModule
postCommand
destination
tsPropsDeclaration
memo
separateIndex
reactNative
What I have to do with them? Remove?
This is tool is awesome, thank you @nitzanhen ! I just ran into a small bug this morning :
When an update is available a warning is displayed to inform the user. There is a misspelling in this warning : agrrippa
instead of agrippa
.
[WARN]: New patch version available: 1.3.1!
[WARN]: please update now by typing npm i -g agrrippa into the terminal
Hi, I'm trying to generate a component with Agrippa using the following command:
agrippa gen button
The result is that the CLI generated an index.tsx
file in the Button/
folder as follows:
[INFO]: Generation successful.
[INFO]: Generated files:
[INFO]: /Sandbox/example-app/src/Button/index.tsx
[INFO]: /Sandbox/example-app/src/Button
Isn't it supposed to generate an index.jsx
or index.js
file for the component? I'm currently on a fresh create-react-app install without a tsconfig.json
file in the application.
Is there something I'm missing?
Thanks!
Already done, opening this just to be organized.
This raised an error when trying to generate a component resolved outside the working directory (e.g. agrippa gen button --dest '../temp'
) with baseDir not specified. It's an extreme case, but should be handled nonetheless.
Current base component
export interface SampleComponentProps { }
export const SampleComponent: React.VFC<SampleComponentProps> = () => (
<div/>
);
For convince sake, I would like if the component could look like this =>
export interface SampleComponentProps { }
export const SampleComponent: React.VFC<SampleComponentProps> = () => (
<div><div/>
);
there's no use for <div/>
.
We need end-to-end tests - tests that "receive" a config, an Agrippa command and the result files, runs the command with the config, and compares the generated files to the given ones.
The majority of work here is on the testing script - one that will properly run the command with the config and compare the output files. It should also log out everything nicely.
Hey @nitzanhen, congrats on the nice tool, great initiative!
Since you obviously like code-generation, I suggest you look at https://github.com/nrwl/nx.
It's a tool for mono-repos, but at its core is code generation.
Extending your tool to also be a plugin for NX and allowing NX users to use it can help you gain users for your tool ๐๐ป
Is it possible to add configuration to generate type alias instead of interface for props? Like this:
type ComponentProps = {}
instead of interface ComponentProps {}
Some people adopt this directory layout:
components
โโโ MyComponent
โโโ MyComponent.tsx
โโโ index.js
MyComponent.tsx holds the component's code and index.js is always something like:
export {default} from './MyComponent.tsx'
That directory layout allows to group files related to MyComponent inside its directory, helps identify what component we are working on in the editor (when you have 10 files called index.tsx open you get confused), and keeps a clean import syntax, such as:
import MyComponent from '../MyComponent'
Are you interested in implementing such a feature?
I could do it :-)
Currently need to update the tarball file name manually.
Currently, Agrippa creates the React component code as one big array of "lines" (strings or nulls), from which the nulls are then filtered and the rows then joined. ostr()
is used extensively for optional lines, and cstr()
for conditional strings inside lines.
This approach is nice and was simple to implement, but is harder to scale and maintain since all the logic is stored in one place as a huge block of code. Right now (v1.1.1) this is a minor issue, since the amount of code is not too large, but as Agrippa grows on it can only get much worse.
Also, since all the logic is bundled together, it is difficult to test one piece at a time. This is a major issue, as demonstrated in issues #3 and #5 - both are awkward bugs that were missed due to the lack of standardized testing on my part.
To solve these issues, Agrippa's internals will be reformed as such:
The generation code will be implemented in a functional manner (functional as in functional programming); I prefer writing functional code as long as there's no eminent benefit to using a different paradigm (OOP or otherwise).
The logic of determining the correct form for a small segment of the code should be separated from the logic of composing those segments together. By "small segment of the code" I mean an atomic segment, i.e. a segment which cannot be reasonably split into a composition of two other segments. Segment composing other segments will be called composing segments; **the composed segments can be atomic segments, other composing segments or a combination of the two.
For example, consider the type Agrippa declares for a component in a Typescript project - e.g. React.VFC<ButtonProps>
in const Button: React.VFC<ButtonProps> = (props) => { ... }
. This simple segment would be modeled as a composition segment of two other atomic segments - The base React type (React.VFC
or React.FC
) and the name of the props interface (derived from the component's name, e.g. ButtonProps
in the example above).
This distinction between atomic and composing segments will help keep concerns separated and the code DRY.
The logic for atomic segments will be implemented as pure functions, which will receive as parameters exactly the data they need (and no more); this will make unit-testing them dead simple.
The logic for composing segments, on the other hand, will be implemented as methods of a single class, Composer
(name definitely not final), which will have the entire config as a readonly member, and will pass the relevant parts of it down to the atomic segments it composes.
This means each method will have access to the entire config (and will typically need no parameters of its own). Having the config be a readonly member assures that the code remains functional, since no internal state is implemented - this is essentially a cleaner alternative to requiring the config as an argument in the funcitons of all composing segments and partially applying it.
Requiring the entire config for each method (by way of requiring it for the entire Composer
class) makes testing a bit more cumbersome, but should pose no real problem.
type | atomic segments | composing segments |
---|---|---|
implemented as | pure functions | Composer methods |
parameters | only what is used | typically none; access to entire config as class member |
Finally, the code generation task will create and use the Composer
class to generate the final component code.
Implementing atomic segments as pure functions and composing segments as methods of Composer
is important, but not cardinal - if there's a very good reason to implement an atomic segment as a mehtod of Composer
it will be implemented as such (and vice versa).
This spec might change or extended as it's implemented, but I think it's a solid strategy. It will also make it easier to implement some of the features I've been willing to add to Agrippa, such as an option to declare components as function
s instead of const
s, and in turn the ability to generate memo
components or the likes.
Suggestions and inputs are welcome.
Another issue will be opened in the near future for the testing RFC.
Personally I haven't played around with mui 5 yet, but it seems their styling got an overhaul. This might be a non-trivial feature.
This will probably also require another flag (as we'll need to support both mui 4 and mui 5).
Hoping for the discussion on dev.to to give us a lead on whether this is relevant territory for Agrippa, and if so - what can we do.
If you're reading this, your opinion is most welcome!
The most important addition is support for react native StyleSheets
.
However, for support to be good we also need to add a JSX template for react native projects.
How will this feature look in the aspect of options? will a react-native
styling be added and another flag be added for react-native project (parallel to Typescript having both the props: ts
option and the typescript
flag)
I personally prefere to use type
instead of interface
when describing the props in typescript. I see agrippa defaults to using interface
It would be nice to have some sort of flag to decide which alternative to use.
props
defaults to ts
if Agrippa manages to find a tsconfig
, and is none
otherwise.
However, in non-ts environments this means that passing --typescript
is not enough, as that generates no props.
It needs to be changed such that props
will default to ts
only if --typescript
is set (whether manually or by default).
This is kind of an edge case, but I found it annoying while writing integration tests.
In styling options add support for styled components to add in importing of styled from styled components
Please add --dest
or --destintion
.
I am working on a node project the file structure is as follows:-
I want to generate components in the components folder but Agrippa is making it in the project's main directory i.e /.
agrippa gen [name] --dest ./src/components --[other args]
For props: ts
to be valid, the typescript
flag must be set (it is set by default for TS projects; this issue simply requires that this requirement be enforced).
When I look at the following line (default: ...
):
'import-react': {
alias: 'importReact',
type: 'boolean',
default: tsConfig?.compilerOptions?.jsx ? !/^react-jsx/.test(tsConfig.compilerOptions.jsx) : true,
desc: 'Whether to import React.'
},
and the description in the wiki:
Command-line usage: --import-react
Type: boolean
Default: true if the CLI manages to find a tsconfig.json file and it has a jsx field under compilerOptions with react-jsx or react-jsxdev as the value. false otherwise.
I have the impression that the default value is just the opposite. Shouldn't it be as follows or am I missing something?
default: tsConfig?.compilerOptions?.jsx ? /^react-jsx/.test(tsConfig.compilerOptions.jsx) : false,
Thanks!
Also need to change the "variable paths" functionality to "post command variables".
Needed for #42.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.