@lark-apaas/openclaw-dev-cli 0.1.3 → 0.1.5

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.
Files changed (3) hide show
  1. package/README.md +86 -0
  2. package/dist/index.js +56 -37
  3. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # @lark-apaas/openclaw-dev-cli
2
+
3
+ OpenClaw 应用开发 CLI,管理应用的创建、关联和部署。
4
+
5
+ ## 安装
6
+
7
+ 无需安装,通过 npx 直接使用:
8
+
9
+ ```bash
10
+ npx --yes @lark-apaas/openclaw-dev-cli <command> [options]
11
+ ```
12
+
13
+ ## 命令
14
+
15
+ ### init — 初始化应用
16
+
17
+ ```bash
18
+ # 从模板创建新应用
19
+ npx --yes @lark-apaas/openclaw-dev-cli init --template <html|nextjs-static|nextjs> --dir <path>
20
+
21
+ # clone 后初始化
22
+ npx --yes @lark-apaas/openclaw-dev-cli init --dir <path>
23
+ ```
24
+
25
+ | 选项 | 说明 | 默认值 |
26
+ |------|------|--------|
27
+ | `--dir <path>` | 项目目录 | `.` |
28
+ | `--template <template>` | 模板类型(无代码时必须) | - |
29
+ | `--title <title>` | 应用名称 | 目录名 |
30
+ | `--description <desc>` | 应用描述 | `""` |
31
+ | `--template-version <version>` | 模板包版本 | `latest` |
32
+ | `--skip-install` | 跳过依赖安装 | `false` |
33
+
34
+ ### link — 关联已有项目
35
+
36
+ ```bash
37
+ npx --yes @lark-apaas/openclaw-dev-cli link --app-id <id> --template <type>
38
+ ```
39
+
40
+ | 选项 | 说明 | 默认值 |
41
+ |------|------|--------|
42
+ | `--dir <path>` | 项目目录 | `.` |
43
+ | `--app-id <id>` | 要关联的应用 ID | 不传则自动注册 |
44
+ | `--template <template>` | 技术栈类型 | 从 package.json mclaw 字段读取 |
45
+ | `--title <title>` | 应用名称 | 目录名 |
46
+ | `--description <desc>` | 应用描述 | `""` |
47
+
48
+ ### deploy — 部署应用
49
+
50
+ ```bash
51
+ npx --yes @lark-apaas/openclaw-dev-cli deploy
52
+ ```
53
+
54
+ | 选项 | 说明 | 默认值 |
55
+ |------|------|--------|
56
+ | `--dir <path>` | 项目目录 | `.` |
57
+ | `--skip-build` | 跳过构建 | `false` |
58
+
59
+ ## 全局选项
60
+
61
+ | 选项 | 说明 |
62
+ |------|------|
63
+ | `--canary <env>` | 设置 canary 泳道 |
64
+ | `-V, --version` | 输出版本号 |
65
+
66
+ ## 支持的技术栈
67
+
68
+ | 模板 | 说明 |
69
+ |------|------|
70
+ | `html` | 纯 HTML + Tailwind CDN |
71
+ | `nextjs-static` | Next.js Pages Router,静态导出 |
72
+ | `nextjs` | Next.js App Router 全栈 |
73
+
74
+ ## 环境配置
75
+
76
+ 在项目目录下创建 `.env` 文件:
77
+
78
+ ```
79
+ FORCE_AUTHN_INNERAPI_DOMAIN=<API域名>
80
+ FORCE_AUTHN_ACCESS_KEY=<AK>
81
+ FORCE_AUTHN_ACCESS_SECRET=<SK>
82
+ ```
83
+
84
+ ## License
85
+
86
+ MIT
package/dist/index.js CHANGED
@@ -7288,7 +7288,7 @@ var initCommand = {
7288
7288
  const hasPackageJson = import_node_fs9.default.existsSync(import_node_path12.default.join(projectDir, "package.json"));
7289
7289
  const existingMeta = readSparkMeta(projectDir);
7290
7290
  const title = options.title ?? import_node_path12.default.basename(projectDir);
7291
- let stackVersion = existingMeta.stack_version;
7291
+ let templateVersion = existingMeta.templateVersion;
7292
7292
  if (!hasPackageJson) {
7293
7293
  if (!options.template) {
7294
7294
  throw new Error(
@@ -7306,26 +7306,26 @@ Available: ${TEMPLATE_TYPES.join(", ")}`
7306
7306
  projectName: import_node_path12.default.basename(projectDir),
7307
7307
  localTemplate: options.localTemplate
7308
7308
  });
7309
- stackVersion = version;
7309
+ templateVersion = version;
7310
7310
  }
7311
- let stack = options.template ?? existingMeta.stack;
7312
- if (!stack) {
7311
+ let template = options.template ?? existingMeta.template;
7312
+ if (!template) {
7313
7313
  const pkgPath = import_node_path12.default.join(projectDir, "package.json");
7314
7314
  if (import_node_fs9.default.existsSync(pkgPath)) {
7315
7315
  try {
7316
7316
  const pkg = JSON.parse(import_node_fs9.default.readFileSync(pkgPath, "utf-8"));
7317
- stack = pkg.mclaw?.stack;
7318
- stackVersion = stackVersion ?? pkg.mclaw?.stackVersion;
7317
+ template = pkg.mclaw?.stack;
7318
+ templateVersion = templateVersion ?? pkg.mclaw?.stackVersion;
7319
7319
  } catch {
7320
7320
  }
7321
7321
  }
7322
7322
  }
7323
- if (!stack) {
7323
+ if (!template) {
7324
7324
  throw new Error(
7325
- "Cannot determine stack type. Please provide --template or ensure package.json has mclaw.stack field."
7325
+ "Cannot determine template type. Please provide --template or ensure package.json has mclaw.stack field."
7326
7326
  );
7327
7327
  }
7328
- let appId = options.appId ?? existingMeta.app_id;
7328
+ let appId = options.appId ?? existingMeta.appId;
7329
7329
  if (!appId) {
7330
7330
  const result = await createSubApp({
7331
7331
  name: title,
@@ -7337,9 +7337,9 @@ Available: ${TEMPLATE_TYPES.join(", ")}`
7337
7337
  console.log(`Using existing app_id: ${appId}`);
7338
7338
  }
7339
7339
  writeSparkMeta(projectDir, {
7340
- app_id: appId,
7341
- stack,
7342
- stack_version: stackVersion ?? "0.1.0"
7340
+ appId,
7341
+ template,
7342
+ templateVersion: templateVersion ?? "0.1.0"
7343
7343
  });
7344
7344
  if (!options.skipInstall) {
7345
7345
  console.log("\nInstalling dependencies...");
@@ -7352,7 +7352,7 @@ Available: ${TEMPLATE_TYPES.join(", ")}`
7352
7352
  \u2705 Initialized successfully!`);
7353
7353
  console.log(` Directory: ${projectDir}`);
7354
7354
  console.log(` App ID: ${appId}`);
7355
- console.log(` Stack: ${stack}`);
7355
+ console.log(` Template: ${template}`);
7356
7356
  });
7357
7357
  }
7358
7358
  };
@@ -7399,9 +7399,9 @@ Available: ${TEMPLATE_TYPES.join(", ")}`
7399
7399
  console.log(`Using app_id: ${appId}`);
7400
7400
  }
7401
7401
  writeSparkMeta(projectDir, {
7402
- app_id: appId,
7403
- stack,
7404
- stack_version: stackVersion
7402
+ appId,
7403
+ template: stack,
7404
+ templateVersion: stackVersion
7405
7405
  });
7406
7406
  if (import_node_fs10.default.existsSync(pkgPath)) {
7407
7407
  const pkg = JSON.parse(import_node_fs10.default.readFileSync(pkgPath, "utf-8"));
@@ -7483,8 +7483,14 @@ function configureTosutil(tosutilPath, confPath, credential) {
7483
7483
  ], { stdio: "pipe" });
7484
7484
  }
7485
7485
  function uploadToTos(tosutilPath, confPath, sourceDir, destUrl) {
7486
- console.error(`${LOG_PREFIX} Uploading ${sourceDir} \u2192 ${destUrl}`);
7487
- (0, import_node_child_process3.execFileSync)(tosutilPath, [
7486
+ console.log(`${LOG_PREFIX} Uploading ${sourceDir} \u2192 ${destUrl}`);
7487
+ const files = import_node_fs12.default.readdirSync(sourceDir);
7488
+ if (files.length === 0) {
7489
+ console.warn(`${LOG_PREFIX} Warning: source directory is empty, skipping upload.`);
7490
+ return;
7491
+ }
7492
+ console.log(`${LOG_PREFIX} Source files: ${files.length}`);
7493
+ const output = (0, import_node_child_process3.execFileSync)(tosutilPath, [
7488
7494
  "cp",
7489
7495
  "-conf",
7490
7496
  confPath,
@@ -7499,7 +7505,19 @@ function uploadToTos(tosutilPath, confPath, sourceDir, destUrl) {
7499
7505
  "-ps",
7500
7506
  "10485760",
7501
7507
  "-f"
7502
- ], { stdio: "inherit" });
7508
+ ], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
7509
+ console.log(output);
7510
+ const succeedMatch = output.match(/Succeed count is:\s*(\d+)/);
7511
+ const failedMatch = output.match(/Failed count is:\s*(\d+)/);
7512
+ const succeedCount = succeedMatch ? parseInt(succeedMatch[1], 10) : 0;
7513
+ const failedCount = failedMatch ? parseInt(failedMatch[1], 10) : 0;
7514
+ if (failedCount > 0) {
7515
+ throw new Error(`${LOG_PREFIX} Upload failed: ${failedCount} files failed, ${succeedCount} succeeded.`);
7516
+ }
7517
+ if (succeedCount === 0) {
7518
+ throw new Error(`${LOG_PREFIX} Upload failed: no files were uploaded. Check tosutil credentials and bucket permissions.`);
7519
+ }
7520
+ console.log(`${LOG_PREFIX} Uploaded ${succeedCount} files successfully.`);
7503
7521
  }
7504
7522
  function uploadWithCredential(tosutilPath, sourceDir, destUrl, credential, label) {
7505
7523
  const confPath = import_node_path15.default.join(import_node_os2.default.tmpdir(), `.tosutilconfig-mclaw-${label}-${process.pid}`);
@@ -7532,7 +7550,8 @@ function uploadOutput(options) {
7532
7550
  }
7533
7551
  if (validated.hasOutputStatic) {
7534
7552
  const localPath = import_node_path15.default.join(distDir, OUTPUT_STATIC_DIR);
7535
- const destUrl = `${preUploadResult.uploadPrefix}${OUTPUT_STATIC_DIR}/`;
7553
+ const prefix = preUploadResult.uploadPrefix.endsWith("/") ? preUploadResult.uploadPrefix : `${preUploadResult.uploadPrefix}/`;
7554
+ const destUrl = `${prefix}${OUTPUT_STATIC_DIR}/`;
7536
7555
  console.error(`${LOG_PREFIX} Uploading output_static (static credential)...`);
7537
7556
  uploadWithCredential(tosutilPath, localPath, destUrl, {
7538
7557
  accessKeyID: preUploadResult.uploadCredential.AccessKeyID,
@@ -7555,30 +7574,30 @@ var deployCommand = {
7555
7574
  throw new Error('.spark/meta.json not found. Run "mclaw-dev init" first.');
7556
7575
  }
7557
7576
  const meta = JSON.parse(import_node_fs13.default.readFileSync(metaPath, "utf-8"));
7558
- if (!meta.app_id || !meta.stack) {
7577
+ if (!meta.appId || !meta.template) {
7559
7578
  throw new Error('.spark/meta.json is incomplete. Run "mclaw-dev init" to fix.');
7560
7579
  }
7561
- const publishResult = await createPublish(meta.app_id);
7580
+ const publishResult = await createPublish(meta.appId);
7562
7581
  console.log(`Version: ${publishResult.version}, PublishID: ${publishResult.publishID}`);
7563
7582
  console.log("\nPreparing upload credentials...");
7564
- const artifactCredential = await genArtifactUploadCredential(meta.app_id, String(publishResult.version));
7565
- const bucketId = await getDefaultBucketId(meta.app_id);
7566
- const preUploadResult = await preUploadStatic(meta.app_id, bucketId);
7583
+ const artifactCredential = await genArtifactUploadCredential(meta.appId, String(publishResult.version));
7584
+ const bucketId = await getDefaultBucketId(meta.appId);
7585
+ const preUploadResult = await preUploadStatic(meta.appId, bucketId);
7567
7586
  console.log(`Static prefix: ${preUploadResult.downloadURLPrefix}`);
7568
7587
  if (!options.skipBuild) {
7569
- const cdnDomain = buildCdnDomain(meta.app_id, publishResult.version);
7588
+ const cdnDomain = buildCdnDomain(meta.appId, publishResult.version);
7570
7589
  const buildEnv = {
7571
7590
  ...process.env,
7572
- MCLAW_APP_ID: meta.app_id,
7591
+ MCLAW_APP_ID: meta.appId,
7573
7592
  MCLAW_VERSION: String(publishResult.version),
7574
- MCLAW_STACK: meta.stack,
7593
+ MCLAW_STACK: meta.template,
7575
7594
  MCLAW_CDN_DOMAIN: cdnDomain,
7576
7595
  MCLAW_STATIC_PREFIX: preUploadResult.downloadURLPrefix
7577
7596
  };
7578
7597
  console.log("\nBuilding...");
7579
- console.log(` MCLAW_APP_ID=${meta.app_id}`);
7598
+ console.log(` MCLAW_APP_ID=${meta.appId}`);
7580
7599
  console.log(` MCLAW_VERSION=${publishResult.version}`);
7581
- console.log(` MCLAW_STACK=${meta.stack}`);
7600
+ console.log(` MCLAW_STACK=${meta.template}`);
7582
7601
  console.log(` MCLAW_CDN_DOMAIN=${cdnDomain}`);
7583
7602
  console.log(` MCLAW_STATIC_PREFIX=${preUploadResult.downloadURLPrefix}`);
7584
7603
  (0, import_node_child_process4.execSync)("npm run build", {
@@ -7591,7 +7610,7 @@ var deployCommand = {
7591
7610
  console.log("Build output validated.");
7592
7611
  uploadOutput({
7593
7612
  projectDir,
7594
- appId: meta.app_id,
7613
+ appId: meta.appId,
7595
7614
  version: publishResult.version,
7596
7615
  validated,
7597
7616
  artifactCredential,
@@ -7599,7 +7618,7 @@ var deployCommand = {
7599
7618
  });
7600
7619
  if (validated.hasOutputStatic) {
7601
7620
  console.log("\nNotifying upload complete...");
7602
- const callbackResult = await callbackStatic(meta.app_id, bucketId, preUploadResult.uploadID);
7621
+ const callbackResult = await callbackStatic(meta.appId, bucketId, preUploadResult.uploadID);
7603
7622
  console.log(`Uploaded ${callbackResult.attachments.length} static files.`);
7604
7623
  }
7605
7624
  let routesConfig;
@@ -7608,18 +7627,18 @@ var deployCommand = {
7608
7627
  routesConfig = import_node_fs13.default.readFileSync(routesPath, "utf-8");
7609
7628
  console.log("Found routes.json, including in publish.");
7610
7629
  }
7611
- const publishUpdateResult = await updatePublish(meta.app_id, {
7630
+ const publishUpdateResult = await updatePublish(meta.appId, {
7612
7631
  publishID: publishResult.publishID,
7613
7632
  routesConfig
7614
7633
  });
7615
- const appUrl = publishUpdateResult.onlineURL || buildAppUrl(meta.app_id);
7634
+ const appUrl = publishUpdateResult.onlineURL || buildAppUrl(meta.appId);
7616
7635
  writeSparkMeta(projectDir, {
7617
7636
  ...meta,
7618
- app_url: appUrl
7637
+ appUrl
7619
7638
  });
7620
7639
  console.log(`
7621
7640
  \u2705 Deployed successfully!`);
7622
- console.log(` App ID: ${meta.app_id}`);
7641
+ console.log(` App ID: ${meta.appId}`);
7623
7642
  console.log(` Version: ${publishResult.version}`);
7624
7643
  console.log(` URL: ${appUrl}`);
7625
7644
  });
@@ -7653,7 +7672,7 @@ function loadEnvFile(filePath) {
7653
7672
  }
7654
7673
  }
7655
7674
  loadEnvFile(import_node_path17.default.join(process.cwd(), ".env"));
7656
- var VERSION = "0.1.0";
7675
+ var VERSION = "0.1.5";
7657
7676
  var cli = new OpenClawCLI(VERSION);
7658
7677
  cli.useAll(commands);
7659
7678
  cli.run();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/openclaw-dev-cli",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "CLI tool for OpenClaw development",
5
5
  "main": "dist/index.js",
6
6
  "bin": {