tshex-cli 1.0.15 → 1.0.16
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 +54 -5
- package/package.json +1 -1
- package/readme.md +27 -3
- package/source/main.ts +61 -10
- package/templates/ctx/index.ts +0 -9
- package/templates/react-context/adapters/hooks/.gitkeep +0 -0
- package/templates/react-context/adapters/schemas/.gitkeep +0 -0
- package/templates/react-context/application/.gitkeep +0 -0
- package/templates/react-context/domain/.gitkeep +0 -0
- package/templates/react-context/languages/.gitkeep +0 -0
- package/templates/react-project/core/context/adapters/api/.gitkeep +0 -0
- package/templates/react-project/core/context/adapters/hooks/.gitkeep +0 -0
- package/templates/react-project/core/context/adapters/schemas/.gitkeep +0 -0
- package/templates/react-project/core/context/application/.gitkeep +0 -0
- package/templates/react-project/core/context/domain/.gitkeep +0 -0
- package/templates/react-project/core/context/languages/.gitkeep +0 -0
- package/templates/react-project/core/shared/adapters/i18n/.gitkeep +0 -0
- package/templates/react-project/dom-client/context/Example.tsx +11 -0
- package/templates/react-project/dom-client/context/assets/.gitkeep +0 -0
- package/templates/react-project/dom-client/context/styles/.gitkeep +0 -0
- package/templates/react-project/dom-server/context/Example.tsx +11 -0
- package/templates/react-project/dom-server/context/assets/.gitkeep +0 -0
- package/templates/react-project/dom-server/context/styles/.gitkeep +0 -0
- package/templates/react-project/index.d.ts +1 -0
- package/templates/react-project/native/context/Example.tsx +11 -0
- package/templates/react-project/native/context/assets/.gitkeep +0 -0
- package/templates/react-project/native/context/styles/.gitkeep +0 -0
- package/templates/react-project/tests/core/.gitkeep +0 -0
- package/templates/react-project/tests/dom-client/.gitkeep +0 -0
- package/templates/react-project/tests/dom-server/.gitkeep +0 -0
- package/templates/react-project/tests/native/.gitkeep +0 -0
- /package/{source/index.d.ts → templates/react-context/adapters/api/.gitkeep} +0 -0
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
|
-
|
|
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) =>
|
|
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) =>
|
|
26
|
+
filter: (src) => src.endsWith('.gitkeep') === false
|
|
25
27
|
});
|
|
26
28
|
console.log('Context created successfully');
|
|
27
29
|
}
|
|
@@ -29,15 +31,52 @@ function executeCreateContext(templatesDir, contextDir) {
|
|
|
29
31
|
console.error(err);
|
|
30
32
|
}
|
|
31
33
|
}
|
|
34
|
+
function copyDirectoryContents(sourceDir, destinationDir) {
|
|
35
|
+
const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
|
|
36
|
+
for (const entry of entries) {
|
|
37
|
+
const sourcePath = path.join(sourceDir, entry.name);
|
|
38
|
+
const destinationPath = path.join(destinationDir, entry.name);
|
|
39
|
+
if (fs.existsSync(destinationPath) === false) {
|
|
40
|
+
fs.cpSync(sourcePath, destinationPath, {
|
|
41
|
+
recursive: true,
|
|
42
|
+
filter: (src) => src.endsWith('.gitkeep') === false
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function executeCreateReactProject(templatesDir, projectDir) {
|
|
48
|
+
try {
|
|
49
|
+
fs.cpSync(path.join(templatesDir, 'react-project'), projectDir, {
|
|
50
|
+
recursive: true,
|
|
51
|
+
filter: (src) => src.endsWith('.gitkeep') === false
|
|
52
|
+
});
|
|
53
|
+
copyDirectoryContents(path.join(templatesDir, 'lib', 'shared'), path.join(projectDir, 'core', 'shared'));
|
|
54
|
+
console.log('React project created successfully');
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
console.error(err);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function executeCreateReactContext(templatesDir, contextDir) {
|
|
61
|
+
try {
|
|
62
|
+
fs.cpSync(path.join(templatesDir, 'react-context'), contextDir, {
|
|
63
|
+
recursive: true,
|
|
64
|
+
filter: (src) => src.endsWith('.gitkeep') === false
|
|
65
|
+
});
|
|
66
|
+
console.log('React context created successfully');
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
console.error(err);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
32
72
|
function main(program) {
|
|
33
73
|
const templatesDir = path.join(import.meta.dirname, '..', 'templates');
|
|
34
74
|
const options = program.opts();
|
|
35
75
|
let targetDir = path.resolve(options.dir ?? process.cwd());
|
|
36
76
|
if (Object.keys(options).length === 0) {
|
|
37
77
|
program.help();
|
|
38
|
-
return;
|
|
39
78
|
}
|
|
40
|
-
if (
|
|
79
|
+
if (fs.existsSync(targetDir) === false) {
|
|
41
80
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
42
81
|
}
|
|
43
82
|
if (options.lib !== undefined) {
|
|
@@ -48,6 +87,14 @@ function main(program) {
|
|
|
48
87
|
targetDir = path.join(targetDir, options.ctx);
|
|
49
88
|
executeCreateContext(templatesDir, targetDir);
|
|
50
89
|
}
|
|
90
|
+
if (options.reactProject !== undefined) {
|
|
91
|
+
targetDir = path.join(targetDir, options.reactProject);
|
|
92
|
+
executeCreateReactProject(templatesDir, targetDir);
|
|
93
|
+
}
|
|
94
|
+
if (options.reactContext !== undefined) {
|
|
95
|
+
targetDir = path.join(targetDir, options.reactContext);
|
|
96
|
+
executeCreateReactContext(templatesDir, targetDir);
|
|
97
|
+
}
|
|
51
98
|
}
|
|
52
99
|
const packageJson = readPackageJson();
|
|
53
100
|
program
|
|
@@ -56,5 +103,7 @@ program
|
|
|
56
103
|
.option('--lib <name>', "creates a new library with it's shared directory")
|
|
57
104
|
.option('--ctx <name>', 'creates a new context')
|
|
58
105
|
.option('--dir <path>', 'sets the directory to create the new item')
|
|
106
|
+
.option('--react-project <name>', 'creates a new React project')
|
|
107
|
+
.option('--react-context <name>', 'creates a new React context')
|
|
59
108
|
.parse(process.argv);
|
|
60
109
|
main(program);
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -20,10 +20,12 @@ 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
|
|
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 project** (`--react-project`): a full React-oriented hexagonal structure with `core/`, `dom-client/`, `dom-server/`, and `native/` folders.
|
|
28
|
+
- A **React context** (`--react-context`): a React-ready context scaffold.
|
|
27
29
|
|
|
28
30
|
A typical project has one library and one or more contexts inside it.
|
|
29
31
|
|
|
@@ -50,18 +52,20 @@ tshex --help
|
|
|
50
52
|
## Usage
|
|
51
53
|
|
|
52
54
|
```bash
|
|
53
|
-
tshex [--lib <name>] [--ctx <name>] [--dir <path>]
|
|
55
|
+
tshex [--lib <name>] [--ctx <name>] [--react-project <name>] [--react-context <name>] [--dir <path>]
|
|
54
56
|
```
|
|
55
57
|
|
|
56
58
|
| Option | Purpose |
|
|
57
59
|
| -------------- | ------------------------------------------------------------------- |
|
|
58
60
|
| `--lib <name>` | Generate a library called `<name>`, based on `templates/lib`. |
|
|
59
61
|
| `--ctx <name>` | Generate a context called `<name>`, based on `templates/ctx`. |
|
|
62
|
+
| `--react-project <name>` | Generate a React project called `<name>`, based on `templates/react-project` and `templates/lib/shared`. |
|
|
63
|
+
| `--react-context <name>` | Generate a React context called `<name>`, based on `templates/react-context`. |
|
|
60
64
|
| `--dir <path>` | Parent directory where the library/context will be created. Defaults to the current directory. |
|
|
61
65
|
| `--help` | Show the command options. |
|
|
62
66
|
| `--version` | Show the installed version. |
|
|
63
67
|
|
|
64
|
-
`--lib
|
|
68
|
+
`--lib`, `--ctx`, `--react-project`, 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
69
|
|
|
66
70
|
## Create a library
|
|
67
71
|
|
|
@@ -203,3 +207,23 @@ src/
|
|
|
203
207
|
├── domain/
|
|
204
208
|
└── index.ts
|
|
205
209
|
```
|
|
210
|
+
|
|
211
|
+
## Create a React project
|
|
212
|
+
|
|
213
|
+
Use this when you want the React-specific project scaffold with the shared `core/shared` contracts copied from the library template:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
tshex --react-project app
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
This generates a `app/` folder in the current directory.
|
|
220
|
+
|
|
221
|
+
## Create a React context
|
|
222
|
+
|
|
223
|
+
Use this when you want only the React context scaffold:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
tshex --react-context users
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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) =>
|
|
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) =>
|
|
36
|
+
filter: (src) => src.endsWith('.gitkeep') === false
|
|
40
37
|
})
|
|
41
38
|
console.log('Context created successfully')
|
|
42
39
|
} catch (err) {
|
|
@@ -44,6 +41,49 @@ function executeCreateContext(templatesDir: string, contextDir: string) {
|
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
|
|
44
|
+
function copyDirectoryContents(sourceDir: string, destinationDir: string) {
|
|
45
|
+
const entries = fs.readdirSync(sourceDir, { withFileTypes: true })
|
|
46
|
+
|
|
47
|
+
for (const entry of entries) {
|
|
48
|
+
const sourcePath = path.join(sourceDir, entry.name)
|
|
49
|
+
const destinationPath = path.join(destinationDir, entry.name)
|
|
50
|
+
|
|
51
|
+
if (fs.existsSync(destinationPath) === false) {
|
|
52
|
+
fs.cpSync(sourcePath, destinationPath, {
|
|
53
|
+
recursive: true,
|
|
54
|
+
filter: (src) => src.endsWith('.gitkeep') === false
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function executeCreateReactProject(templatesDir: string, projectDir: string) {
|
|
61
|
+
try {
|
|
62
|
+
fs.cpSync(path.join(templatesDir, 'react-project'), projectDir, {
|
|
63
|
+
recursive: true,
|
|
64
|
+
filter: (src) => src.endsWith('.gitkeep') === false
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
copyDirectoryContents(path.join(templatesDir, 'lib', 'shared'), path.join(projectDir, 'core', 'shared'))
|
|
68
|
+
|
|
69
|
+
console.log('React project created successfully')
|
|
70
|
+
} catch (err) {
|
|
71
|
+
console.error(err)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function executeCreateReactContext(templatesDir: string, contextDir: string) {
|
|
76
|
+
try {
|
|
77
|
+
fs.cpSync(path.join(templatesDir, 'react-context'), contextDir, {
|
|
78
|
+
recursive: true,
|
|
79
|
+
filter: (src) => src.endsWith('.gitkeep') === false
|
|
80
|
+
})
|
|
81
|
+
console.log('React context created successfully')
|
|
82
|
+
} catch (err) {
|
|
83
|
+
console.error(err)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
47
87
|
function main(program: typeof import('commander').program) {
|
|
48
88
|
const templatesDir = path.join(import.meta.dirname, '..', 'templates')
|
|
49
89
|
|
|
@@ -53,10 +93,9 @@ function main(program: typeof import('commander').program) {
|
|
|
53
93
|
|
|
54
94
|
if (Object.keys(options).length === 0) {
|
|
55
95
|
program.help()
|
|
56
|
-
return
|
|
57
96
|
}
|
|
58
97
|
|
|
59
|
-
if (
|
|
98
|
+
if (fs.existsSync(targetDir) === false) {
|
|
60
99
|
fs.mkdirSync(targetDir, { recursive: true })
|
|
61
100
|
}
|
|
62
101
|
|
|
@@ -69,6 +108,16 @@ function main(program: typeof import('commander').program) {
|
|
|
69
108
|
targetDir = path.join(targetDir, options.ctx)
|
|
70
109
|
executeCreateContext(templatesDir, targetDir)
|
|
71
110
|
}
|
|
111
|
+
|
|
112
|
+
if (options.reactProject !== undefined) {
|
|
113
|
+
targetDir = path.join(targetDir, options.reactProject)
|
|
114
|
+
executeCreateReactProject(templatesDir, targetDir)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (options.reactContext !== undefined) {
|
|
118
|
+
targetDir = path.join(targetDir, options.reactContext)
|
|
119
|
+
executeCreateReactContext(templatesDir, targetDir)
|
|
120
|
+
}
|
|
72
121
|
}
|
|
73
122
|
|
|
74
123
|
const packageJson = readPackageJson()
|
|
@@ -79,6 +128,8 @@ program
|
|
|
79
128
|
.option('--lib <name>', "creates a new library with it's shared directory")
|
|
80
129
|
.option('--ctx <name>', 'creates a new context')
|
|
81
130
|
.option('--dir <path>', 'sets the directory to create the new item')
|
|
131
|
+
.option('--react-project <name>', 'creates a new React project')
|
|
132
|
+
.option('--react-context <name>', 'creates a new React context')
|
|
82
133
|
.parse(process.argv)
|
|
83
134
|
|
|
84
135
|
main(program)
|
package/templates/ctx/index.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
type Generic<T=unknown> = Record<string, T>;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|