tshex-cli 1.0.15 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/main.js CHANGED
@@ -3,13 +3,15 @@ import { program } from 'commander';
3
3
  import fs from 'node:fs';
4
4
  import path from 'node:path';
5
5
  function readPackageJson() {
6
- return JSON.parse(fs.readFileSync(path.join(import.meta.dirname, '..', 'package.json'), 'utf-8'));
6
+ const filePath = path.join(import.meta.dirname, '..', 'package.json');
7
+ const fileContents = fs.readFileSync(filePath, 'utf-8');
8
+ return JSON.parse(fileContents);
7
9
  }
8
10
  function executeCreateLib(templatesDir, libraryDir) {
9
11
  try {
10
12
  fs.cpSync(path.join(templatesDir, 'lib'), libraryDir, {
11
13
  recursive: true,
12
- filter: (src) => !src.endsWith('.gitkeep')
14
+ filter: (src) => src.endsWith('.gitkeep') === false
13
15
  });
14
16
  console.log('Library created successfully');
15
17
  }
@@ -21,7 +23,7 @@ function executeCreateContext(templatesDir, contextDir) {
21
23
  try {
22
24
  fs.cpSync(path.join(templatesDir, 'ctx'), contextDir, {
23
25
  recursive: true,
24
- filter: (src) => !src.endsWith('.gitkeep')
26
+ filter: (src) => src.endsWith('.gitkeep') === false
25
27
  });
26
28
  console.log('Context created successfully');
27
29
  }
@@ -29,24 +31,43 @@ function executeCreateContext(templatesDir, contextDir) {
29
31
  console.error(err);
30
32
  }
31
33
  }
34
+ function executeCreateReactContext(templatesDir, contextDir) {
35
+ try {
36
+ fs.cpSync(path.join(templatesDir, 'ctx-react'), contextDir, {
37
+ recursive: true,
38
+ filter: (src) => src.endsWith('.gitkeep') === false
39
+ });
40
+ console.log('React context created successfully');
41
+ }
42
+ catch (err) {
43
+ console.error(err);
44
+ }
45
+ }
32
46
  function main(program) {
33
47
  const templatesDir = path.join(import.meta.dirname, '..', 'templates');
34
48
  const options = program.opts();
35
49
  let targetDir = path.resolve(options.dir ?? process.cwd());
36
50
  if (Object.keys(options).length === 0) {
37
51
  program.help();
38
- return;
39
52
  }
40
- if (!fs.existsSync(targetDir)) {
53
+ if (fs.existsSync(targetDir) === false) {
41
54
  fs.mkdirSync(targetDir, { recursive: true });
42
55
  }
43
56
  if (options.lib !== undefined) {
44
57
  targetDir = path.join(targetDir, options.lib);
45
58
  executeCreateLib(templatesDir, targetDir);
46
59
  }
60
+ if (options.react === true && options.ctx === undefined) {
61
+ program.error('Option --react requires --ctx <name>');
62
+ }
47
63
  if (options.ctx !== undefined) {
48
64
  targetDir = path.join(targetDir, options.ctx);
49
- executeCreateContext(templatesDir, targetDir);
65
+ if (options.react === true) {
66
+ executeCreateReactContext(templatesDir, targetDir);
67
+ }
68
+ else {
69
+ executeCreateContext(templatesDir, targetDir);
70
+ }
50
71
  }
51
72
  }
52
73
  const packageJson = readPackageJson();
@@ -55,6 +76,7 @@ program
55
76
  .version(packageJson.version)
56
77
  .option('--lib <name>', "creates a new library with it's shared directory")
57
78
  .option('--ctx <name>', 'creates a new context')
79
+ .option('-R, --react', 'creates a React context with --ctx')
58
80
  .option('--dir <path>', 'sets the directory to create the new item')
59
81
  .parse(process.argv);
60
82
  main(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tshex-cli",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "author": "https://github.com/virtualitems/",
5
5
  "description": "Typescript Hexagonal Architecture CLI",
6
6
  "type": "module",
package/readme.md CHANGED
@@ -20,10 +20,11 @@ https://github.com/virtualitems/tshex-cli/issues
20
20
 
21
21
  `tshex` scaffolds folders and files for a hexagonal architecture project. It does not write business logic for you; it only generates the structure, so you can fill it in with your own code.
22
22
 
23
- There are two things you can generate:
23
+ There are four things you can generate:
24
24
 
25
25
  - A **library** (`--lib`): the shared foundation of a project. It contains the domain and application contracts (entities, value objects, services, etc.) that the rest of the code depends on.
26
26
  - A **context** (`--ctx`): a specific business area (e.g. `users`, `billing`, `orders`). It contains the `domain/`, `application/`, and `adapters/` folders where you implement that area's logic.
27
+ - A **React context** (`--react-context`): a React-ready context scaffold.
27
28
 
28
29
  A typical project has one library and one or more contexts inside it.
29
30
 
@@ -50,18 +51,19 @@ tshex --help
50
51
  ## Usage
51
52
 
52
53
  ```bash
53
- tshex [--lib <name>] [--ctx <name>] [--dir <path>]
54
+ tshex [--lib <name>] [--ctx <name>] [--react-context <name>] [--dir <path>]
54
55
  ```
55
56
 
56
57
  | Option | Purpose |
57
58
  | -------------- | ------------------------------------------------------------------- |
58
59
  | `--lib <name>` | Generate a library called `<name>`, based on `templates/lib`. |
59
60
  | `--ctx <name>` | Generate a context called `<name>`, based on `templates/ctx`. |
61
+ | `--react-context <name>` | Generate a React context called `<name>`, based on `templates/react-context`. |
60
62
  | `--dir <path>` | Parent directory where the library/context will be created. Defaults to the current directory. |
61
63
  | `--help` | Show the command options. |
62
64
  | `--version` | Show the installed version. |
63
65
 
64
- `--lib` and `--ctx` can be used together in a single command (see [Create a library and a context together](#create-a-library-and-a-context-together)). Running `tshex` without any options just prints the help text — it does not generate anything.
66
+ `--lib`, `--ctx`, and `--react-context` can be used together in a single command. Running `tshex` without any options just prints the help text — it does not generate anything.
65
67
 
66
68
  ## Create a library
67
69
 
@@ -203,3 +205,13 @@ src/
203
205
  ├── domain/
204
206
  └── index.ts
205
207
  ```
208
+
209
+ ## Create a React context
210
+
211
+ Use this when you want only the React context scaffold:
212
+
213
+ ```bash
214
+ tshex --react-context users
215
+ ```
216
+
217
+ This generates a `users/` folder in the current directory.
package/source/main.ts CHANGED
@@ -12,19 +12,16 @@ import path from 'node:path'
12
12
  // FUNCTIONS
13
13
 
14
14
  function readPackageJson() {
15
- return JSON.parse(
16
- fs.readFileSync(
17
- path.join(import.meta.dirname, '..', 'package.json'),
18
- 'utf-8'
19
- )
20
- )
15
+ const filePath = path.join(import.meta.dirname, '..', 'package.json')
16
+ const fileContents = fs.readFileSync(filePath, 'utf-8')
17
+ return JSON.parse(fileContents)
21
18
  }
22
19
 
23
20
  function executeCreateLib(templatesDir: string, libraryDir: string) {
24
21
  try {
25
22
  fs.cpSync(path.join(templatesDir, 'lib'), libraryDir, {
26
23
  recursive: true,
27
- filter: (src) => !src.endsWith('.gitkeep')
24
+ filter: (src) => src.endsWith('.gitkeep') === false
28
25
  })
29
26
  console.log('Library created successfully')
30
27
  } catch (err) {
@@ -36,7 +33,7 @@ function executeCreateContext(templatesDir: string, contextDir: string) {
36
33
  try {
37
34
  fs.cpSync(path.join(templatesDir, 'ctx'), contextDir, {
38
35
  recursive: true,
39
- filter: (src) => !src.endsWith('.gitkeep')
36
+ filter: (src) => src.endsWith('.gitkeep') === false
40
37
  })
41
38
  console.log('Context created successfully')
42
39
  } catch (err) {
@@ -44,6 +41,18 @@ function executeCreateContext(templatesDir: string, contextDir: string) {
44
41
  }
45
42
  }
46
43
 
44
+ function executeCreateReactContext(templatesDir: string, contextDir: string) {
45
+ try {
46
+ fs.cpSync(path.join(templatesDir, 'ctx-react'), contextDir, {
47
+ recursive: true,
48
+ filter: (src) => src.endsWith('.gitkeep') === false
49
+ })
50
+ console.log('React context created successfully')
51
+ } catch (err) {
52
+ console.error(err)
53
+ }
54
+ }
55
+
47
56
  function main(program: typeof import('commander').program) {
48
57
  const templatesDir = path.join(import.meta.dirname, '..', 'templates')
49
58
 
@@ -53,10 +62,9 @@ function main(program: typeof import('commander').program) {
53
62
 
54
63
  if (Object.keys(options).length === 0) {
55
64
  program.help()
56
- return
57
65
  }
58
66
 
59
- if (!fs.existsSync(targetDir)) {
67
+ if (fs.existsSync(targetDir) === false) {
60
68
  fs.mkdirSync(targetDir, { recursive: true })
61
69
  }
62
70
 
@@ -65,9 +73,18 @@ function main(program: typeof import('commander').program) {
65
73
  executeCreateLib(templatesDir, targetDir)
66
74
  }
67
75
 
76
+ if (options.react === true && options.ctx === undefined) {
77
+ program.error('Option --react requires --ctx <name>')
78
+ }
79
+
68
80
  if (options.ctx !== undefined) {
69
81
  targetDir = path.join(targetDir, options.ctx)
70
- executeCreateContext(templatesDir, targetDir)
82
+
83
+ if (options.react === true) {
84
+ executeCreateReactContext(templatesDir, targetDir)
85
+ } else {
86
+ executeCreateContext(templatesDir, targetDir)
87
+ }
71
88
  }
72
89
  }
73
90
 
@@ -78,6 +95,7 @@ program
78
95
  .version(packageJson.version)
79
96
  .option('--lib <name>', "creates a new library with it's shared directory")
80
97
  .option('--ctx <name>', 'creates a new context')
98
+ .option('-R, --react', 'creates a React context with --ctx')
81
99
  .option('--dir <path>', 'sets the directory to create the new item')
82
100
  .parse(process.argv)
83
101
 
@@ -0,0 +1,5 @@
1
+ // Ports are exports from the context root level
2
+
3
+ export function example(): void {
4
+ // ...
5
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,81 +1,102 @@
1
- // Libraries
1
+ type Generic<T = unknown> = Record<string, T>
2
2
 
3
- // Same Layer
3
+ /**
4
+ * @description
5
+ */
6
+ export interface Filterable<S = Generic> {
7
+ filter(selector: S): Promise<Array<S>>
8
+ }
4
9
 
5
- // Lower Layers
10
+ /**
11
+ * @description
12
+ */
13
+ export interface Sortable<S = Generic> {
14
+ sort(selector: S): Promise<Array<S>>
15
+ }
6
16
 
7
- // Types
17
+ /**
18
+ * @description
19
+ */
20
+ export interface Creatable<D = Generic> {
21
+ create(data: D): Promise<unknown>
22
+ }
8
23
 
9
- // Constants
24
+ /**
25
+ * @description
26
+ */
27
+ export interface Updatable<S = Generic, D = Generic> {
28
+ update(selector: S, data: D): Promise<unknown>
29
+ }
10
30
 
11
31
  /**
12
32
  * @description
13
33
  */
14
- export abstract class DataManager {
15
- [property: string]: unknown
34
+ export interface Deletable<S = Generic> {
35
+ delete(selector: S): Promise<unknown>
36
+ }
16
37
 
17
- // Public Attributes
38
+ /**
39
+ * @description
40
+ */
41
+ export interface Aggregatable<S = Generic> {
42
+ aggregate(selector: S): Promise<S>
43
+ }
18
44
 
19
- // Protected Attributes
45
+ /**
46
+ * @description
47
+ */
48
+ export interface Relatable {
49
+ selectRelated(...args: unknown[]): unknown
20
50
 
21
- // Private Attributes
51
+ prefetchRelated(...args: unknown[]): unknown
52
+ }
22
53
 
23
- // Public Static Attributes
54
+ /**
55
+ * @description
56
+ */
57
+ export abstract class DataManager<T = Generic> {
58
+ [property: string]: unknown
24
59
 
25
- // Protected Static Attributes
60
+ public abstract all(): Promise<Array<T>>
26
61
 
27
- // Private Static Attributes
62
+ public abstract none(): Array<T>
63
+ } //:: class
28
64
 
29
- // Constructor, Getters, Setters
65
+ /**
66
+ * @description
67
+ */
68
+ export abstract class DatasetManager<T = Generic> extends DataManager<T> {
69
+ [property: string]: unknown
30
70
 
31
- // Public Methods
71
+ public abstract union(other: Array<T>): Promise<Array<T>>
32
72
 
33
- public abstract connect(...args: unknown[]): Promise<unknown>
73
+ public abstract intersection(other: Array<T>): Promise<Array<T>>
34
74
 
35
- public abstract disconnect(): Promise<unknown>
75
+ public abstract difference(other: Array<T>): Promise<Array<T>>
36
76
 
37
- // Protected Methods
77
+ public abstract symmetric_difference(other: Array<T>): Promise<Array<T>>
38
78
 
39
- // Private Methods
79
+ public abstract complement(other: Array<T>): Promise<Array<T>>
80
+ } //:: class
40
81
 
41
- // Public Static Methods
82
+ /**
83
+ * @description
84
+ */
85
+ export abstract class DriverManager<M extends DataManager = DataManager> {
86
+ [property: string]: unknown
42
87
 
43
- // Protected Static Methods
88
+ public abstract connect(...args: unknown[]): Promise<M>
44
89
 
45
- // Private Static Methods
90
+ public abstract disconnect(): Promise<unknown>
46
91
  } //:: class
47
92
 
48
93
  /**
49
94
  * @description Represents a data source.
50
95
  */
51
- export abstract class Repository<Manager extends DataManager> {
96
+ export abstract class Repository<M extends DriverManager = DriverManager> {
52
97
  [property: string]: unknown
53
98
 
54
- // Public Attributes
55
-
56
- // Protected Attributes
57
-
58
- // Private Attributes
59
-
60
- // Public Static Attributes
61
-
62
- // Protected Static Attributes
63
-
64
- // Private Static Attributes
65
-
66
- // Constructor, Getters, Setters
67
-
68
- public constructor(public readonly manager: Manager) {}
69
-
70
- // Public Methods
71
-
72
- // Protected Methods
73
-
74
- // Private Methods
75
-
76
- // Public Static Methods
77
-
78
- // Protected Static Methods
99
+ public constructor(public readonly manager: M) {}
79
100
 
80
- // Private Static Methods
101
+ protected abstract transform<T = Generic>(data: Generic): T
81
102
  } //:: class
@@ -1,12 +1,12 @@
1
- // Libraries
1
+ export const DEBUG = 10
2
2
 
3
- // Same Layer
3
+ export const INFO = 20
4
4
 
5
- // Lower Layers
5
+ export const WARNING = 30
6
6
 
7
- // Types
7
+ export const ERROR = 40
8
8
 
9
- // Constants
9
+ export const CRITICAL = 50
10
10
 
11
11
  /**
12
12
  * @description
@@ -14,22 +14,6 @@
14
14
  export abstract class Logger {
15
15
  [property: string]: unknown
16
16
 
17
- // public ATTRIBUTES
18
-
19
- // protected ATTRIBUTES
20
-
21
- // private ATTRIBUTES
22
-
23
- // public static ATTRIBUTES
24
-
25
- // protected static ATTRIBUTES
26
-
27
- // private static ATTRIBUTES
28
-
29
- // Constructor, Getters, Setters
30
-
31
- // public METHODS
32
-
33
17
  public abstract debug(data: unknown): void
34
18
 
35
19
  public abstract info(data: unknown): void
@@ -38,13 +22,5 @@ export abstract class Logger {
38
22
 
39
23
  public abstract error(data: unknown): void
40
24
 
41
- // protected METHODS
42
-
43
- // private METHODS
44
-
45
- // public static METHODS
46
-
47
- // protected static METHODS
48
-
49
- // private static METHODS
25
+ public abstract critical(data: unknown): void
50
26
  } //:: class
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @description
3
+ */
4
+ export interface Validatable {
5
+ [property: string]: unknown
6
+
7
+ isValid(): boolean
8
+
9
+ validate(): unknown
10
+ }
@@ -1,9 +0,0 @@
1
- // Ports layer
2
-
3
- // Adapters layer
4
-
5
- // Application layer
6
-
7
- // Domain layer
8
-
9
- // Constants