@40q/40q-cli 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
package/.cliroot ADDED
File without changes
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@40q/40q-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "40q CLI tool",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "40q": "./dist/index.js"
8
8
  },
9
9
  "dependencies": {
10
+ "inquirer": "^8.0.0",
10
11
  "yargs": "^17.7.2"
11
12
  },
12
13
  "peerDependencies": {
@@ -14,7 +15,7 @@
14
15
  },
15
16
  "scripts": {
16
17
  "build": "tsc",
17
- "build-publish": "yarn build && yarn publish --access public"
18
+ "deploy": "yarn build && yarn publish --access public"
18
19
  },
19
20
  "author": "40q <info@40q.agency> (https://40q.agency/)",
20
21
  "license": "ISC",
@@ -23,6 +24,7 @@
23
24
  "url": "https://github.com/40Q/40q-cli.git"
24
25
  },
25
26
  "devDependencies": {
27
+ "@types/inquirer": "^8.0.0",
26
28
  "@types/node": "^20.8.7",
27
29
  "@types/yargs": "^17.0.29",
28
30
  "ts-node": "^10.9.1",
package/src/40qCli.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import yargs from 'yargs';
2
2
  import { hideBin } from 'yargs/helpers';
3
- import { SetupCommand } from './commands/Setup.command';
3
+ import { SetupCommand } from './commands/Setup/Setup.command';
4
+ import { CodegenCommand } from './commands/Codegen/Codegen.command';
4
5
 
5
6
  export class q40Cli {
6
7
  static init() {
@@ -11,6 +12,12 @@ export class q40Cli {
11
12
  SetupCommand.builder,
12
13
  SetupCommand.handler
13
14
  )
15
+ .command(
16
+ 'codegen [type] [template]',
17
+ 'Generate code from a template',
18
+ CodegenCommand.builder,
19
+ CodegenCommand.handler
20
+ )
14
21
  .help().argv;
15
22
  }
16
23
  }
@@ -0,0 +1,52 @@
1
+ import { ArgumentsCamelCase, Argv } from 'yargs';
2
+ import { Command } from '../Command';
3
+ import inquirer, { QuestionCollection } from 'inquirer';
4
+ import { GenerateBlock } from './Generators/GenerateBlock';
5
+ import { Templates, Types, templateChoices, typeChoices } from './Codegen.types';
6
+
7
+ export class CodegenCommand implements Command {
8
+ static builder(yargs: Argv<{}>) {
9
+ yargs.positional('type', {
10
+ describe: 'Type of code piece to generate',
11
+ choices: typeChoices,
12
+ demandOption: true,
13
+ type: 'string',
14
+ });
15
+
16
+ yargs.positional('template', {
17
+ describe: 'Template to use for code generation',
18
+ choices: templateChoices,
19
+ demandOption: false,
20
+ type: 'string',
21
+ });
22
+ }
23
+
24
+ static async handler(argv: ArgumentsCamelCase<{}>) {
25
+ const type = argv.type as Types;
26
+ const template = (argv.template ?? 'default') as Templates;
27
+
28
+ if (type === 'block') {
29
+ const answers = await CodegenCommand.prompt(
30
+ [
31
+ {
32
+ type: 'input',
33
+ name: 'name',
34
+ message: 'Please enter a name for the block:',
35
+ default: 'section-header',
36
+ },
37
+ ],
38
+ template === 'default'
39
+ );
40
+
41
+ const name = (answers?.name as string) || null;
42
+
43
+ return GenerateBlock.run(template, name);
44
+ }
45
+ }
46
+
47
+ static async prompt(prompts: QuestionCollection, condition: boolean) {
48
+ if (!condition) return null;
49
+
50
+ return await inquirer.prompt(prompts);
51
+ }
52
+ }
@@ -0,0 +1,5 @@
1
+ export const typeChoices = ['block'] as const;
2
+ export type Types = (typeof typeChoices)[number];
3
+
4
+ export const templateChoices = ['section-header'] as const;
5
+ export type Templates = (typeof templateChoices)[number] | 'default';
@@ -0,0 +1,36 @@
1
+ import { execSync } from 'child_process';
2
+ import * as fs from 'fs';
3
+ import path from 'path';
4
+ import { Templates } from '../Codegen.types';
5
+ import { findCliRoot } from '../../../lib/cliRoot';
6
+
7
+ export class GenerateBlock {
8
+ static run(template: Templates, name: string | null) {
9
+ const title =
10
+ name
11
+ ?.split('-')
12
+ .map((word) => {
13
+ return word.charAt(0).toUpperCase() + word.slice(1);
14
+ })
15
+ .join(' ') ?? '';
16
+ const dirAndFileName = name || template;
17
+
18
+ execSync(`mkdir -p resources/scripts/editor/blocks/${dirAndFileName}`);
19
+
20
+ const cliRoot = findCliRoot(__dirname);
21
+ const templateContent = fs.readFileSync(
22
+ path.join(cliRoot, 'templates/blocks/', `${template}.txt`),
23
+ 'utf8'
24
+ );
25
+
26
+ fs.writeFileSync(
27
+ path.join(
28
+ process.cwd(),
29
+ `resources/scripts/editor/blocks/${dirAndFileName}/${dirAndFileName}.tsx`
30
+ ),
31
+ templateContent
32
+ .replace(/{{name}}/g, name ?? '')
33
+ .replace(/{{title}}/g, title)
34
+ );
35
+ }
36
+ }
@@ -1,6 +1,6 @@
1
1
  import { ArgumentsCamelCase, Argv } from 'yargs';
2
2
  import { execSync } from 'child_process';
3
- import { Command } from './Command';
3
+ import { Command } from '../Command';
4
4
 
5
5
  const eslintrc = `
6
6
  {
@@ -0,0 +1,16 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+
4
+ export function findCliRoot(startDir: string): string {
5
+ let currentDir = startDir;
6
+
7
+ while (currentDir !== path.parse(currentDir).root) {
8
+ if (fs.existsSync(path.join(currentDir, '.cliroot'))) {
9
+ return currentDir;
10
+ }
11
+
12
+ currentDir = path.dirname(currentDir);
13
+ }
14
+
15
+ throw new Error('CLI root directory with .cliroot marker not found.');
16
+ }
@@ -0,0 +1,54 @@
1
+ import { __ } from "@wordpress/i18n";
2
+ import { PanelBody } from "@wordpress/components";
3
+ import {
4
+ InspectorControls,
5
+ RichText,
6
+ useBlockProps,
7
+ } from "@wordpress/block-editor";
8
+
9
+ /* Block name */
10
+ export const name = "by40q/section-header";
11
+
12
+ /* Block title */
13
+ export const title = __("Section Header", "40q");
14
+
15
+ /* Block category */
16
+ export const category = "text";
17
+
18
+ /* Block attributes */
19
+ export const attributes = {
20
+ title: {
21
+ type: "string",
22
+ default: "40Q",
23
+ },
24
+ };
25
+
26
+ /* Block edit */
27
+ export const edit = ({ attributes, setAttributes }) => {
28
+ const { title } = attributes;
29
+
30
+ const blockProps = useBlockProps();
31
+
32
+ return (
33
+ <>
34
+ <InspectorControls>
35
+ <PanelBody title={__("Section Header Settings")} initialOpen></PanelBody>
36
+ </InspectorControls>
37
+
38
+ <div {...blockProps}>
39
+ <RichText
40
+ tagName="h2"
41
+ placeholder={__("40Q")}
42
+ value={title}
43
+ onChange={(title) => setAttributes({ title })}
44
+ />
45
+ </div>
46
+ </>
47
+ );
48
+ };
49
+
50
+ /* Block save */
51
+ export const save = () => <></>;
52
+
53
+ /* Block styles */
54
+ export const styles = [];
package/tsconfig.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "es2016",
4
- "module": "commonjs",
4
+ "module": "CommonJS",
5
+ "moduleResolution": "node",
5
6
  "esModuleInterop": true,
6
7
  "forceConsistentCasingInFileNames": true,
7
8
  "strict": true,