tkeron 4.5.0 → 5.0.0

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 CHANGED
@@ -1,3 +1,38 @@
1
+ # v5.0.0
2
+
3
+ ## Breaking: sourceDir and targetDir removed as CLI arguments
4
+
5
+ - `tk build` and `tk dev` no longer accept positional directory arguments
6
+ - Fixed convention: source in `websrc/`, output in `web/`
7
+ - To migrate: rename your source directory to `websrc/` (`mv your-dir websrc`)
8
+ - Output is always `web/` (sibling of `websrc/`) — no longer configurable via CLI
9
+ - `port` and `host` remain as positional arguments for `tk dev`
10
+
11
+ ## Fix: pre-rendering module resolution in projects without node_modules
12
+
13
+ - `processPre.ts` now injects the absolute resolved path of `@tkeron/html-parser` instead of the bare specifier
14
+ - Fixes failure when the user's project lives inside a workspace root with a `node_modules/` that doesn't include `@tkeron` dependencies
15
+
16
+ ### Migration
17
+
18
+ ```bash
19
+ # Before (v4.x)
20
+ tk build src dist
21
+ tk dev src dist 8080
22
+
23
+ # After (v5.0)
24
+ tk build
25
+ tk dev 8080
26
+ ```
27
+
28
+ ### What changed
29
+
30
+ - `buildWrapper` no longer forwards `sourceDir`/`targetDir` to `build()`
31
+ - CLI positioned arguments for directories removed from `build` and `develop` commands
32
+ - Documentation updated (cli-reference, getting-started)
33
+
34
+ ---
35
+
1
36
  # v4.5.0
2
37
 
3
38
  ## tsconfig.json Generation on Init
@@ -52,30 +52,22 @@ Build your project by processing source files into static output.
52
52
  **Usage:**
53
53
 
54
54
  ```bash
55
- tk build [sourceDir] [targetDir]
55
+ tk build
56
56
  ```
57
57
 
58
- **Arguments:**
58
+ **Convention:**
59
59
 
60
- | Argument | Type | Default | Description |
61
- | ----------- | ------ | -------- | ---------------------------------------------- |
62
- | `sourceDir` | string | `websrc` | Source directory containing your project files |
63
- | `targetDir` | string | `web` | Output directory for built files |
60
+ - Source directory: `websrc/` (relative to current directory)
61
+ - Output directory: `web/` (sibling of `websrc/`)
64
62
 
65
63
  **Examples:**
66
64
 
67
65
  ```bash
68
- # Build with defaults (websrc → web)
66
+ # Build the project
69
67
  tk build
70
68
 
71
- # Build with custom source directory
72
- tk build src web
73
-
74
- # Build to custom output directory
75
- tk build websrc dist
76
-
77
- # Build with both custom
78
- tk build source output
69
+ # Using alias
70
+ tk b
79
71
  ```
80
72
 
81
73
  **Build Process:**
@@ -120,17 +112,20 @@ Start a development server with hot reload.
120
112
  **Usage:**
121
113
 
122
114
  ```bash
123
- tk develop [sourceDir] [outputDir] [port] [host]
115
+ tk develop [port] [host]
124
116
  ```
125
117
 
126
118
  **Arguments:**
127
119
 
128
- | Argument | Type | Default | Description |
129
- | ----------- | ------ | ----------- | --------------------------- |
130
- | `sourceDir` | string | `websrc` | Source directory to watch |
131
- | `outputDir` | string | `web` | Output directory for builds |
132
- | `port` | number | `3000` | Port for development server |
133
- | `host` | string | `localhost` | Host to bind server to |
120
+ | Argument | Type | Default | Description |
121
+ | -------- | ------ | ----------- | --------------------------- |
122
+ | `port` | number | `3000` | Port for development server |
123
+ | `host` | string | `localhost` | Host to bind server to |
124
+
125
+ **Convention:**
126
+
127
+ - Source directory: `websrc/` (relative to current directory)
128
+ - Output directory: `web/` (sibling of `websrc/`)
134
129
 
135
130
  **Examples:**
136
131
 
@@ -138,17 +133,14 @@ tk develop [sourceDir] [outputDir] [port] [host]
138
133
  # Start with defaults
139
134
  tk dev
140
135
 
141
- # Custom source and output
142
- tk dev src dist
143
-
144
136
  # Custom port
145
- tk dev websrc web 8080
137
+ tk dev 8080
146
138
 
147
139
  # Bind to all interfaces
148
- tk dev websrc web 3000 0.0.0.0
140
+ tk dev 3000 0.0.0.0
149
141
 
150
142
  # Complete custom configuration
151
- tk develop source output 8080 0.0.0.0
143
+ tk develop 8080 0.0.0.0
152
144
  ```
153
145
 
154
146
  **What It Does:**
@@ -317,7 +309,7 @@ tk init . --force
317
309
  cd my-website
318
310
 
319
311
  # Start development server
320
- tk dev websrc
312
+ tk dev
321
313
 
322
314
  # Open http://localhost:3000
323
315
  ```
@@ -356,7 +348,7 @@ Quick reference for command shortcuts:
356
348
  ```bash
357
349
  tk b # Same as: tk build
358
350
  tk d # Same as: tk develop
359
- tk dev websrc web 8080 # Same as: tk develop websrc web 8080
351
+ tk dev 8080 # Same as: tk develop 8080
360
352
  tk i my-site # Same as: tk init my-site
361
353
  ```
362
354
 
@@ -430,22 +422,19 @@ Tkeron uses **convention over configuration**. There are no configuration files.
430
422
 
431
423
  **Project Structure Convention:**
432
424
 
433
- - Source directory: `websrc/` (default)
434
- - Output directory: `web/` (default)
425
+ - Source directory: `websrc/` (fixed)
426
+ - Output directory: `web/` (fixed)
435
427
  - Component files: `*.com.html` and `*.com.ts`
436
428
  - Pre-render files: `*.pre.ts`
437
429
  - Type definitions: `tkeron.d.ts`
438
430
 
439
431
  **Customization:**
440
432
 
441
- All customization is done via command-line arguments:
433
+ Server configuration is done via command-line arguments:
442
434
 
443
435
  ```bash
444
- # Custom directories
445
- tk build src dist
446
-
447
436
  # Custom server config
448
- tk dev src dist 8080 0.0.0.0
437
+ tk dev 8080 0.0.0.0
449
438
  ```
450
439
 
451
440
  ---
@@ -580,7 +569,7 @@ Error: Port 3000 is already in use
580
569
 
581
570
  ```bash
582
571
  # Use different port
583
- tk dev websrc web 3001
572
+ tk dev 3001
584
573
  ```
585
574
 
586
575
  ### Source Directory Not Found
@@ -597,8 +586,8 @@ tk dev websrc web 3001
597
586
  # Create directory
598
587
  mkdir websrc
599
588
 
600
- # Or use correct path
601
- tk build src web
589
+ # Or initialize a new project
590
+ tk init .
602
591
  ```
603
592
 
604
593
  ### Permission Denied
@@ -668,11 +657,8 @@ tk dev
668
657
  # Build for production
669
658
  NODE_ENV=production tk build
670
659
 
671
- # Build to custom directory
672
- tk build websrc dist
673
-
674
660
  # Development on port 8080
675
- tk dev websrc web 8080
661
+ tk dev 8080
676
662
 
677
663
  # Initialize in current directory
678
664
  tk init .
@@ -65,22 +65,20 @@ tk init my-website --force
65
65
  Build your project to compile it into static files:
66
66
 
67
67
  ```bash
68
- tk build websrc web
68
+ tk build
69
69
  ```
70
70
 
71
- **Parameters:**
71
+ **Convention:**
72
72
 
73
- - First argument: source directory (default: `websrc`)
74
- - Second argument: output directory (default: `web`)
73
+ - Source: `websrc/` (relative to current directory)
74
+ - Output: `web/` (sibling of `websrc/`)
75
75
 
76
- **Shorthand:**
76
+ **Using alias:**
77
77
 
78
78
  ```bash
79
- tk build
79
+ tk b
80
80
  ```
81
81
 
82
- This uses the defaults: `websrc` → `web`
83
-
84
82
  **Output structure:**
85
83
 
86
84
  ```
@@ -110,20 +108,18 @@ This will:
110
108
  **Custom configuration:**
111
109
 
112
110
  ```bash
113
- tk dev websrc web 8080 0.0.0.0
111
+ tk dev 8080 0.0.0.0
114
112
  ```
115
113
 
116
114
  **Parameters:**
117
115
 
118
- - Source directory (default: `websrc`)
119
- - Output directory (default: `web`)
120
116
  - Port (default: `3000`)
121
117
  - Host (default: `localhost`)
122
118
 
123
119
  **Example with custom port:**
124
120
 
125
121
  ```bash
126
- tk dev websrc web 8080
122
+ tk dev 8080
127
123
  ```
128
124
 
129
125
  Visit `http://localhost:8080` in your browser.
@@ -212,17 +208,14 @@ Open `web/index.html` in your browser. You'll see the greeting component inlined
212
208
  # Show help
213
209
  tk
214
210
 
215
- # Build with defaults
211
+ # Build the project
216
212
  tk build
217
213
 
218
- # Build with custom directories
219
- tk build src dist
220
-
221
214
  # Start dev server
222
215
  tk dev
223
216
 
224
217
  # Start dev server on port 8080
225
- tk dev websrc web 8080
218
+ tk dev 8080
226
219
 
227
220
  # Initialize new project
228
221
  tk init my-project
@@ -248,14 +241,14 @@ Now that you have a basic understanding:
248
241
 
249
242
  ### "Source directory does not exist"
250
243
 
251
- Make sure you're running commands from the right directory:
244
+ Make sure you're running commands from the right directory and that `websrc/` exists:
252
245
 
253
246
  ```bash
254
247
  # Check if websrc exists
255
248
  ls websrc
256
249
 
257
- # Or specify the correct path
258
- tk build path/to/websrc path/to/web
250
+ # Or run tk init to create a new project
251
+ tk init .
259
252
  ```
260
253
 
261
254
  ### "Command not found: tk"
@@ -271,7 +264,7 @@ bun install -g tkeron
271
264
  Use a different port:
272
265
 
273
266
  ```bash
274
- tk dev websrc web 3001
267
+ tk dev 3001
275
268
  ```
276
269
 
277
270
  ### Components not working
@@ -1,13 +1 @@
1
- // Augment global scope for .pre.ts files
2
- declare module "*.pre.ts" {
3
- global {
4
- const document: Document;
5
- }
6
- }
7
-
8
- // Augment global scope for .com.ts files
9
- declare module "*.com.ts" {
10
- global {
11
- const com: HTMLElement;
12
- }
13
- }
1
+ declare const com: HTMLElement;
package/index.ts CHANGED
@@ -15,8 +15,6 @@ getCommands("tkeron", packageJson.version)
15
15
  .addCommand("build")
16
16
  .addAlias("b")
17
17
  .addDescription("Build the project")
18
- .addPositionedArgument("sourceDir")
19
- .addPositionedArgument("targetDir")
20
18
  .setCallback(buildWrapper)
21
19
 
22
20
  .commands()
@@ -25,8 +23,6 @@ getCommands("tkeron", packageJson.version)
25
23
  .addAlias("dev")
26
24
  .addAlias("d")
27
25
  .addDescription("Start development server")
28
- .addPositionedArgument("sourceDir")
29
- .addPositionedArgument("targetDir")
30
26
  .addPositionedArgument("port")
31
27
  .addPositionedArgument("host")
32
28
  .setCallback(develop)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tkeron",
3
- "version": "4.5.0",
3
+ "version": "5.0.0",
4
4
  "description": "CLI tool for backend-driven frontend development with TypeScript.",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -3,8 +3,6 @@ import type { Logger } from "@tkeron/tools";
3
3
  import { logger as defaultLogger } from "@tkeron/tools";
4
4
 
5
5
  export interface BuildWrapperOptions {
6
- sourceDir?: string;
7
- targetDir?: string;
8
6
  logger?: Logger;
9
7
  [key: string]: any;
10
8
  }
@@ -13,7 +11,7 @@ export const buildWrapper = async (options: BuildWrapperOptions) => {
13
11
  const log = options?.logger || defaultLogger;
14
12
 
15
13
  try {
16
- await build({ ...options, logger: log });
14
+ await build({ logger: log });
17
15
  } catch (error: any) {
18
16
  log.error(`\n❌ Build failed: ${error.message}\n`);
19
17
  process.exit(1);
@@ -0,0 +1,68 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "fs";
2
+ import { join } from "path";
3
+
4
+ const REQUIRED_INCLUDES = ["websrc/**/*", "tkeron.d.ts"];
5
+
6
+ const DEFAULT_COMPILER_OPTIONS = {
7
+ target: "ESNext",
8
+ module: "ESNext",
9
+ lib: ["ESNext", "DOM"],
10
+ moduleResolution: "bundler",
11
+ strict: true,
12
+ skipLibCheck: true,
13
+ };
14
+
15
+ const createFreshTsconfig = () => ({
16
+ compilerOptions: { ...DEFAULT_COMPILER_OPTIONS },
17
+ include: [...REQUIRED_INCLUDES],
18
+ });
19
+
20
+ const mergeIncludes = (existing: string[]): string[] => {
21
+ const merged = [...existing];
22
+ for (const entry of REQUIRED_INCLUDES) {
23
+ if (!merged.includes(entry)) {
24
+ merged.push(entry);
25
+ }
26
+ }
27
+ return merged;
28
+ };
29
+
30
+ export const ensureTsconfig = (
31
+ targetPath: string,
32
+ previousTsconfig?: Record<string, unknown>,
33
+ ) => {
34
+ const tsconfigPath = join(targetPath, "tsconfig.json");
35
+
36
+ if (previousTsconfig) {
37
+ const existingIncludes = Array.isArray(previousTsconfig.include)
38
+ ? (previousTsconfig.include as string[])
39
+ : [];
40
+ const merged = {
41
+ ...previousTsconfig,
42
+ include: mergeIncludes(existingIncludes),
43
+ };
44
+ writeFileSync(tsconfigPath, JSON.stringify(merged, null, 2));
45
+ return;
46
+ }
47
+
48
+ if (existsSync(tsconfigPath)) {
49
+ try {
50
+ const content = readFileSync(tsconfigPath, "utf-8");
51
+ const parsed = JSON.parse(content);
52
+ const existingIncludes = Array.isArray(parsed.include)
53
+ ? (parsed.include as string[])
54
+ : [];
55
+ const merged = { ...parsed, include: mergeIncludes(existingIncludes) };
56
+ writeFileSync(tsconfigPath, JSON.stringify(merged, null, 2));
57
+ return;
58
+ } catch {
59
+ writeFileSync(
60
+ tsconfigPath,
61
+ JSON.stringify(createFreshTsconfig(), null, 2),
62
+ );
63
+ return;
64
+ }
65
+ }
66
+
67
+ writeFileSync(tsconfigPath, JSON.stringify(createFreshTsconfig(), null, 2));
68
+ };
package/src/init.ts CHANGED
@@ -4,7 +4,6 @@ import {
4
4
  mkdirSync,
5
5
  copyFileSync,
6
6
  readFileSync,
7
- writeFileSync,
8
7
  readdirSync,
9
8
  rmSync,
10
9
  } from "fs";
@@ -12,6 +11,7 @@ import { join, resolve, basename } from "path";
12
11
  import type { Logger } from "@tkeron/tools";
13
12
  import { silentLogger } from "@tkeron/tools";
14
13
  import { promptUser } from "./promptUser";
14
+ import { ensureTsconfig } from "./ensureTsconfig";
15
15
 
16
16
  export interface InitOptions {
17
17
  projectName: string;
@@ -30,6 +30,8 @@ export const init = async (options: InitOptions) => {
30
30
  const targetPath = resolve(process.cwd(), projectName);
31
31
  const isCurrentDir = projectName === "." || targetPath === process.cwd();
32
32
 
33
+ let skipWebsrc = false;
34
+
33
35
  if (existsSync(targetPath)) {
34
36
  if (!isCurrentDir) {
35
37
  if (!force) {
@@ -57,18 +59,22 @@ export const init = async (options: InitOptions) => {
57
59
  "\nDo you want to overwrite them? (y/N): ",
58
60
  );
59
61
 
60
- if (!shouldContinue) {
61
- log.log("\n❌ Operation cancelled.");
62
- return;
62
+ if (shouldContinue) {
63
+ existingTkeronFiles.forEach((file) => {
64
+ const filePath = join(targetPath, file);
65
+ rmSync(filePath, { recursive: true, force: true });
66
+ });
67
+ log.log("✓ Cleaned existing tkeron files");
68
+ } else {
69
+ skipWebsrc = existingTkeronFiles.includes("websrc");
63
70
  }
71
+ } else {
72
+ existingTkeronFiles.forEach((file) => {
73
+ const filePath = join(targetPath, file);
74
+ rmSync(filePath, { recursive: true, force: true });
75
+ });
76
+ log.log("✓ Cleaned existing tkeron files");
64
77
  }
65
-
66
- existingTkeronFiles.forEach((file) => {
67
- const filePath = join(targetPath, file);
68
- rmSync(filePath, { recursive: true, force: true });
69
- });
70
-
71
- log.log("✓ Cleaned existing tkeron files");
72
78
  }
73
79
  }
74
80
  }
@@ -91,36 +97,27 @@ export const init = async (options: InitOptions) => {
91
97
  }
92
98
 
93
99
  const tsconfigPath = join(targetPath, "tsconfig.json");
94
- let existingTsconfig: Record<string, unknown> | null = null;
95
- if (isCurrentDir && existsSync(tsconfigPath)) {
100
+ let previousTsconfig: Record<string, unknown> | undefined;
101
+ if (existsSync(tsconfigPath)) {
96
102
  try {
97
- existingTsconfig = JSON.parse(readFileSync(tsconfigPath, "utf-8"));
103
+ previousTsconfig = JSON.parse(readFileSync(tsconfigPath, "utf-8"));
98
104
  } catch {
99
- existingTsconfig = null;
105
+ previousTsconfig = undefined;
100
106
  }
101
107
  }
102
108
 
103
109
  mkdirSync(targetPath, { recursive: true });
104
- cpSync(templatePath, targetPath, { recursive: true });
110
+ const websrcInTemplate = join(templatePath, "websrc");
111
+ cpSync(templatePath, targetPath, {
112
+ recursive: true,
113
+ filter: skipWebsrc
114
+ ? (src: string) =>
115
+ src !== websrcInTemplate && !src.startsWith(websrcInTemplate + "/")
116
+ : undefined,
117
+ });
105
118
  copyFileSync(tkeronDtsPath, join(targetPath, "tkeron.d.ts"));
106
119
 
107
- if (existingTsconfig !== null) {
108
- const templateTsconfig = JSON.parse(readFileSync(tsconfigPath, "utf-8"));
109
- const requiredIncludes: string[] = Array.isArray(templateTsconfig.include)
110
- ? (templateTsconfig.include as string[])
111
- : [];
112
- const existingIncludes: string[] = Array.isArray(existingTsconfig.include)
113
- ? (existingTsconfig.include as string[])
114
- : [];
115
- const mergedIncludes = [...existingIncludes];
116
- for (const entry of requiredIncludes) {
117
- if (!mergedIncludes.includes(entry)) {
118
- mergedIncludes.push(entry);
119
- }
120
- }
121
- const merged = { ...existingTsconfig, include: mergedIncludes };
122
- writeFileSync(tsconfigPath, JSON.stringify(merged, null, 2));
123
- }
120
+ ensureTsconfig(targetPath, previousTsconfig);
124
121
 
125
122
  const projectDisplayName = isCurrentDir ? basename(targetPath) : projectName;
126
123
  log.log(`✓ Created project "${projectDisplayName}"`);
@@ -137,7 +137,9 @@ const processComponentsTs = async (
137
137
 
138
138
  const elementHTML = (child as any).outerHTML;
139
139
 
140
- log.info(`Processing component <${tagName}> from ${componentPath}`);
140
+ log.info(
141
+ `Processing component <${tagName}> from ${componentPath.replace(rootDir, ".")}`,
142
+ );
141
143
 
142
144
  const tempDoc = parseHTML(
143
145
  "<html><body>" + elementHTML + "</body></html>",
@@ -199,7 +201,9 @@ ${codeWithoutImports}
199
201
  await executeComponent(com);
200
202
  }
201
203
  } catch (execError: any) {
202
- log.error(`\n❌ Error executing component <${tagName}>:`);
204
+ log.error(
205
+ `\n❌ Error executing component <${tagName}>: ${componentPath.replace(rootDir, ".")}`,
206
+ );
203
207
  log.error(` ${execError.message}`);
204
208
  throw execError;
205
209
  }
package/src/processPre.ts CHANGED
@@ -7,6 +7,8 @@ const packageJsonPath = join(import.meta.dir, "..", "package.json");
7
7
  const packageJson = await Bun.file(packageJsonPath).json();
8
8
  const TKERON_VERSION = packageJson.version;
9
9
 
10
+ const HTML_PARSER_PATH = import.meta.resolve("@tkeron/html-parser");
11
+
10
12
  const DEFAULT_HTML = `<!DOCTYPE html>
11
13
  <html lang="en">
12
14
  <head>
@@ -48,7 +50,7 @@ export const processPre = async (
48
50
  : DEFAULT_HTML;
49
51
 
50
52
  const modifiedCode = `
51
- import { parseHTML } from "@tkeron/html-parser";
53
+ import { parseHTML } from ${JSON.stringify(HTML_PARSER_PATH)};
52
54
 
53
55
  const htmlPath = ${JSON.stringify(htmlFile)};
54
56
  const htmlContent = ${JSON.stringify(htmlContent)};
package/tkeron.d.ts CHANGED
@@ -1,13 +1 @@
1
- // Augment global scope for .pre.ts files
2
- declare module "*.pre.ts" {
3
- global {
4
- const document: Document;
5
- }
6
- }
7
-
8
- // Augment global scope for .com.ts files
9
- declare module "*.com.ts" {
10
- global {
11
- const com: HTMLElement;
12
- }
13
- }
1
+ declare const com: HTMLElement;