diff --git a/.scaffdog/documents/component.md b/.scaffdog/documents/component.md index a4246bb..ede270d 100644 --- a/.scaffdog/documents/component.md +++ b/.scaffdog/documents/component.md @@ -15,6 +15,7 @@ output: "**/*" ```gjs [[name := pascal(inputs.name)-]] + import Component from "@glimmer/component"; export default class [[name]] extends Component { @@ -27,6 +28,7 @@ export default class [[name]] extends Component { ```gts [[name := pascal(inputs.name)-]] + import type { TOC } from '@ember/component/template-only'; export interface [[name]]Signature { @@ -47,6 +49,7 @@ export default [[name]]; ```gts [[name := pascal(inputs.name)-]] + import Component from "@glimmer/component"; export interface [[name]]Signature { diff --git a/.scaffdog/documents/helper.md b/.scaffdog/documents/helper.md index a91e227..0bf8bc6 100644 --- a/.scaffdog/documents/helper.md +++ b/.scaffdog/documents/helper.md @@ -4,11 +4,28 @@ root: "." output: "**/*" --- -# [[inputs.name]].[[inputs.authoringFormat]] +# [[inputs.classBased ? "!" : ""]][[inputs.name]].[[inputs.authoringFormat]] ```ts -export default function [[camel(inputs.name)]]Helper(positional /*, named*/) { +[[name := camel(inputs.name)-]] + +export default function [[name]](positional /*, named*/) { return positional; } ``` + +# [[inputs.classBased ? "" : "!"]][[inputs.name]].[[inputs.authoringFormat]] + +```ts +[[name := pascal(inputs.name)-]] + +import Helper from "@ember/component/helper"; + +export default class [[name]] extends Helper { + compute(positional /*, named*/) { + return positional; + } +} + +``` diff --git a/.scaffdog/documents/service.md b/.scaffdog/documents/service.md index ee334b6..f86369e 100644 --- a/.scaffdog/documents/service.md +++ b/.scaffdog/documents/service.md @@ -8,6 +8,7 @@ output: "**/*" ```ts [[name := pascal(inputs.name)-]] + import Service from "@ember/service"; export default class [[name]]Service extends Service {} diff --git a/README.md b/README.md index bb5455d..7d8d107 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ pnpm gember component foo --gts pnpm gember component foo --path="src/-private" pnpm gember helper foo +pnpm gember helper foo --class pnpm gember helper foo --ts pnpm gember helper foo --path="src/-private" diff --git a/src/cli.ts b/src/cli.ts index 316872a..8bd4698 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -55,6 +55,12 @@ yargs(hideBin(process.argv)) description: "The helper's name", type: "string", }) + .option("class-based", { + alias: ["class"], + default: false, + description: "Generate a class-based helper", + type: "boolean", + }) .option("path", { default: "", description: "Generate a helper at a custom path", @@ -69,6 +75,7 @@ yargs(hideBin(process.argv)) handler(options) { generateHelper(options.name, { authoringFormat: options.ts ? "ts" : "js", + classBased: options.classBased, path: options.path, }); }, diff --git a/src/generate-document.ts b/src/generate-document.ts index f307cd4..71f9325 100644 --- a/src/generate-document.ts +++ b/src/generate-document.ts @@ -33,7 +33,7 @@ export async function generateDocument( const document = documents.find((document) => document.name === documentName); if (document === undefined) { - throw new Error(`[BUG] Document "${documentName}" not found.`); + throw new Error(`[BUG] Document \`${documentName}\` not found.`); } const documentPath = path @@ -56,7 +56,7 @@ export async function generateDocument( console.log( chalk.green( - `🫚 Generated ${documentName} "${entityName}" at "${relative(cwd, file.path)}".`, + `🫚 Generated ${documentName} \`${entityName}\` at \`${relative(cwd, file.path)}\`.`, ), ); } diff --git a/src/generators.ts b/src/generators.ts index 6110ded..b084c7f 100644 --- a/src/generators.ts +++ b/src/generators.ts @@ -26,17 +26,19 @@ export function generateHelper( name: string, { authoringFormat = "js", + classBased = false, cwd = "", path = "", }: { authoringFormat?: "js" | "ts"; + classBased?: boolean; cwd?: string; path?: string; } = {}, ) { return generateDocument(DocumentName.Helper, name, { cwd, - inputs: { authoringFormat }, + inputs: { authoringFormat, classBased }, path, }); } diff --git a/test/__snapshots__/generate-component.test.ts.snap b/test/__snapshots__/generate-component.test.ts.snap index 46e5306..d07bcb3 100644 --- a/test/__snapshots__/generate-component.test.ts.snap +++ b/test/__snapshots__/generate-component.test.ts.snap @@ -1,6 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`generates a \`.gjs\` class-based component 1`] = ` +exports[`generates a class-based \`.gjs\` component 1`] = ` "import Component from "@glimmer/component"; export default class Foo extends Component { @@ -9,17 +9,7 @@ export default class Foo extends Component { " `; -exports[`generates a \`.gjs\` template-only component 1`] = ` -" -" -`; - -exports[`generates a \`.gjs\` template-only component at a custom path 1`] = ` -" -" -`; - -exports[`generates a \`.gts\` class-based component 1`] = ` +exports[`generates a class-based \`.gts\` component 1`] = ` "import Component from "@glimmer/component"; export interface FooSignature { @@ -38,7 +28,17 @@ export default class Foo extends Component { " `; -exports[`generates a \`.gts\` template-only component 1`] = ` +exports[`generates a template-only \`.gjs\` component 1`] = ` +" +" +`; + +exports[`generates a template-only \`.gjs\` component at a custom path 1`] = ` +" +" +`; + +exports[`generates a template-only \`.gts\` component 1`] = ` "import type { TOC } from '@ember/component/template-only'; export interface FooSignature { @@ -55,7 +55,7 @@ export default Foo; " `; -exports[`generates a \`.gts\` template-only component at a custom path 1`] = ` +exports[`generates a template-only \`.gts\` component at a custom path 1`] = ` "import type { TOC } from '@ember/component/template-only'; export interface FooSignature { diff --git a/test/__snapshots__/generate-helper.test.ts.snap b/test/__snapshots__/generate-helper.test.ts.snap index 94472c0..f8d40cf 100644 --- a/test/__snapshots__/generate-helper.test.ts.snap +++ b/test/__snapshots__/generate-helper.test.ts.snap @@ -1,28 +1,50 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`generates a \`.js\` helper 1`] = ` -"export default function fooHelper(positional /*, named*/) { +exports[`generates a class-based \`.js\` helper 1`] = ` +"import Helper from "@ember/component/helper"; + +export default class Foo extends Helper { + compute(positional /*, named*/) { + return positional; + } +} +" +`; + +exports[`generates a class-based \`.ts\` helper 1`] = ` +"import Helper from "@ember/component/helper"; + +export default class Foo extends Helper { + compute(positional /*, named*/) { + return positional; + } +} +" +`; + +exports[`generates a function-based \`.js\` helper 1`] = ` +"export default function foo(positional /*, named*/) { return positional; } " `; -exports[`generates a \`.js\` helper at a custom path 1`] = ` -"export default function fooHelper(positional /*, named*/) { +exports[`generates a function-based \`.js\` helper at a custom path 1`] = ` +"export default function foo(positional /*, named*/) { return positional; } " `; -exports[`generates a \`.ts\` helper 1`] = ` -"export default function fooHelper(positional /*, named*/) { +exports[`generates a function-based \`.ts\` helper 1`] = ` +"export default function foo(positional /*, named*/) { return positional; } " `; -exports[`generates a \`.ts\` helper at a custom path 1`] = ` -"export default function fooHelper(positional /*, named*/) { +exports[`generates a function-based \`.ts\` helper at a custom path 1`] = ` +"export default function foo(positional /*, named*/) { return positional; } " diff --git a/test/generate-component.test.ts b/test/generate-component.test.ts index 01db0c8..6956518 100644 --- a/test/generate-component.test.ts +++ b/test/generate-component.test.ts @@ -9,7 +9,7 @@ let cwd: string; afterEach(() => fsExtra.remove(cwd)); -it("generates a `.gjs` template-only component", async (ctx) => { +it("generates a template-only `.gjs` component", async (ctx) => { cwd = await copyBlueprint("v2-addon"); await generateComponent("foo", { cwd }); @@ -19,7 +19,7 @@ it("generates a `.gjs` template-only component", async (ctx) => { ctx.expect(content).toMatchSnapshot(); }); -it("generates a `.gjs` class-based component", async (ctx) => { +it("generates a class-based `.gjs` component", async (ctx) => { cwd = await copyBlueprint("v2-addon"); await generateComponent("foo", { classBased: true, cwd }); @@ -29,7 +29,7 @@ it("generates a `.gjs` class-based component", async (ctx) => { ctx.expect(content).toMatchSnapshot(); }); -it("generates a `.gjs` template-only component at a custom path", async (ctx) => { +it("generates a template-only `.gjs` component at a custom path", async (ctx) => { cwd = await copyBlueprint("v2-addon"); await generateComponent("foo", { cwd, path: "src/-private" }); @@ -39,7 +39,7 @@ it("generates a `.gjs` template-only component at a custom path", async (ctx) => ctx.expect(content).toMatchSnapshot(); }); -it("generates a `.gts` template-only component", async (ctx) => { +it("generates a template-only `.gts` component", async (ctx) => { cwd = await copyBlueprint("v2-addon"); await generateComponent("foo", { authoringFormat: "gts", cwd }); @@ -49,7 +49,7 @@ it("generates a `.gts` template-only component", async (ctx) => { ctx.expect(content).toMatchSnapshot(); }); -it("generates a `.gts` class-based component", async (ctx) => { +it("generates a class-based `.gts` component", async (ctx) => { cwd = await copyBlueprint("v2-addon"); await generateComponent("foo", { @@ -63,7 +63,7 @@ it("generates a `.gts` class-based component", async (ctx) => { ctx.expect(content).toMatchSnapshot(); }); -it("generates a `.gts` template-only component at a custom path", async (ctx) => { +it("generates a template-only `.gts` component at a custom path", async (ctx) => { cwd = await copyBlueprint("v2-addon"); await generateComponent("foo", { diff --git a/test/generate-helper.test.ts b/test/generate-helper.test.ts index d53ae51..b7bbe6a 100644 --- a/test/generate-helper.test.ts +++ b/test/generate-helper.test.ts @@ -9,7 +9,7 @@ let cwd: string; afterEach(() => fsExtra.remove(cwd)); -it("generates a `.js` helper", async (ctx) => { +it("generates a function-based `.js` helper", async (ctx) => { cwd = await copyBlueprint("v2-addon"); await generateHelper("foo", { cwd }); @@ -19,17 +19,17 @@ it("generates a `.js` helper", async (ctx) => { ctx.expect(content).toMatchSnapshot(); }); -it("generates a `.ts` helper", async (ctx) => { +it("generates a class-based `.js` helper", async (ctx) => { cwd = await copyBlueprint("v2-addon"); - await generateHelper("foo", { authoringFormat: "ts", cwd }); + await generateHelper("foo", { classBased: true, cwd }); - const content = await readFile(join(cwd, "src/helpers/foo.ts"), "utf-8"); + const content = await readFile(join(cwd, "src/helpers/foo.js"), "utf-8"); ctx.expect(content).toMatchSnapshot(); }); -it("generates a `.js` helper at a custom path", async (ctx) => { +it("generates a function-based `.js` helper at a custom path", async (ctx) => { cwd = await copyBlueprint("v2-addon"); await generateHelper("foo", { cwd, path: "src/-private" }); @@ -39,7 +39,27 @@ it("generates a `.js` helper at a custom path", async (ctx) => { ctx.expect(content).toMatchSnapshot(); }); -it("generates a `.ts` helper at a custom path", async (ctx) => { +it("generates a function-based `.ts` helper", async (ctx) => { + cwd = await copyBlueprint("v2-addon"); + + await generateHelper("foo", { authoringFormat: "ts", cwd }); + + const content = await readFile(join(cwd, "src/helpers/foo.ts"), "utf-8"); + + ctx.expect(content).toMatchSnapshot(); +}); + +it("generates a class-based `.ts` helper", async (ctx) => { + cwd = await copyBlueprint("v2-addon"); + + await generateHelper("foo", { authoringFormat: "ts", classBased: true, cwd }); + + const content = await readFile(join(cwd, "src/helpers/foo.ts"), "utf-8"); + + ctx.expect(content).toMatchSnapshot(); +}); + +it("generates a function-based `.ts` helper at a custom path", async (ctx) => { cwd = await copyBlueprint("v2-addon"); await generateHelper("foo", {