asyncapi / generator-react-sdk

Generator React SDK enabling the AsyncAPI generator to support React as the rendering engine for templates.
Apache License 2.0
20 stars 8 forks source link

Simplify `File template` feature #10

Closed magicmatatjahu closed 3 years ago

magicmatatjahu commented 3 years ago

Reason/Context

Some people know or not, the Generator has feature called File template. More info here https://github.com/asyncapi/generator/blob/master/docs/authoring.md#file-templates

Issue is created to start discussion about how to simplify this feature. File template is good for Nunjucks but using React we can make it more powerful and more flexible.

Proposition

My proposition is return as output from template an array of <File> components and then render and save every given File, something like:

export default function({ asyncapi }) {
  if (!asyncapi.components().hasSchemas()) {
    return null;
  }

  return Object.entries(asyncapi.components().schemas()).map(([schemaName, schema]) => {
    return (
      <File name={`${schemaName}.html`}>
        <SchemaFile schemaName={schemaName} schema={schema} />
      </File>
    );
  });
}

function SchemaFile({ schemaName, schema }) {
  // implementation...
}

Any other ideas? :)

derberg commented 3 years ago

I love the idea. Fewer custom features = easier to understand generator and go forward with generator adoption.

Don't you think it would be even better to make it even easier for people that are not so much familiar with react and just want to connect components all together (what a long strange sentence) -> basically have a MultiFile component that returns multiple files? just hiding the array you created above?

by ${name} you mean ${schemaName}?

magicmatatjahu commented 3 years ago

by ${name} you mean ${schemaName}?

Yeah, sorry, I edited :) Thanks!

Don't you think it would be even better to make it even easier for people that are not so much familiar with react and just want to connect components all together (what a long strange sentence) -> basically have a MultiFile component that returns multiple files? just hiding the array you created above?

I thought about something similar with MultiFile, but with this approach you must check that root component is a MultiFile type (inside the generator) and then change children of component to given array, something like:

export default function({ asyncapi }) {
  return (
    <MultiFile>
      <File ... />
      <File ... />
      <File ... />
    </MultiFile>
  );
}

or you had something different in mind?

Also, with this approach you cannot define conditional template, I mean something like:

export default function({ asyncapi }) {
  const files = [];
  if (asyncapi.components().hasSchemas()) {
    Object.entries(asyncapi.components().schemas()).map(([schemaName, schema]) => {
      files.push(
        <File name={`${schemaName}.html`}>
          <SchemaFile schemaName={schemaName} schema={schema} />
        </File>
      );
    })
  }
  if (asyncapi.components().hasMessages()) {
    // push message template to files variable
  }
  return files;
}

but with pure array you can.

Stmated commented 3 years ago

I was just about to create an issue for something like this.

I would very much like this feature, since the $$schema$$ system feels quite backwards at times.

jonaslagoni commented 3 years ago

I think we need to prioritize this feature because the file template names are no longer possible if we want to inherit syntax highlighter in the IDE.

If I want to generate something for each channel in the document with the typescript extension such as $$channel$$.spec.ts I am no longer able to do the following, without the IDE (VSCode in my case) highlighting errors.

import { File, Text } from "@asyncapi/generator-react-sdk";
export default function({ asyncapi, params }) {
  return <File>
  {
    `
...
  `
  }
  </File>
}

I mean we could do something like:

export default function({ asyncapi }) {
  const files = [];
  if (asyncapi.components().hasSchemas()) {
    Object.entries(asyncapi.components().schemas()).map(([schemaName, schema]) => {
      files.push(
        <File name={`${schemaName}.html`}>
          <SchemaFile schemaName={schemaName} schema={schema} />
        </File>
      );
    })
  }
  if (asyncapi.components().hasMessages()) {
    // push message template to files variable
  }
  return <MultiFile files={files} />;
}

But tbh I still like the pure array better, and it seems silly to wrap the files in a MultiFile component when it could just be returned as is.

derberg commented 3 years ago

Go ahead with it 😄 And yeah, multifile was just a quick idea, I see it may just bring confusion and limitation

magicmatatjahu commented 3 years ago

Done by https://github.com/asyncapi/generator/commit/f92fabfdc3d9db8c4ebab95ad9485200e7200825 and https://github.com/asyncapi/generator-react-sdk/pull/38