transone-cli 0.3.0 → 0.4.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/README.md CHANGED
@@ -1,35 +1,148 @@
1
1
  # transone-cli
2
2
 
3
- TransOne 多端编译器:Bun 原生 CLI,按 Target 将一份 TypeScript 源码静态转换为多端原生工程。
3
+ **English** · [简体中文](./README.zh-CN.md)
4
4
 
5
- ## 目标端抽象(Target)
5
+ Bun-native, multi-target compiler CLI for TransOne applications. It statically converts **one TypeScript source** into Web and multi-platform mini-program native projects at compile time, per target.
6
+
7
+ The CLI is the compiler half of the TransOne framework — the runtime model is in [`transone`](../transone), and the component library is in [`transone-ui`](../transone-ui).
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ bun add -g transone-cli
13
+ # or npm i -g transone-cli
14
+ ```
15
+
16
+ Requires Bun >= 1.3.0.
17
+
18
+ ## Usage
6
19
 
7
20
  ```text
8
- web 直接渲染(HTML + 浏览器运行时,M1 已实现)
9
- mp-weixin WXML / WXSS / JS 静态转换(M2 规划中)
10
- mp-alipay AXML / ACSS 静态转换(M3 规划中)
11
- mp-bytedance ttml / ttss 静态转换(M3 规划中)
12
- app-* 远期占位(app-ios / app-android / app-harmony)
21
+ Usage:
22
+ transone create
23
+ transone dev [--host <host>] [--port <port>] [--base <path>] [--no-watch]
24
+ transone build [--target <target>] [--out-dir <path>] [--base <path>] [--library]
25
+
26
+ Targets: web, mp-weixin, mp-alipay, mp-bytedance, mp-xiaohongshu, app-ios, app-android, app-harmony (default: web)
27
+ ```
28
+
29
+ ### `transone create`
30
+
31
+ Scaffolds a new TransOne project in the current directory (refuses to overwrite existing project files).
32
+
33
+ ### `transone dev`
34
+
35
+ Starts the development server (Web target only) with optional watch mode (`--no-watch` to disable), custom `--host` / `--port`, and a `--base` path.
36
+
37
+ ### `transone build`
38
+
39
+ Builds the app for a target:
40
+
41
+ ```bash
42
+ transone build --target web # H5 site / SPA
43
+ transone build --target mp-weixin # WeChat mini-program project (WXML/WXSS/JS)
44
+ transone build --target mp-alipay # Alipay mini-program project (AXML/ACSS)
45
+ transone build --target mp-bytedance # ByteDance mini-program project (TTML/TTSS)
46
+ transone build --target mp-xiaohongshu # Xiaohongshu mini-program project (XHSML/CSS)
47
+ ```
48
+
49
+ - `--out-dir` overrides the output directory.
50
+ - `--base` sets the deployment base path (e.g. a GitHub Pages sub-path).
51
+ - `--library` builds in library mode (no page entry required).
52
+
53
+ The iOS, Android, and Harmony native app targets are implemented. A generated project should still be opened in its platform IDE for runtime/device validation.
54
+
55
+ ## Targets
56
+
57
+ | Target | Output | Mechanism | Status |
58
+ | --- | --- | --- | --- |
59
+ | `web` | H5 site / SPA | Direct rendering (HTML + browser runtime) | Implemented |
60
+ | `mp-weixin` | Native WeChat mini-program project | Compile-time static conversion (WXML / WXSS / JS) | Implemented |
61
+ | `mp-alipay` | Native Alipay mini-program project | Compile-time static conversion (AXML / ACSS) | Implemented |
62
+ | `mp-bytedance` | Native ByteDance mini-program project | Compile-time static conversion (TTML / TTSS) | Implemented |
63
+ | `mp-xiaohongshu` | Native Xiaohongshu Mini Program (not Mini Widget) | Compile-time static conversion (XHSML / CSS) | Implemented |
64
+ | `app-ios` / `app-android` / `app-harmony` | Native app (SwiftUI / Jetpack Compose / ArkUI) | Compile-time source generation | Implemented |
65
+
66
+ Mini-program builds emit a complete native project: `app.json` / `app.js` / app style file / project config, plus `pages/<route>/<name>.*` and `components/<tag>/<tag>.*`. Platform differences (template syntax, style language, event binding, lifecycle mapping) are handled by the `MpDialect` abstraction.
67
+
68
+ ## Configuration
69
+
70
+ Create a `transone.config.ts` in the project root and export the config with `defineConfig`:
71
+
72
+ ```ts
73
+ import { defineConfig } from 'transone-cli';
74
+
75
+ export default defineConfig({
76
+ entry: 'src/main.ts', // default
77
+ server: {
78
+ host: '127.0.0.1', // default
79
+ port: 52211, // default
80
+ proxy: {
81
+ '/api': { target: 'http://localhost:8080', changeOrigin: true },
82
+ },
83
+ },
84
+ build: {
85
+ outDir: 'dist/build/h5', // default
86
+ basePath: '',
87
+ directoryPages: false,
88
+ },
89
+ mp: {
90
+ appId: 'touristappid', // WeChat dev-tool test id by default
91
+ navigationBarTitleText: 'TransOne',
92
+ lengthUnit: 'px', // or 'rpx' (values converted at 1px = 2rpx)
93
+ // pages, window, tabBar, appExtra, pageExtra, globalData, publicDir ...
94
+ },
95
+ });
13
96
  ```
14
97
 
15
- 新增目标端:实现 `BuildTarget` 接口并注册到 `TargetRegistry`,无需改动构建入口。
98
+ The `mp` field accepts either a single `MiniProgramConfig` (applies to every mini-program target) or a per-platform map like `{ 'mp-weixin': {...}, 'mp-alipay': {...}, 'mp-xiaohongshu': {...} }` — only the config for the current target is used. Xiaohongshu uses the default placeholder app ID unless you set its own `appId`.
16
99
 
17
- ## 使用
100
+ Generate the Counter playground project for Xiaohongshu with:
18
101
 
19
102
  ```bash
20
- transone build --target web # 产出 H5 站点
21
- transone build --target mp-weixin # 未实现时编译期报错并给出路线图阶段
22
- transone dev # 开发服务(仅 web)
23
- transone create # 脚手架
103
+ bun run --cwd playground/counter build:xiaohongshu
24
104
  ```
25
105
 
106
+ The output is `playground/counter/dist/build/mp-xiaohongshu`.
107
+
108
+ ## How the compiler works
109
+
110
+ 1. Loads the project config and resolves pages from the entry file.
111
+ 2. For Web: renders directly with the browser runtime (H5 site / SPA).
112
+ 3. For mini-program targets: statically analyzes the root component class of each page, then compiles the component tree into native files — WXML/WXSS (WeChat), AXML/ACSS (Alipay), TTML/TTSS (ByteDance), and XHSML/CSS (Xiaohongshu) — including styles, template bindings, event methods, and data-state mapping. The generated code is a standalone native project with no TransOne runtime.
113
+ 4. Library components are resolved through the `"source"` field of each package's `package.json` (see `transone-ui`).
114
+
115
+ ## Extending a new target
116
+
117
+ Implement the `BuildTarget` interface and register it with `TargetRegistry` — no changes to the build entry point are needed:
118
+
119
+ ```ts
120
+ import type { BuildTarget, TargetType, ResolvedConfig, BuildOptions, BuildResult } from 'transone-cli';
121
+
122
+ export class MyTarget implements BuildTarget {
123
+ readonly type: TargetType = 'my-target';
124
+ readonly label = 'My target platform';
125
+ async build(config: ResolvedConfig, options: BuildOptions): Promise<BuildResult> {
126
+ // generate the native project for your platform
127
+ }
128
+ }
129
+ ```
130
+
131
+ ## Development
132
+
26
133
  ```bash
27
- bun test # 测试
28
- bun run build # 构建 dist(CLI bundle + .d.ts)
134
+ bun test # run tests
135
+ bun run build # build dist (CLI bundle + .d.ts)
136
+ bun run build:types
137
+ bun run lint
29
138
  ```
30
139
 
31
- ## 文档
140
+ ## Documentation
141
+
142
+ - Online docs (CLI site): <https://geektech-team.github.io/transone/cli/>
143
+ - Main docs site: <https://geektech-team.github.io/transone/>
144
+ - Repository: <https://github.com/geektech-team/transone>
145
+
146
+ ## License
32
147
 
33
- - 在线文档(CLI 子站):<https://geektech-team.github.io/transone/cli/>
34
- - 主文档站:<https://geektech-team.github.io/transone/>
35
- - 仓库:<https://github.com/geektech-team/transone>
148
+ MIT
@@ -0,0 +1,50 @@
1
+ # transone-cli
2
+
3
+ **简体中文** · [English](./README.md)
4
+
5
+ TransOne 多端编译器:Bun 原生 CLI,按 Target 将一份 TypeScript 源码静态转换为多端原生工程。
6
+
7
+ ## 目标端抽象(Target)
8
+
9
+ ```text
10
+ web 直接渲染(HTML + 浏览器运行时,M1 已实现)
11
+ mp-weixin WXML / WXSS / JS 静态转换(已实现)
12
+ mp-alipay AXML / ACSS 静态转换(已实现)
13
+ mp-bytedance TTML / TTSS 静态转换(已实现)
14
+ mp-xiaohongshu XHSML / CSS 静态转换(已实现;小红书小程序,非小组件)
15
+ app-* 原生应用代码生成(app-ios / app-android / app-harmony,已实现)
16
+ ```
17
+
18
+ 新增目标端:实现 `BuildTarget` 接口并注册到 `TargetRegistry`,无需改动构建入口。
19
+
20
+ ## 使用
21
+
22
+ ```bash
23
+ transone build --target web # 产出 H5 站点
24
+ transone build --target mp-weixin # 生成微信小程序原生工程
25
+ transone build --target mp-xiaohongshu # 生成小红书小程序原生工程(XHSML / CSS)
26
+ transone dev # 开发服务(仅 web)
27
+ transone create # 脚手架
28
+ ```
29
+
30
+ ```bash
31
+ bun test # 测试
32
+ bun run build # 构建 dist(CLI bundle + .d.ts)
33
+ ```
34
+
35
+ 在 Counter 演练项目中生成微信、支付宝、字节和小红书小程序:
36
+
37
+ ```bash
38
+ bun run --cwd playground/counter build:weixin
39
+ bun run --cwd playground/counter build:alipay
40
+ bun run --cwd playground/counter build:bytedance
41
+ bun run --cwd playground/counter build:xiaohongshu
42
+ ```
43
+
44
+ 小红书产物位于 `playground/counter/dist/build/mp-xiaohongshu`。`mp` 配置既支持适用于所有小程序端的扁平配置,也支持按 target 分组;小红书未配置 `appId` 时使用占位默认值,导入开发者工具前应设置真实 App ID。
45
+
46
+ ## 文档
47
+
48
+ - 在线文档(CLI 子站):<https://geektech-team.github.io/transone/cli/>
49
+ - 主文档站:<https://geektech-team.github.io/transone/>
50
+ - 仓库:<https://github.com/geektech-team/transone>
@@ -0,0 +1,2 @@
1
+ import type { NativeScreen } from './types';
2
+ export declare function analyzeNativeScreen(entry: string): Promise<NativeScreen>;
@@ -0,0 +1,3 @@
1
+ import type { BuildResult, ResolvedConfig } from '../types';
2
+ import type { NativeDialect } from './types';
3
+ export declare function buildNativeApp(config: ResolvedConfig, dialect: NativeDialect): Promise<BuildResult>;
@@ -0,0 +1,4 @@
1
+ import type { NativeDialect } from './types';
2
+ export declare const IOS_DIALECT: NativeDialect;
3
+ export declare const ANDROID_DIALECT: NativeDialect;
4
+ export declare const HARMONY_DIALECT: NativeDialect;
@@ -0,0 +1 @@
1
+ export declare function nativeError(filePath: string, message: string): Error;
@@ -0,0 +1,61 @@
1
+ import type { ResolvedAppConfig } from '../types';
2
+ export type NativeStateValue = string | number | boolean;
3
+ export interface NativeStateEntry {
4
+ key: string;
5
+ value: NativeStateValue;
6
+ }
7
+ export interface NativeStyle {
8
+ color?: string;
9
+ backgroundColor?: string;
10
+ fontSize?: number;
11
+ fontWeight?: string | number;
12
+ padding?: number;
13
+ margin?: number;
14
+ width?: number;
15
+ height?: number;
16
+ borderRadius?: number;
17
+ textAlign?: string;
18
+ }
19
+ export type NativeTextPart = {
20
+ kind: 'literal';
21
+ value: string;
22
+ } | {
23
+ kind: 'state';
24
+ key: string;
25
+ };
26
+ export type NativeAction = {
27
+ kind: 'increment';
28
+ key: string;
29
+ by: number;
30
+ } | {
31
+ kind: 'set-literal';
32
+ key: string;
33
+ value: NativeStateValue;
34
+ };
35
+ export type NativeNode = {
36
+ kind: 'container';
37
+ children: NativeNode[];
38
+ style?: NativeStyle;
39
+ } | {
40
+ kind: 'text';
41
+ parts: NativeTextPart[];
42
+ style?: NativeStyle;
43
+ } | {
44
+ kind: 'button';
45
+ parts: NativeTextPart[];
46
+ action: NativeAction;
47
+ style?: NativeStyle;
48
+ };
49
+ export interface NativeScreen {
50
+ name: string;
51
+ state: NativeStateEntry[];
52
+ root: Extract<NativeNode, {
53
+ kind: 'container';
54
+ }>;
55
+ }
56
+ export interface NativeDialect {
57
+ readonly id: 'app-ios' | 'app-android' | 'app-harmony';
58
+ readonly label: string;
59
+ readonly resourceDirectory: string;
60
+ generateProject(screen: NativeScreen, config: ResolvedAppConfig): Record<string, string>;
61
+ }
@@ -1,23 +1,14 @@
1
1
  // @bun
2
2
  import {
3
- __require
4
- } from "./index-yb2wsc7f.js";
3
+ loadTypescript
4
+ } from "./index-k1qfvp0y.js";
5
+ import"./index-yb2wsc7f.js";
5
6
 
6
7
  // src/mp/build-mp.ts
7
8
  import { cp, mkdir, readdir, rm, writeFile } from "fs/promises";
8
9
  import { existsSync as existsSync2 } from "fs";
9
10
  import { basename, dirname as dirname3, join as join3, relative, resolve as resolve2 } from "path";
10
11
 
11
- // src/mp/ts-loader.ts
12
- var tsModule = null;
13
- async function loadTypescript() {
14
- if (tsModule) {
15
- return tsModule;
16
- }
17
- tsModule = await import("typescript");
18
- return tsModule;
19
- }
20
-
21
12
  // src/mp/analyze.ts
22
13
  import { existsSync, readFileSync } from "fs";
23
14
  import { dirname, join, resolve } from "path";
@@ -1452,6 +1443,9 @@ function compileSlot(context, classSource, node, env) {
1452
1443
  return [indent(env.indent) + "<slot/>"];
1453
1444
  }
1454
1445
  const name = compileLiteralString(context, classSource, nameExpr, "slot \u540D\u79F0");
1446
+ if (name === "default") {
1447
+ return [indent(env.indent) + "<slot/>"];
1448
+ }
1455
1449
  return [indent(env.indent) + `<slot name="${name}"/>`];
1456
1450
  }
1457
1451
  function compileListener(context, classSource, eventName, handlerExpr, env) {
@@ -2119,6 +2113,7 @@ function collectModuleConsts3(context, classSource) {
2119
2113
  // src/mp/methods.ts
2120
2114
  var PAGE_LIFECYCLE = {
2121
2115
  beforeMount: "onLoad",
2116
+ onLoad: "onLoad",
2122
2117
  onMounted: "onReady",
2123
2118
  onUnmounted: "onUnload",
2124
2119
  onShow: "onShow",
@@ -2149,6 +2144,9 @@ function compileMethods(context, classSource, usedNames, kind, customEvents) {
2149
2144
  seed.add(hook);
2150
2145
  }
2151
2146
  }
2147
+ if (methods.has("onPropsChange")) {
2148
+ seed.add("onPropsChange");
2149
+ }
2152
2150
  const queue = [...seed];
2153
2151
  const visited = new Set;
2154
2152
  const entries = [];
@@ -2621,6 +2619,13 @@ function generateComponentJs(unit, dialect) {
2621
2619
  }
2622
2620
  parts.push(" },");
2623
2621
  }
2622
+ const hasPropsHook = unit.methods.some((entry) => entry.key === "onPropsChange");
2623
+ if (hasPropsHook) {
2624
+ const watched = Object.keys(unit.properties);
2625
+ parts.push(" observers: {");
2626
+ parts.push(` ${JSON.stringify(watched.join(", "))}: function () { if (typeof this.onPropsChange === 'function') this.onPropsChange(); },`);
2627
+ parts.push(" },");
2628
+ }
2624
2629
  parts.push("});");
2625
2630
  return parts.join(`
2626
2631
  `) + `
@@ -2791,5 +2796,5 @@ export {
2791
2796
  buildMiniProgram
2792
2797
  };
2793
2798
 
2794
- //# debugId=1B46276CC3CBABAA64756E2164756E21
2795
- //# sourceMappingURL=build-mp-kcnx989m.js.map
2799
+ //# debugId=B563DD7B11FB4E5E64756E2164756E21
2800
+ //# sourceMappingURL=build-mp-6j38wf4r.js.map