@mbsi/mkcmd 0.2.2 → 0.2.4
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/CHANGELOG.md +45 -0
- package/README.md +89 -66
- package/dist/index.js +188 -33
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,40 +7,84 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-1-1
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `WatchConfig` interface in `src/config.ts` for defining watch targets
|
|
15
|
+
- Support for both `"dir"` and `"file"` types in watch configurations
|
|
16
|
+
- `scaffold-rest.ts` function for handling arbitrary watch targets
|
|
17
|
+
- `src/data/index.ts` for centralized data exports
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- `stringifier.ts` now reads from `config.watchConfigs` instead of hardcoded paths
|
|
22
|
+
- `stringifier.ts` supports watching individual files and multiple directories
|
|
23
|
+
- `parseFolder` renamed and refactored to support both directory and file processing
|
|
24
|
+
- `stringifier.ts` currently only supports typescript and md files - other file types may need special file handling.
|
|
25
|
+
- `README.md` to match current export structure.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
The following are marked under 0.2.4 in git, but are released in 0.3.0+
|
|
29
|
+
- `src/functions/scaffold-core.ts` - using `cwd` to handle folder creation, matching the relative pathing intimated by the clack prompt masking.
|
|
30
|
+
- `src/functions/scaffold-project.ts` - same as above
|
|
31
|
+
- `src/README.md` - finished styling directory markup
|
|
32
|
+
|
|
33
|
+
## [0.2.3] - 2025-12-30
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
I forgot to push some files from 0.2.2 to github and then forgot to make sure they existed before publishing to npm.
|
|
38
|
+
Oh well.
|
|
10
39
|
|
|
11
40
|
## [0.2.2] - 2025-12-30
|
|
12
41
|
|
|
13
42
|
### Added
|
|
43
|
+
|
|
14
44
|
- `src/core/helpers/stringifier.ts` to codegen before building
|
|
15
45
|
- `prebuild` script to dynamically update the code located in data/core at build time.
|
|
16
46
|
- `src/data/core.ts` is generated / regenerated at before building for use in dist
|
|
47
|
+
- `README.md` - Rewrote to make sense for display on NPM store as NPX package
|
|
17
48
|
|
|
18
49
|
### Fixed
|
|
50
|
+
|
|
19
51
|
- `src/functions/scaffold-core.ts` doesn't try to pull data that doesn't exist anymore :^)
|
|
52
|
+
- `src/core/cli.ts` doesn't try to read the version from the user's computer anymore (hopefully)
|
|
53
|
+
|
|
54
|
+
### Moved
|
|
55
|
+
|
|
56
|
+
- Original `README.md` moved to `src/README.md` - it's for devs, anyways.
|
|
20
57
|
|
|
21
58
|
## [0.2.1] - 2025-12-30
|
|
59
|
+
|
|
22
60
|
### Added
|
|
61
|
+
|
|
23
62
|
- `CHANGELOG.md` for tracking changes
|
|
24
63
|
|
|
25
64
|
### Changed
|
|
65
|
+
|
|
26
66
|
- Simplified `file-utils.ts` by removing path caching (was causing issues with non-existent directories)
|
|
27
67
|
|
|
28
68
|
### Fixed
|
|
69
|
+
|
|
29
70
|
- Directory creation bug: `realpath()` now replaced with `resolve()` to handle new target directories
|
|
30
71
|
- Path resolution in bundled code for version command
|
|
31
72
|
|
|
32
73
|
### Removed
|
|
74
|
+
|
|
33
75
|
- Path caching in `file-utils.ts` (unnecessary optimization causing failures)
|
|
34
76
|
- Removed unused imports in `src/functions/orchestrate-scaffold.ts` to lint warnings
|
|
35
77
|
|
|
36
78
|
## [0.2.0] - 2025-12-30
|
|
37
79
|
|
|
38
80
|
### Added
|
|
81
|
+
|
|
39
82
|
- Build system with `bun build --target=bun`
|
|
40
83
|
- Build scripts: `build`, `build:exe`, `prepack`
|
|
41
84
|
- npm package preparation (removed `private: true`)
|
|
42
85
|
|
|
43
86
|
### Changed
|
|
87
|
+
|
|
44
88
|
- Moved `typescript` from peerDependencies to devDependencies
|
|
45
89
|
- Updated package.json entry points to `./dist/index.js`
|
|
46
90
|
- Fixed `--version` command to use `process.cwd()` for package.json resolution
|
|
@@ -48,6 +92,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
48
92
|
## [0.1.0] - 2025-12-30
|
|
49
93
|
|
|
50
94
|
### Added
|
|
95
|
+
|
|
51
96
|
- Initial CLI scaffolding tool
|
|
52
97
|
- Interactive project setup with `@clack/prompts`
|
|
53
98
|
- Full CLI scaffold generation (package.json, tsconfig.json, README.md, core files)
|
package/README.md
CHANGED
|
@@ -1,111 +1,134 @@
|
|
|
1
1
|
# mkcmd
|
|
2
2
|
|
|
3
|
-
A
|
|
4
|
-
|
|
5
|
-
**Version:** 0.2.0 | See [CHANGELOG.md](./CHANGELOG.md) for version history.
|
|
3
|
+
A CLI tool for scaffolding new CLI projects with sensible defaults. Create command-line tools with TypeScript, Bun runtime, and a solid core structure out of the box.
|
|
6
4
|
|
|
7
5
|
## Features
|
|
8
6
|
|
|
9
|
-
- **Interactive
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
7
|
+
- **Interactive Setup** - Prompts for project name, location, and description
|
|
8
|
+
- **Complete CLI Framework** - Generates a working CLI with command registration, logging, and helpers
|
|
9
|
+
- **TypeScript + Bun** - Pre-configured with TypeScript and Bun runtime support
|
|
10
|
+
- **Core Utilities** - Includes `FileBuilder` for dynamic code generation and file utilities
|
|
11
|
+
- **Extensible** - Easy to add your own commands
|
|
12
|
+
|
|
13
|
+
> [!WARNING]
|
|
14
|
+
> While you can *run* the program in without Bun, the source code itself **depends on Bun** for development and building
|
|
15
|
+
|
|
16
|
+
## Run remotely
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx @mbsi/mkcmd init
|
|
20
|
+
# or
|
|
21
|
+
bun @mbsi/mkcmd init
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g @mbsi/mkcmd
|
|
28
|
+
# or
|
|
29
|
+
bun install -g @mbsi/mkcmd
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
mkcmd init
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The `init` command will prompt you for:
|
|
39
|
+
- Project name
|
|
40
|
+
- Target directory (defaults to `./<project-name>`)
|
|
41
|
+
- Project description
|
|
14
42
|
|
|
15
43
|
## What Gets Scaffolding
|
|
16
44
|
|
|
17
|
-
|
|
45
|
+
After running `mkcmd init`, you'll have a complete CLI project:
|
|
18
46
|
|
|
19
47
|
```
|
|
20
|
-
|
|
48
|
+
my-cli/
|
|
21
49
|
├── src/
|
|
22
50
|
│ ├── core/
|
|
23
|
-
│ │ ├── cli.ts
|
|
24
|
-
│ │ ├── log.ts
|
|
25
|
-
│ │
|
|
26
|
-
│ │
|
|
51
|
+
│ │ ├── cli.ts # CLI framework with command registration
|
|
52
|
+
│ │ ├── log.ts # Logging helpers (single/multi info/warn/err, title)
|
|
53
|
+
│ │ └── helpers/
|
|
54
|
+
│ │ ├── file-builder.ts # Indentation-aware file builder
|
|
55
|
+
│ │ ├── file-utils.ts # Path and file writing utilities
|
|
56
|
+
│ │ └── stringifier.ts # Dynamic template code generation
|
|
27
57
|
│ ├── commands/
|
|
28
|
-
│ │ └── index.ts
|
|
29
|
-
│ └── config.ts
|
|
58
|
+
│ │ └── index.ts # Command registration hook
|
|
59
|
+
│ └── config.ts # Project configuration
|
|
30
60
|
├── package.json
|
|
31
61
|
├── tsconfig.json
|
|
32
62
|
└── README.md
|
|
33
63
|
```
|
|
34
64
|
|
|
35
|
-
##
|
|
65
|
+
## Usage
|
|
36
66
|
|
|
37
|
-
###
|
|
67
|
+
### Running Your New CLI
|
|
38
68
|
|
|
39
69
|
```bash
|
|
70
|
+
cd my-cli
|
|
40
71
|
bun install
|
|
72
|
+
bun run src/index.ts --help
|
|
41
73
|
```
|
|
42
74
|
|
|
43
|
-
###
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
npm install -g mkcmd
|
|
47
|
-
# or
|
|
48
|
-
bun install -g mkcmd
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Usage
|
|
52
|
-
|
|
53
|
-
### Development
|
|
75
|
+
### Adding Commands
|
|
54
76
|
|
|
55
|
-
|
|
56
|
-
# Show help
|
|
57
|
-
bun run src/index.ts --help
|
|
77
|
+
Commands are registered in `src/commands/index.ts`. Here's the pattern:
|
|
58
78
|
|
|
59
|
-
|
|
60
|
-
|
|
79
|
+
```typescript
|
|
80
|
+
import { registerCommand } from "../core/cli";
|
|
61
81
|
|
|
62
|
-
|
|
63
|
-
|
|
82
|
+
registerCommand({
|
|
83
|
+
name: "greet",
|
|
84
|
+
description: "Say hello",
|
|
85
|
+
instructions: "Pass a name to greet",
|
|
86
|
+
run: async (args: string[]) => {
|
|
87
|
+
const name = args[0] || "world";
|
|
88
|
+
console.log(`Hello, ${name}!`);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
64
91
|
```
|
|
65
92
|
|
|
66
|
-
|
|
93
|
+
Then run:
|
|
67
94
|
|
|
68
95
|
```bash
|
|
69
|
-
|
|
70
|
-
bun run
|
|
71
|
-
bun dist/index.js --help
|
|
72
|
-
|
|
73
|
-
# Build standalone executable
|
|
74
|
-
bun run build:exe
|
|
75
|
-
./dist/mkcmd --help
|
|
96
|
+
bun run src/index.ts greet
|
|
97
|
+
bun run src/index.ts greet Alice
|
|
76
98
|
```
|
|
77
99
|
|
|
78
|
-
###
|
|
100
|
+
### Using the File Builder
|
|
79
101
|
|
|
80
|
-
|
|
81
|
-
mkcmd --help
|
|
82
|
-
mkcmd init
|
|
83
|
-
```
|
|
102
|
+
The included `FileBuilder` helps generate code files dynamically:
|
|
84
103
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
104
|
+
```typescript
|
|
105
|
+
import { FileBuilder } from "./core/helpers/file-builder";
|
|
106
|
+
|
|
107
|
+
const fb = new FileBuilder();
|
|
108
|
+
fb.addLine("export function hello() {");
|
|
109
|
+
fb.addLine(' console.log("Hello!");', 1);
|
|
110
|
+
fb.addLine("}");
|
|
111
|
+
const code = fb.build();
|
|
112
|
+
```
|
|
89
113
|
|
|
90
|
-
##
|
|
114
|
+
## CLI Flags
|
|
91
115
|
|
|
92
|
-
|
|
116
|
+
After installation, `mkcmd` supports:
|
|
93
117
|
|
|
94
118
|
```bash
|
|
95
|
-
#
|
|
96
|
-
|
|
119
|
+
mkcmd --help # Show help
|
|
120
|
+
mkcmd --version # Show version
|
|
121
|
+
```
|
|
97
122
|
|
|
98
|
-
|
|
99
|
-
bun run build:exe
|
|
123
|
+
## Requirements
|
|
100
124
|
|
|
101
|
-
|
|
102
|
-
npm
|
|
103
|
-
```
|
|
125
|
+
- Bun runtime (for running the generated project)
|
|
126
|
+
- Node.js 16+ (for installation via npm)
|
|
104
127
|
|
|
105
|
-
|
|
128
|
+
## License
|
|
106
129
|
|
|
107
|
-
|
|
130
|
+
See LICENSE file for details.
|
|
108
131
|
|
|
109
|
-
|
|
132
|
+
---
|
|
110
133
|
|
|
111
|
-
See
|
|
134
|
+
**Version:** See `npm info @mbsi/mkcmd version`, `npx @mbsi/mkcmd --version`, or run `mkcmd --version` after installation.
|
package/dist/index.js
CHANGED
|
@@ -1586,12 +1586,21 @@ var log = {
|
|
|
1586
1586
|
var log_default = log;
|
|
1587
1587
|
|
|
1588
1588
|
// src/core/cli.ts
|
|
1589
|
-
import { join as
|
|
1589
|
+
import { join as join3 } from "path";
|
|
1590
1590
|
|
|
1591
1591
|
// src/config.ts
|
|
1592
|
+
import { join as join2 } from "path";
|
|
1592
1593
|
var config = {
|
|
1593
1594
|
about_text: "mkcmd is a remote node executable for scaffolding other remote node executables with sensible defaults.",
|
|
1594
|
-
more_info_text: "See https://github.com/mackenziebowes/mkcmd for more details."
|
|
1595
|
+
more_info_text: "See https://github.com/mackenziebowes/mkcmd for more details.",
|
|
1596
|
+
watchConfigs: [
|
|
1597
|
+
{
|
|
1598
|
+
name: "core",
|
|
1599
|
+
type: "dir",
|
|
1600
|
+
sourcePath: join2(".", "src", "core"),
|
|
1601
|
+
outputPath: join2(".", "src", "data", "core.ts")
|
|
1602
|
+
}
|
|
1603
|
+
]
|
|
1595
1604
|
};
|
|
1596
1605
|
|
|
1597
1606
|
// src/core/cli.ts
|
|
@@ -1631,7 +1640,8 @@ async function runCLI(argv = Bun.argv.slice(2)) {
|
|
|
1631
1640
|
return;
|
|
1632
1641
|
}
|
|
1633
1642
|
if (["-v", "--version"].includes(name)) {
|
|
1634
|
-
const
|
|
1643
|
+
const pkgPath = join3(import.meta.dir, "..", "package.json");
|
|
1644
|
+
const pkgText = await Bun.file(pkgPath).text();
|
|
1635
1645
|
const pkg = JSON.parse(pkgText);
|
|
1636
1646
|
log_default.multi.info([
|
|
1637
1647
|
{
|
|
@@ -2124,10 +2134,10 @@ async function promptProjectDetails() {
|
|
|
2124
2134
|
|
|
2125
2135
|
// src/core/helpers/file-utils.ts
|
|
2126
2136
|
import { mkdir } from "fs/promises";
|
|
2127
|
-
import { resolve, join as
|
|
2137
|
+
import { resolve, join as join4 } from "path";
|
|
2128
2138
|
async function writeFileTuple([targetDir, relativePath, content]) {
|
|
2129
2139
|
const fullPath = resolve(targetDir, relativePath);
|
|
2130
|
-
await mkdir(
|
|
2140
|
+
await mkdir(join4(fullPath, ".."), { recursive: true });
|
|
2131
2141
|
await Bun.write(fullPath, content);
|
|
2132
2142
|
}
|
|
2133
2143
|
|
|
@@ -2156,11 +2166,33 @@ var commands_init = () => {
|
|
|
2156
2166
|
};
|
|
2157
2167
|
var config_init = (about) => {
|
|
2158
2168
|
const file = new FileBuilder;
|
|
2159
|
-
file.addLine(`
|
|
2169
|
+
file.addLine(`import { join } from "node:path";`);
|
|
2170
|
+
file.addEmptyLine();
|
|
2171
|
+
file.addLine(`export interface WatchConfig {`);
|
|
2172
|
+
file.addLine(`name: string;`, 1);
|
|
2173
|
+
file.addLine(`type: "dir" | "file";`, 1);
|
|
2174
|
+
file.addLine(`sourcePath: string;`, 1);
|
|
2175
|
+
file.addLine(`outputPath: string;`, 1);
|
|
2176
|
+
file.addLine(`}`);
|
|
2177
|
+
file.addEmptyLine();
|
|
2178
|
+
file.addLine(`type Config = {`);
|
|
2179
|
+
file.addLine(`about_text: string;`, 1);
|
|
2180
|
+
file.addLine(`more_info_text: string;`, 1);
|
|
2181
|
+
file.addLine(`watchConfigs: WatchConfig[];`, 1);
|
|
2182
|
+
file.addLine(`}`);
|
|
2183
|
+
file.addLine(`export const config: Config = {`, 0);
|
|
2160
2184
|
file.addLine(`about_text:`, 2);
|
|
2161
2185
|
file.addLine(`"${about}",`, 1);
|
|
2162
2186
|
file.addLine(`more_info_text:`, 2);
|
|
2163
2187
|
file.addLine(`"See https://github.com/mackenziebowes/mkcmd for more details.",`, 1);
|
|
2188
|
+
file.addLine(`watchConfigs: [`, 1);
|
|
2189
|
+
file.addLine(`{`, 2);
|
|
2190
|
+
file.addLine(`name: "core",`, 3);
|
|
2191
|
+
file.addLine(`type: "dir",`, 3);
|
|
2192
|
+
file.addLine(`sourcePath: join(".", "src", "core"),`, 3);
|
|
2193
|
+
file.addLine(`outputPath: join(".", "src", "data", "core.ts"),`, 3);
|
|
2194
|
+
file.addLine(`},`, 2);
|
|
2195
|
+
file.addLine(`],`, 1);
|
|
2164
2196
|
file.addLine(`};`, 0);
|
|
2165
2197
|
return file.build();
|
|
2166
2198
|
};
|
|
@@ -2250,10 +2282,10 @@ async function scaffoldProject(prompts) {
|
|
|
2250
2282
|
}
|
|
2251
2283
|
|
|
2252
2284
|
// src/functions/scaffold-core.ts
|
|
2253
|
-
import { join as
|
|
2285
|
+
import { join as join5, dirname as dirname2 } from "path";
|
|
2286
|
+
import { cwd } from "process";
|
|
2254
2287
|
import { existsSync } from "fs";
|
|
2255
2288
|
import { mkdir as mkdir2, writeFile } from "fs/promises";
|
|
2256
|
-
import { cwd } from "process";
|
|
2257
2289
|
|
|
2258
2290
|
// src/data/core.ts
|
|
2259
2291
|
var src_core_cli_init = () => {
|
|
@@ -2307,7 +2339,8 @@ var src_core_cli_init = () => {
|
|
|
2307
2339
|
fb.addLine(" }");
|
|
2308
2340
|
fb.addLine("");
|
|
2309
2341
|
fb.addLine(' if (["-v", "--version"].includes(name)) {');
|
|
2310
|
-
fb.addLine(' const
|
|
2342
|
+
fb.addLine(' const pkgPath = join(import.meta.dir, "..", "package.json");');
|
|
2343
|
+
fb.addLine(" const pkgText = await Bun.file(pkgPath).text();");
|
|
2311
2344
|
fb.addLine(" const pkg = JSON.parse(pkgText);");
|
|
2312
2345
|
fb.addLine(" log.multi.info([");
|
|
2313
2346
|
fb.addLine(" {");
|
|
@@ -2483,10 +2516,10 @@ var src_core_helpers_stringifier_init = () => {
|
|
|
2483
2516
|
fb.addLine('import { readdir, writeFile } from "node:fs/promises";');
|
|
2484
2517
|
fb.addLine('import { FileBuilder } from "./file-builder";');
|
|
2485
2518
|
fb.addLine('import { statSync } from "node:fs";');
|
|
2519
|
+
fb.addLine('import { cwd } from "node:process";');
|
|
2520
|
+
fb.addLine('import { config } from "../../config";');
|
|
2486
2521
|
fb.addLine("");
|
|
2487
|
-
fb.addLine("
|
|
2488
|
-
fb.addLine("");
|
|
2489
|
-
fb.addLine("async function generateTemplate(path: string) {");
|
|
2522
|
+
fb.addLine("async function generateTemplateFromTs(path: string) {");
|
|
2490
2523
|
fb.addLine(' if (path.endsWith(".ts")) {');
|
|
2491
2524
|
fb.addLine(" const content = await Bun.file(path).text();");
|
|
2492
2525
|
fb.addLine(" const fb = new FileBuilder();");
|
|
@@ -2496,6 +2529,8 @@ var src_core_helpers_stringifier_init = () => {
|
|
|
2496
2529
|
fb.addLine(' .split("-")');
|
|
2497
2530
|
fb.addLine(' .join("_")');
|
|
2498
2531
|
fb.addLine(' .split(".")[0];');
|
|
2532
|
+
fb.addLine(" if (!snaked_title)");
|
|
2533
|
+
fb.addLine(" throw new Error(`Failed to generate identifier for path: ${path}`);");
|
|
2499
2534
|
fb.addLine(' fb.addLine(`const ${snaked_title + "_init"} = () => {`);');
|
|
2500
2535
|
fb.addLine(" fb.addLine(`const fb = new FileBuilder();`, 1);");
|
|
2501
2536
|
fb.addLine(' const lines = content.split("\\n");');
|
|
@@ -2506,42 +2541,135 @@ var src_core_helpers_stringifier_init = () => {
|
|
|
2506
2541
|
fb.addLine(' fb.addLine("return fb.build();", 1);');
|
|
2507
2542
|
fb.addLine(' fb.addLine("};");');
|
|
2508
2543
|
fb.addLine(" fb.addEmptyLine();");
|
|
2509
|
-
fb.addLine(" fb.addLine(`
|
|
2544
|
+
fb.addLine(" fb.addLine(`const ${snaked_title} = {`);");
|
|
2510
2545
|
fb.addLine(' fb.addLine(`location: "${path}",`, 1);');
|
|
2511
2546
|
fb.addLine(' fb.addLine(`content: ${snaked_title + "_init"}`, 1);');
|
|
2512
2547
|
fb.addLine(" fb.addLine(`};`);");
|
|
2513
2548
|
fb.addLine(" const out = fb.build();");
|
|
2514
|
-
fb.addLine("
|
|
2515
|
-
fb.addLine(" return out;");
|
|
2549
|
+
fb.addLine(" return { name: snaked_title, content: out };");
|
|
2516
2550
|
fb.addLine(" }");
|
|
2517
|
-
fb.addLine(
|
|
2551
|
+
fb.addLine(" return null;");
|
|
2552
|
+
fb.addLine("}");
|
|
2553
|
+
fb.addLine("");
|
|
2554
|
+
fb.addLine("async function generateTemplateFromMd(path: string) {");
|
|
2555
|
+
fb.addLine(' if (path.endsWith(".md")) {');
|
|
2556
|
+
fb.addLine(" const content = await Bun.file(path).text();");
|
|
2557
|
+
fb.addLine(" const fb = new FileBuilder();");
|
|
2558
|
+
fb.addLine(" const snaked_title = path");
|
|
2559
|
+
fb.addLine(' .split("/")');
|
|
2560
|
+
fb.addLine(' .join("_")');
|
|
2561
|
+
fb.addLine(' .split("-")');
|
|
2562
|
+
fb.addLine(' .join("_")');
|
|
2563
|
+
fb.addLine(' .split(".")[0];');
|
|
2564
|
+
fb.addLine(" if (!snaked_title)");
|
|
2565
|
+
fb.addLine(" throw new Error(`Failed to generate identifier for path: ${path}`);");
|
|
2566
|
+
fb.addLine(' fb.addLine(`const ${snaked_title + "_init"} = () => {`);');
|
|
2567
|
+
fb.addLine(" fb.addLine(`const fb = new FileBuilder();`, 1);");
|
|
2568
|
+
fb.addLine(' const lines = content.split("\\n");');
|
|
2569
|
+
fb.addLine(" for (const line of lines) {");
|
|
2570
|
+
fb.addLine(` const cleanLine = line.replaceAll("\\\\", "\\\\\\\\").replaceAll('"', '\\\\"');`);
|
|
2571
|
+
fb.addLine(' fb.addLine(`fb.addLine("${cleanLine}")`, 1);');
|
|
2572
|
+
fb.addLine(" }");
|
|
2573
|
+
fb.addLine(' fb.addLine("return fb.build();", 1);');
|
|
2574
|
+
fb.addLine(' fb.addLine("};");');
|
|
2575
|
+
fb.addLine(" fb.addEmptyLine();");
|
|
2576
|
+
fb.addLine(" fb.addLine(`const ${snaked_title} = {`);");
|
|
2577
|
+
fb.addLine(' fb.addLine(`location: "${path}",`, 1);');
|
|
2578
|
+
fb.addLine(' fb.addLine(`content: ${snaked_title + "_init"}`, 1);');
|
|
2579
|
+
fb.addLine(" fb.addLine(`};`);");
|
|
2580
|
+
fb.addLine(" const out = fb.build();");
|
|
2581
|
+
fb.addLine(" return { name: snaked_title, content: out };");
|
|
2582
|
+
fb.addLine(" }");
|
|
2583
|
+
fb.addLine(" return null;");
|
|
2584
|
+
fb.addLine("}");
|
|
2585
|
+
fb.addLine("");
|
|
2586
|
+
fb.addLine("async function generateTemplate(path: string) {");
|
|
2587
|
+
fb.addLine(' if (path.endsWith(".ts")) {');
|
|
2588
|
+
fb.addLine(" return generateTemplateFromTs(path);");
|
|
2589
|
+
fb.addLine(" }");
|
|
2590
|
+
fb.addLine(' if (path.endsWith(".md")) {');
|
|
2591
|
+
fb.addLine(" return generateTemplateFromMd(path);");
|
|
2592
|
+
fb.addLine(" }");
|
|
2593
|
+
fb.addLine(" return null;");
|
|
2518
2594
|
fb.addLine("}");
|
|
2519
2595
|
fb.addLine("");
|
|
2520
2596
|
fb.addLine("async function parseFolder(path: string, fb: FileBuilder) {");
|
|
2597
|
+
fb.addLine(" const outExport: string[] = [];");
|
|
2521
2598
|
fb.addLine(" const items = await readdir(path);");
|
|
2522
2599
|
fb.addLine(" for (const item of items) {");
|
|
2523
2600
|
fb.addLine(" const relPath = join(path, item);");
|
|
2524
2601
|
fb.addLine(" const itemStat = statSync(relPath);");
|
|
2525
2602
|
fb.addLine(" if (itemStat.isDirectory()) {");
|
|
2526
|
-
fb.addLine(" await parseFolder(relPath, fb);");
|
|
2603
|
+
fb.addLine(" const nestedExports = await parseFolder(relPath, fb);");
|
|
2604
|
+
fb.addLine(" outExport.push(...nestedExports);");
|
|
2527
2605
|
fb.addLine(" }");
|
|
2528
2606
|
fb.addLine(' if (item.endsWith(".ts")) {');
|
|
2529
|
-
fb.addLine("
|
|
2530
|
-
fb.addLine("
|
|
2607
|
+
fb.addLine(" const template = await generateTemplate(relPath);");
|
|
2608
|
+
fb.addLine(" if (template) {");
|
|
2609
|
+
fb.addLine(" fb.addLine(template.content);");
|
|
2610
|
+
fb.addLine(" fb.addEmptyLine();");
|
|
2611
|
+
fb.addLine(" outExport.push(template.name);");
|
|
2612
|
+
fb.addLine(" }");
|
|
2531
2613
|
fb.addLine(" }");
|
|
2532
2614
|
fb.addLine(" }");
|
|
2615
|
+
fb.addLine(" return outExport;");
|
|
2533
2616
|
fb.addLine("}");
|
|
2534
2617
|
fb.addLine("");
|
|
2535
|
-
fb.addLine("async function
|
|
2536
|
-
fb.addLine(' const sourceCoreDir = join(".", "src", "core");');
|
|
2618
|
+
fb.addLine("async function exportDataTemplates() {");
|
|
2537
2619
|
fb.addLine(" const fb = new FileBuilder();");
|
|
2538
|
-
fb.addLine(
|
|
2620
|
+
fb.addLine(" const exportList: string[] = [];");
|
|
2621
|
+
fb.addLine(' const dataFiles = await readdir(join(cwd(), "src", "data"));');
|
|
2622
|
+
fb.addLine(" for (const file of dataFiles) {");
|
|
2623
|
+
fb.addLine(' if (file == "init.ts" || file == "core.ts" || file == "index.ts") {');
|
|
2624
|
+
fb.addLine(" continue;");
|
|
2625
|
+
fb.addLine(" }");
|
|
2626
|
+
fb.addLine(' const content = await Bun.file(join(cwd(), "src", "data", file)).text();');
|
|
2627
|
+
fb.addLine(' const lines = content.split("\\n");');
|
|
2628
|
+
fb.addLine(" const exportStatement = lines.pop();");
|
|
2629
|
+
fb.addLine(" if (!exportStatement) throw new Error(`Parsed file ${file} is empty`);");
|
|
2630
|
+
fb.addLine(' const functionName = exportStatement.split(" ")[2];');
|
|
2631
|
+
fb.addLine(" if (!functionName)");
|
|
2632
|
+
fb.addLine(" throw new Error(");
|
|
2633
|
+
fb.addLine(" `Parse file ${file} is malformed - missing export statement`,");
|
|
2634
|
+
fb.addLine(" );");
|
|
2635
|
+
fb.addLine(" exportList.push(functionName);");
|
|
2636
|
+
fb.addLine(' fb.addLine(`import { ${functionName} } from "./${file}";`);');
|
|
2637
|
+
fb.addLine(" }");
|
|
2539
2638
|
fb.addLine(" fb.addEmptyLine();");
|
|
2540
|
-
fb.addLine(
|
|
2541
|
-
fb.addLine(' fb.addLine(
|
|
2542
|
-
fb.addLine(
|
|
2639
|
+
fb.addLine(' fb.addLine("type DataExport = {");');
|
|
2640
|
+
fb.addLine(' fb.addLine("location: string", 1);');
|
|
2641
|
+
fb.addLine(' fb.addLine("content: () => string", 1);');
|
|
2642
|
+
fb.addLine(' fb.addLine("};");');
|
|
2643
|
+
fb.addLine(" fb.addEmptyLine();");
|
|
2644
|
+
fb.addLine(' fb.addLine(`const data: DataExport[] = [${exportList.join(", ")}];`);');
|
|
2645
|
+
fb.addLine(' fb.addLine("export { data }");');
|
|
2543
2646
|
fb.addLine(" const out = fb.build();");
|
|
2544
|
-
fb.addLine(' await writeFile(join(
|
|
2647
|
+
fb.addLine(' await writeFile(join(cwd(), "src", "data", "index.ts"), out, "utf8");');
|
|
2648
|
+
fb.addLine("}");
|
|
2649
|
+
fb.addLine("");
|
|
2650
|
+
fb.addLine("async function generateTemplates() {");
|
|
2651
|
+
fb.addLine(" for (const watchConfig of config.watchConfigs) {");
|
|
2652
|
+
fb.addLine(" const fb = new FileBuilder();");
|
|
2653
|
+
fb.addLine(' fb.addLine(`import { FileBuilder } from "../core/helpers/file-builder";`);');
|
|
2654
|
+
fb.addLine(" fb.addEmptyLine();");
|
|
2655
|
+
fb.addLine(' if (watchConfig.type == "dir") {');
|
|
2656
|
+
fb.addLine(" const exports = await parseFolder(watchConfig.sourcePath, fb);");
|
|
2657
|
+
fb.addLine(' fb.addLine(`const ${watchConfig.name} = [${exports.join(", ")}]`);');
|
|
2658
|
+
fb.addLine(" fb.addLine(`export { ${watchConfig.name} }`);");
|
|
2659
|
+
fb.addLine(" const out = fb.build();");
|
|
2660
|
+
fb.addLine(' await writeFile(watchConfig.outputPath, out, "utf8");');
|
|
2661
|
+
fb.addLine(" } else {");
|
|
2662
|
+
fb.addLine(" const template = await generateTemplate(watchConfig.sourcePath);");
|
|
2663
|
+
fb.addLine(" if (template) {");
|
|
2664
|
+
fb.addLine(" fb.addLine(template.content);");
|
|
2665
|
+
fb.addLine(" fb.addEmptyLine();");
|
|
2666
|
+
fb.addLine(" fb.addLine(`export { ${template.name} }`);");
|
|
2667
|
+
fb.addLine(" const out = fb.build();");
|
|
2668
|
+
fb.addLine(' await writeFile(watchConfig.outputPath, out, "utf8");');
|
|
2669
|
+
fb.addLine(" }");
|
|
2670
|
+
fb.addLine(" }");
|
|
2671
|
+
fb.addLine(" }");
|
|
2672
|
+
fb.addLine(" exportDataTemplates();");
|
|
2545
2673
|
fb.addLine("}");
|
|
2546
2674
|
fb.addLine("");
|
|
2547
2675
|
fb.addLine("generateTemplates();");
|
|
@@ -2572,18 +2700,43 @@ var src_core_helpers_file_utils = {
|
|
|
2572
2700
|
var core = [src_core_cli, src_core_log, src_core_helpers_file_builder, src_core_helpers_stringifier, src_core_helpers_file_utils];
|
|
2573
2701
|
|
|
2574
2702
|
// src/functions/scaffold-core.ts
|
|
2575
|
-
var currentDir = join4(cwd());
|
|
2576
2703
|
async function scaffoldCore(targetDir) {
|
|
2577
|
-
const combinedPath =
|
|
2578
|
-
|
|
2704
|
+
const combinedPath = join5(cwd(), targetDir);
|
|
2705
|
+
if (!existsSync(combinedPath)) {
|
|
2706
|
+
await mkdir2(combinedPath, { recursive: true });
|
|
2707
|
+
}
|
|
2579
2708
|
for (const file of core) {
|
|
2580
2709
|
const relativePath = file.location.replace(/^\.\//, "");
|
|
2581
|
-
const parentDir =
|
|
2582
|
-
console.dir({ parentDir });
|
|
2710
|
+
const parentDir = join5(combinedPath, dirname2(relativePath));
|
|
2583
2711
|
if (!existsSync(parentDir)) {
|
|
2584
|
-
mkdir2(parentDir, { recursive: true });
|
|
2712
|
+
await mkdir2(parentDir, { recursive: true });
|
|
2713
|
+
}
|
|
2714
|
+
await writeFile(join5(combinedPath, relativePath), file.content(), "utf8");
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
|
|
2718
|
+
// src/functions/scaffold-rest.ts
|
|
2719
|
+
import { join as join6, dirname as dirname3 } from "path";
|
|
2720
|
+
import { cwd as cwd2 } from "process";
|
|
2721
|
+
import { existsSync as existsSync2 } from "fs";
|
|
2722
|
+
import { mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
|
|
2723
|
+
|
|
2724
|
+
// src/data/index.ts
|
|
2725
|
+
var data = [];
|
|
2726
|
+
|
|
2727
|
+
// src/functions/scaffold-rest.ts
|
|
2728
|
+
async function scaffoldRest(targetDir) {
|
|
2729
|
+
const combinedPath = join6(cwd2(), targetDir);
|
|
2730
|
+
if (!existsSync2(combinedPath)) {
|
|
2731
|
+
await mkdir3(combinedPath, { recursive: true });
|
|
2732
|
+
}
|
|
2733
|
+
for (const file of data) {
|
|
2734
|
+
const relativePath = file.location.replace(/^\.\//, "");
|
|
2735
|
+
const parentDir = join6(combinedPath, dirname3(relativePath));
|
|
2736
|
+
if (!existsSync2(parentDir)) {
|
|
2737
|
+
await mkdir3(parentDir, { recursive: true });
|
|
2585
2738
|
}
|
|
2586
|
-
|
|
2739
|
+
await writeFile2(join6(combinedPath, relativePath), file.content(), "utf8");
|
|
2587
2740
|
}
|
|
2588
2741
|
}
|
|
2589
2742
|
|
|
@@ -2594,6 +2747,8 @@ async function orchestrateScaffold() {
|
|
|
2594
2747
|
log_default.single.info("Project", "Project files created");
|
|
2595
2748
|
await scaffoldCore(prompts.targetDir);
|
|
2596
2749
|
log_default.single.info("Core", "Core files copied");
|
|
2750
|
+
await scaffoldRest(prompts.targetDir);
|
|
2751
|
+
log_default.single.info("Rest", "All files copied");
|
|
2597
2752
|
log_default.multi.info([
|
|
2598
2753
|
{ t: "Success", m: "Project scaffolded successfully!" },
|
|
2599
2754
|
{ t: "Location", m: prompts.targetDir },
|