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`] = `
-"{{yield}}
-"
-`;
-
-exports[`generates a \`.gjs\` template-only component at a custom path 1`] = `
-"{{yield}}
-"
-`;
-
-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`] = `
+"{{yield}}
+"
+`;
+
+exports[`generates a template-only \`.gjs\` component at a custom path 1`] = `
+"{{yield}}
+"
+`;
+
+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", {