@chidchanun/bcp 0.1.20 → 0.1.22

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.
@@ -0,0 +1,77 @@
1
+ # BCP Framework 0.1.22
2
+
3
+ BCP 0.1.22 adds the first dedicated Developer Tools milestone.
4
+
5
+ ## Highlights
6
+
7
+ - Added `bcp doctor` for project/runtime health diagnostics.
8
+ - Added `bcp inspect` for environment, resolved config, dependency and route inspection.
9
+ - Added `--json` output for both developer-tool commands.
10
+ - `bcp doctor` returns a non-zero exit code when blocking checks fail, so it can be used as a CI health gate.
11
+ - Added React / React DOM version and package-location checks to detect duplicate React installations before they surface as `Invalid hook call` runtime failures.
12
+ - Added route conflict and client-boundary validation without starting the dev server.
13
+ - Added development environment diagnostics without printing private environment values.
14
+ - Added unit coverage for CLI parsing, version checks, missing-project diagnostics and deterministic inspection output.
15
+
16
+ ## `bcp doctor`
17
+
18
+ ```bash
19
+ bcp doctor
20
+ ```
21
+
22
+ The health report checks:
23
+
24
+ - Node.js support,
25
+ - `package.json`, `app/` and optional `public/`,
26
+ - declared and installed BCP dependencies,
27
+ - React and React DOM versions,
28
+ - whether BCP and the application resolve the same React/React DOM package roots,
29
+ - development environment loading,
30
+ - resolved framework config,
31
+ - page/API route discovery,
32
+ - client/server module boundaries.
33
+
34
+ Use JSON output in automation:
35
+
36
+ ```bash
37
+ bcp doctor --json
38
+ ```
39
+
40
+ ## `bcp inspect`
41
+
42
+ ```bash
43
+ bcp inspect
44
+ ```
45
+
46
+ The inspection report includes:
47
+
48
+ - framework/runtime identity,
49
+ - loaded development env filenames,
50
+ - public environment variable names,
51
+ - resolved BCP configuration,
52
+ - installed BCP/React/React DOM versions,
53
+ - page and API route mappings.
54
+
55
+ Machine-readable output:
56
+
57
+ ```bash
58
+ bcp inspect --json
59
+ ```
60
+
61
+ ## Duplicate React diagnostics
62
+
63
+ The Developer Tools milestone includes a check motivated by the 0.1.21 local release verification workflow.
64
+
65
+ If an application is linked directly to a framework staging directory, the application may resolve React from its own `node_modules` while the BCP SSR renderer resolves React DOM from the framework checkout. `bcp doctor` detects this package-root split and reports it as a failure before SSR reaches the `Invalid hook call` error.
66
+
67
+ For local release verification, continue using packed `.tgz` artifacts rather than installing `.package/bcp` as a linked directory.
68
+
69
+ ## Compatibility
70
+
71
+ 0.1.22 does not change public rendering, routing, database, authentication, validation, middleware or error-handling APIs.
72
+
73
+ The new functionality is additive CLI tooling. Existing BCP applications can continue using the current commands unchanged.
74
+
75
+ ## Next milestone
76
+
77
+ The next planned milestone is BCP 0.1.23 — Logging & Observability.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chidchanun/bcp",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "BCP Framework - a React full-stack framework with file-based routing, SSR, APIs, middleware, islands, caching and standalone production builds.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -881,6 +881,9 @@ export class DevClientBundler {
881
881
  jsx:
882
882
  "automatic",
883
883
 
884
+ jsxDev:
885
+ true,
886
+
884
887
  define:
885
888
  createClientEnvironmentDefines(
886
889
  "development"
@@ -1010,7 +1013,7 @@ export class DevClientBundler {
1010
1013
  * เปลี่ยนเป็น
1011
1014
  *
1012
1015
  * Page
1013
- * import A
1016
+ * เดิม import A
1014
1017
  * import B
1015
1018
  *
1016
1019
  * จึง rebuild graph ใหม่
@@ -1737,17 +1740,18 @@ function createReactRefreshPlugin(
1737
1740
  extension === ".ts" ||
1738
1741
  extension === ".tsx";
1739
1742
 
1743
+ const parsesJsx =
1744
+ extension !== ".ts";
1745
+
1740
1746
  const presets:
1741
1747
  any[] = [];
1742
1748
 
1743
1749
  /*
1744
- * Babel 8
1745
- *
1746
- * ไม่ใช้:
1747
- *
1748
- * allowDeclareFields
1749
- * allExtensions
1750
- * isTSX
1750
+ * Babel removes TypeScript syntax and
1751
+ * injects React Refresh registrations.
1752
+ * JSX intentionally remains untransformed
1753
+ * so esbuild owns JSX semantics for both
1754
+ * the normal dev bundle and production.
1751
1755
  */
1752
1756
  if (
1753
1757
  isTypeScript
@@ -1757,17 +1761,6 @@ function createReactRefreshPlugin(
1757
1761
  ]);
1758
1762
  }
1759
1763
 
1760
- presets.push([
1761
- presetReact,
1762
- {
1763
- runtime:
1764
- "automatic",
1765
-
1766
- development:
1767
- true,
1768
- },
1769
- ]);
1770
-
1771
1764
  const result =
1772
1765
  await transformAsync(
1773
1766
  source,
@@ -1784,6 +1777,15 @@ function createReactRefreshPlugin(
1784
1777
  sourceType:
1785
1778
  "module",
1786
1779
 
1780
+ parserOpts:
1781
+ parsesJsx
1782
+ ? {
1783
+ plugins: [
1784
+ "jsx",
1785
+ ],
1786
+ }
1787
+ : undefined,
1788
+
1787
1789
  presets,
1788
1790
 
1789
1791
  plugins: [
@@ -1839,7 +1841,7 @@ ${result.code}
1839
1841
  transformed,
1840
1842
 
1841
1843
  loader:
1842
- "js",
1844
+ "jsx",
1843
1845
 
1844
1846
  resolveDir:
1845
1847
  path.dirname(
@@ -8,6 +8,8 @@ export type CliCommand =
8
8
  | "routes"
9
9
  | "update"
10
10
  | "db"
11
+ | "doctor"
12
+ | "inspect"
11
13
  | "help"
12
14
  | "version";
13
15
 
@@ -33,6 +35,8 @@ export interface CliOptions {
33
35
 
34
36
  updateDryRun?: boolean;
35
37
 
38
+ json?: boolean;
39
+
36
40
  dbAction?: DatabaseCliAction;
37
41
 
38
42
  dbMigrationName?: string;
@@ -61,6 +65,9 @@ export function parseCliArgs(
61
65
  let updateDryRun =
62
66
  false;
63
67
 
68
+ let json =
69
+ false;
70
+
64
71
  let dbAction:
65
72
  DatabaseCliAction | undefined;
66
73
 
@@ -209,6 +216,14 @@ export function parseCliArgs(
209
216
  continue;
210
217
  }
211
218
 
219
+ if (
220
+ argument === "--json"
221
+ ) {
222
+ json =
223
+ true;
224
+ continue;
225
+ }
226
+
212
227
  if (
213
228
  argument.startsWith("-")
214
229
  ) {
@@ -297,6 +312,8 @@ export function parseCliArgs(
297
312
  argument === "routes" ||
298
313
  argument === "update" ||
299
314
  argument === "db" ||
315
+ argument === "doctor" ||
316
+ argument === "inspect" ||
300
317
  argument === "help" ||
301
318
  argument === "version"
302
319
  ) {
@@ -322,6 +339,16 @@ export function parseCliArgs(
322
339
  );
323
340
  }
324
341
 
342
+ if (
343
+ json &&
344
+ command !== "doctor" &&
345
+ command !== "inspect"
346
+ ) {
347
+ throw new Error(
348
+ "Option --json is only valid with `bcp doctor` or `bcp inspect`."
349
+ );
350
+ }
351
+
325
352
  return {
326
353
  command,
327
354
  rootDirectory,
@@ -330,6 +357,11 @@ export function parseCliArgs(
330
357
  updateTarget,
331
358
  updateCheck,
332
359
  updateDryRun,
360
+ ...(json
361
+ ? {
362
+ json: true,
363
+ }
364
+ : {}),
333
365
  ...(command === "db"
334
366
  ? {
335
367
  dbAction,