@lark-apaas/fullstack-cli 1.1.48-alpha.0 → 1.1.48-alpha.1

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 (2) hide show
  1. package/dist/index.js +406 -106
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/index.ts
2
- import fs28 from "fs";
3
- import path24 from "path";
2
+ import fs29 from "fs";
3
+ import path25 from "path";
4
4
  import { fileURLToPath as fileURLToPath5 } from "url";
5
5
  import { config as dotenvConfig } from "dotenv";
6
6
 
@@ -4690,59 +4690,358 @@ var capabilityCommandGroup = {
4690
4690
  commands: [listCommand2]
4691
4691
  };
4692
4692
 
4693
- // src/commands/migration/version-manager.ts
4693
+ // src/commands/component/add.handler.ts
4694
+ import { execFile } from "child_process";
4695
+
4696
+ // src/commands/component/registry-preparer.ts
4694
4697
  import fs16 from "fs";
4695
4698
  import path14 from "path";
4699
+ import os from "os";
4700
+
4701
+ // src/commands/component/service.ts
4702
+ import { mapValues } from "es-toolkit";
4703
+
4704
+ // src/commands/component/utils.ts
4705
+ import createDebug from "debug";
4706
+ var debug = createDebug("component");
4707
+
4708
+ // src/commands/component/service.ts
4709
+ async function getComponents(keys) {
4710
+ const client = getHttpClient();
4711
+ debug("\u8C03\u7528 /components/batch_get %o", keys);
4712
+ const response = await client.post(
4713
+ `/api/v1/studio/innerapi/components/batch_get?keys=${keys.join(",")}`
4714
+ );
4715
+ if (response.status !== 200) {
4716
+ throw new Error(
4717
+ `\u83B7\u53D6\u7EC4\u4EF6\u4FE1\u606F\u5931\u8D25\uFF1A${response.status} ${response.statusText}`
4718
+ );
4719
+ }
4720
+ const result = await response.json();
4721
+ if (result.status_code !== "0") {
4722
+ debug("\u63A5\u53E3\u8FD4\u56DE\u9519\u8BEF\uFF1A%o", result);
4723
+ throw new Error(`\u83B7\u53D6\u7EC4\u4EF6\u4FE1\u606F\u5931\u8D25\uFF1A${result.error_msg}`);
4724
+ }
4725
+ return mapValues(result.data.components, ([component]) => component);
4726
+ }
4727
+ async function getRegistryItem(url) {
4728
+ const client = getHttpClient();
4729
+ debug("\u4E0B\u8F7D registry-item.json\uFF1A%s", url);
4730
+ const response = await client.get(url);
4731
+ if (!response.ok) {
4732
+ throw new Error(
4733
+ `\u4E0B\u8F7D registry-item.json \u5931\u8D25\uFF1A${response.status} ${response.statusText}`
4734
+ );
4735
+ }
4736
+ const item = await response.json();
4737
+ return item;
4738
+ }
4739
+ async function sendInstallEvent(key) {
4740
+ const client = getHttpClient();
4741
+ await client.post("/api/v1/studio/innerapi/resource_events", {
4742
+ events: [
4743
+ {
4744
+ resourceType: "component",
4745
+ resourceKey: key,
4746
+ eventType: "install",
4747
+ details: {}
4748
+ }
4749
+ ]
4750
+ });
4751
+ }
4752
+
4753
+ // src/commands/component/registry-preparer.ts
4754
+ var REGISTRY_TEMP_DIR = path14.join(os.tmpdir(), "miaoda-registry");
4755
+ function parseComponentKey(key) {
4756
+ const match = key.match(/^@([^/]+)\/(.+)$/);
4757
+ if (!match) {
4758
+ throw new Error(
4759
+ `Invalid component key format: ${key}. Expected format: @scope/name`
4760
+ );
4761
+ }
4762
+ return { scope: match[1], name: match[2] };
4763
+ }
4764
+ function getLocalRegistryPath(key) {
4765
+ const { scope, name } = parseComponentKey(key);
4766
+ return path14.join(REGISTRY_TEMP_DIR, scope, `${name}.json`);
4767
+ }
4768
+ function ensureDir(dirPath) {
4769
+ if (!fs16.existsSync(dirPath)) {
4770
+ fs16.mkdirSync(dirPath, { recursive: true });
4771
+ }
4772
+ }
4773
+ async function prepareRecursive(key, visited) {
4774
+ if (visited.has(key)) {
4775
+ debug("\u8DF3\u8FC7\u5DF2\u5904\u7406\u7684\u7EC4\u4EF6: %s", key);
4776
+ return;
4777
+ }
4778
+ visited.add(key);
4779
+ debug("\u5904\u7406\u7EC4\u4EF6: %s", key);
4780
+ debug("\u83B7\u53D6\u7EC4\u4EF6\u4E0B\u8F7D\u4FE1\u606F...");
4781
+ const infoMap = await getComponents([key]);
4782
+ const info = infoMap[key];
4783
+ debug("\u7EC4\u4EF6\u4FE1\u606F: %o", info);
4784
+ if (!info) {
4785
+ throw new Error(`Component not found: ${key}`);
4786
+ }
4787
+ if (info.status !== "active") {
4788
+ throw new Error(`Component is not active: ${key}`);
4789
+ }
4790
+ debug("\u4E0B\u8F7D registry item: %s", info.downloadURL);
4791
+ const registryItem = await getRegistryItem(info.downloadURL);
4792
+ debug("registry item \u5185\u5BB9: %o", registryItem);
4793
+ const deps = registryItem.registryDependencies || [];
4794
+ debug("\u4F9D\u8D56\u5217\u8868: %o", deps);
4795
+ for (const dep of deps) {
4796
+ await prepareRecursive(dep, visited);
4797
+ }
4798
+ const rewrittenItem = {
4799
+ ...registryItem,
4800
+ registryDependencies: deps.map((dep) => getLocalRegistryPath(dep))
4801
+ };
4802
+ const localPath = getLocalRegistryPath(key);
4803
+ ensureDir(path14.dirname(localPath));
4804
+ fs16.writeFileSync(localPath, JSON.stringify(rewrittenItem, null, 2), "utf-8");
4805
+ debug("\u4FDD\u5B58\u5230: %s", localPath);
4806
+ }
4807
+ async function prepareComponentRegistryItems(id) {
4808
+ const visited = /* @__PURE__ */ new Set();
4809
+ await prepareRecursive(id, visited);
4810
+ return getLocalRegistryPath(id);
4811
+ }
4812
+ function cleanupTempDir() {
4813
+ try {
4814
+ if (fs16.existsSync(REGISTRY_TEMP_DIR)) {
4815
+ fs16.rmSync(REGISTRY_TEMP_DIR, { recursive: true, force: true });
4816
+ }
4817
+ } catch {
4818
+ }
4819
+ }
4820
+ function getDownloadedRegistryItem(itemId) {
4821
+ const localPath = getLocalRegistryPath(itemId);
4822
+ if (!fs16.existsSync(localPath)) {
4823
+ return null;
4824
+ }
4825
+ const content = fs16.readFileSync(localPath, "utf-8");
4826
+ return JSON.parse(content);
4827
+ }
4828
+
4829
+ // src/commands/component/shadcn-executor.ts
4830
+ import * as pty from "@lydell/node-pty";
4831
+ function parseOutput(output) {
4832
+ const state = {
4833
+ currentSection: null,
4834
+ files: /* @__PURE__ */ new Set()
4835
+ };
4836
+ const lines = output.split("\n");
4837
+ for (const line of lines) {
4838
+ const trimmedLine = line.trim();
4839
+ if (/Created \d+ files?:/.test(trimmedLine)) {
4840
+ state.currentSection = "created";
4841
+ continue;
4842
+ }
4843
+ if (/Updated \d+ files?:/.test(trimmedLine)) {
4844
+ state.currentSection = "updated";
4845
+ continue;
4846
+ }
4847
+ if (/Skipped \d+ files?:/.test(trimmedLine)) {
4848
+ state.currentSection = "skipped";
4849
+ continue;
4850
+ }
4851
+ if (state.currentSection && trimmedLine.startsWith("- ")) {
4852
+ const filePath = trimmedLine.slice(2).trim();
4853
+ if (filePath && filePath.includes("/")) {
4854
+ state.files.add(filePath);
4855
+ }
4856
+ }
4857
+ if (state.currentSection && trimmedLine.length > 1 && !trimmedLine.startsWith("- ")) {
4858
+ state.currentSection = null;
4859
+ }
4860
+ }
4861
+ return Array.from(state.files);
4862
+ }
4863
+ function toFileInfo(filePath) {
4864
+ const name = filePath.split("/").pop() || filePath;
4865
+ return { name, path: filePath };
4866
+ }
4867
+ var PROMPT_PATTERNS = [
4868
+ // 文件覆盖确认 - 回答 n(不覆盖)
4869
+ { pattern: /overwrite/i, answer: "n\n" },
4870
+ // 主题/样式选择 - 回答 n(不安装额外主题)
4871
+ { pattern: /theme/i, answer: "n\n" },
4872
+ { pattern: /style/i, answer: "n\n" },
4873
+ // 继续确认 - 回答 y
4874
+ { pattern: /continue\?/i, answer: "y\n" },
4875
+ { pattern: /proceed\?/i, answer: "y\n" }
4876
+ ];
4877
+ async function executeShadcnAdd(registryItemPath) {
4878
+ return new Promise((resolve2) => {
4879
+ let output = "";
4880
+ const args = ["--yes", "shadcn@3.8.2", "add", registryItemPath];
4881
+ const ptyProcess = pty.spawn("npx", args, {
4882
+ name: "xterm-color",
4883
+ cols: 120,
4884
+ rows: 30,
4885
+ cwd: process.cwd(),
4886
+ env: {
4887
+ ...process.env,
4888
+ // 禁用颜色输出以便解析
4889
+ NO_COLOR: "1",
4890
+ FORCE_COLOR: "0"
4891
+ }
4892
+ });
4893
+ ptyProcess.onData((data) => {
4894
+ output += data;
4895
+ for (const { pattern, answer } of PROMPT_PATTERNS) {
4896
+ if (pattern.test(data)) {
4897
+ ptyProcess.write(answer);
4898
+ return;
4899
+ }
4900
+ }
4901
+ });
4902
+ const timeoutId = setTimeout(() => {
4903
+ ptyProcess.kill();
4904
+ resolve2({
4905
+ success: false,
4906
+ files: [],
4907
+ error: "\u6267\u884C\u8D85\u65F6"
4908
+ });
4909
+ }, 3 * 60 * 1e3);
4910
+ ptyProcess.onExit(({ exitCode }) => {
4911
+ clearTimeout(timeoutId);
4912
+ const success = exitCode === 0;
4913
+ const filePaths = parseOutput(output);
4914
+ const files = filePaths.map(toFileInfo);
4915
+ resolve2({
4916
+ success,
4917
+ files,
4918
+ error: success ? void 0 : output || `Process exited with code ${exitCode}`
4919
+ });
4920
+ });
4921
+ });
4922
+ }
4923
+
4924
+ // src/commands/component/add.handler.ts
4925
+ function runActionPluginInit() {
4926
+ return new Promise((resolve2) => {
4927
+ execFile("fullstack-cli", ["action-plugin", "init"], { cwd: process.cwd(), stdio: "ignore" }, (error) => {
4928
+ if (error) {
4929
+ debug("action-plugin init \u5931\u8D25: %s", error.message);
4930
+ }
4931
+ resolve2();
4932
+ });
4933
+ });
4934
+ }
4935
+ function printResult(result) {
4936
+ console.log(JSON.stringify(result, null, 2));
4937
+ }
4938
+ async function addComponent(key) {
4939
+ debug("\u5F00\u59CB\u5B89\u88C5\u7EC4\u4EF6: %s", key);
4940
+ debug("\u51C6\u5907 registry items...");
4941
+ const registryItemPath = await prepareComponentRegistryItems(key);
4942
+ debug("registry item \u8DEF\u5F84: %s", registryItemPath);
4943
+ const registryItem = getDownloadedRegistryItem(key);
4944
+ debug("\u83B7\u53D6\u5230 registry item: %o", registryItem);
4945
+ debug("\u6267\u884C shadcn add...");
4946
+ const executeResult = await executeShadcnAdd(registryItemPath);
4947
+ debug("shadcn \u6267\u884C\u7ED3\u679C: %o", executeResult);
4948
+ if (!executeResult.success) {
4949
+ throw new Error(executeResult.error || "\u5B89\u88C5\u5931\u8D25\uFF0C\u672A\u77E5\u539F\u56E0");
4950
+ }
4951
+ return {
4952
+ success: true,
4953
+ name: key,
4954
+ description: registryItem?.description || "",
4955
+ files: executeResult.files,
4956
+ docs: registryItem?.docs || ""
4957
+ };
4958
+ }
4959
+ async function add(key) {
4960
+ try {
4961
+ const result = await addComponent(key);
4962
+ printResult(result);
4963
+ void sendInstallEvent(key);
4964
+ } catch (error) {
4965
+ const errorMessage = error instanceof Error ? error.message : "\u5B89\u88C5\u5931\u8D25\uFF0C\u539F\u56E0\u672A\u77E5";
4966
+ printResult({
4967
+ success: false,
4968
+ errors: [{ message: errorMessage }]
4969
+ });
4970
+ } finally {
4971
+ await runActionPluginInit();
4972
+ cleanupTempDir();
4973
+ }
4974
+ }
4975
+
4976
+ // src/commands/component/index.ts
4977
+ var addCommand = {
4978
+ name: "add",
4979
+ description: "\u5B89\u88C5\u5999\u642D\u7EC4\u4EF6\u5E02\u573A\u4E2D\u7684\u7EC4\u4EF6",
4980
+ register(program) {
4981
+ program.command(this.name).description(this.description).argument("<component>", "\u7EC4\u4EF6 ID (\u4F8B\u5982 @miaoda/button)").action(async (component) => {
4982
+ await add(component);
4983
+ });
4984
+ }
4985
+ };
4986
+ var componentCommandGroup = {
4987
+ name: "component",
4988
+ description: "\u7EC4\u4EF6\u76F8\u5173\u547D\u4EE4",
4989
+ commands: [addCommand]
4990
+ };
4991
+
4992
+ // src/commands/migration/version-manager.ts
4993
+ import fs17 from "fs";
4994
+ import path15 from "path";
4696
4995
  var PACKAGE_JSON = "package.json";
4697
4996
  var VERSION_FIELD = "migrationVersion";
4698
4997
  function getPackageJsonPath2() {
4699
- return path14.join(process.cwd(), PACKAGE_JSON);
4998
+ return path15.join(process.cwd(), PACKAGE_JSON);
4700
4999
  }
4701
5000
  function getCurrentVersion() {
4702
5001
  const pkgPath = getPackageJsonPath2();
4703
- if (!fs16.existsSync(pkgPath)) {
5002
+ if (!fs17.existsSync(pkgPath)) {
4704
5003
  throw new Error("package.json not found");
4705
5004
  }
4706
- const pkg2 = JSON.parse(fs16.readFileSync(pkgPath, "utf-8"));
5005
+ const pkg2 = JSON.parse(fs17.readFileSync(pkgPath, "utf-8"));
4707
5006
  return pkg2[VERSION_FIELD] ?? 0;
4708
5007
  }
4709
5008
  function setCurrentVersion(version) {
4710
5009
  const pkgPath = getPackageJsonPath2();
4711
- const pkg2 = JSON.parse(fs16.readFileSync(pkgPath, "utf-8"));
5010
+ const pkg2 = JSON.parse(fs17.readFileSync(pkgPath, "utf-8"));
4712
5011
  pkg2[VERSION_FIELD] = version;
4713
- fs16.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
5012
+ fs17.writeFileSync(pkgPath, JSON.stringify(pkg2, null, 2) + "\n", "utf-8");
4714
5013
  }
4715
5014
 
4716
5015
  // src/commands/migration/versions/v001_capability/json-migrator/detector.ts
4717
- import fs18 from "fs";
4718
- import path16 from "path";
5016
+ import fs19 from "fs";
5017
+ import path17 from "path";
4719
5018
 
4720
5019
  // src/commands/migration/versions/v001_capability/utils.ts
4721
- import fs17 from "fs";
4722
- import path15 from "path";
5020
+ import fs18 from "fs";
5021
+ import path16 from "path";
4723
5022
  var CAPABILITIES_DIR2 = "server/capabilities";
4724
5023
  function getProjectRoot3() {
4725
5024
  return process.cwd();
4726
5025
  }
4727
5026
  function getCapabilitiesDir2() {
4728
- return path15.join(getProjectRoot3(), CAPABILITIES_DIR2);
5027
+ return path16.join(getProjectRoot3(), CAPABILITIES_DIR2);
4729
5028
  }
4730
5029
  function getPluginManifestPath2(pluginKey) {
4731
- return path15.join(getProjectRoot3(), "node_modules", pluginKey, "manifest.json");
5030
+ return path16.join(getProjectRoot3(), "node_modules", pluginKey, "manifest.json");
4732
5031
  }
4733
5032
 
4734
5033
  // src/commands/migration/versions/v001_capability/json-migrator/detector.ts
4735
5034
  function detectJsonMigration() {
4736
5035
  const capabilitiesDir = getCapabilitiesDir2();
4737
- const oldFilePath = path16.join(capabilitiesDir, "capabilities.json");
4738
- if (!fs18.existsSync(oldFilePath)) {
5036
+ const oldFilePath = path17.join(capabilitiesDir, "capabilities.json");
5037
+ if (!fs19.existsSync(oldFilePath)) {
4739
5038
  return {
4740
5039
  needsMigration: false,
4741
5040
  reason: "capabilities.json not found"
4742
5041
  };
4743
5042
  }
4744
5043
  try {
4745
- const content = fs18.readFileSync(oldFilePath, "utf-8");
5044
+ const content = fs19.readFileSync(oldFilePath, "utf-8");
4746
5045
  const parsed = JSON.parse(content);
4747
5046
  if (!Array.isArray(parsed)) {
4748
5047
  return {
@@ -4793,8 +5092,8 @@ async function check(options) {
4793
5092
  }
4794
5093
 
4795
5094
  // src/commands/migration/versions/v001_capability/json-migrator/index.ts
4796
- import fs19 from "fs";
4797
- import path17 from "path";
5095
+ import fs20 from "fs";
5096
+ import path18 from "path";
4798
5097
 
4799
5098
  // src/commands/migration/versions/v001_capability/mapping.ts
4800
5099
  var DEFAULT_PLUGIN_VERSION = "1.0.0";
@@ -5024,18 +5323,18 @@ function transformCapabilities(oldCapabilities) {
5024
5323
  // src/commands/migration/versions/v001_capability/json-migrator/index.ts
5025
5324
  function loadExistingCapabilities() {
5026
5325
  const capabilitiesDir = getCapabilitiesDir2();
5027
- if (!fs19.existsSync(capabilitiesDir)) {
5326
+ if (!fs20.existsSync(capabilitiesDir)) {
5028
5327
  return [];
5029
5328
  }
5030
- const files = fs19.readdirSync(capabilitiesDir);
5329
+ const files = fs20.readdirSync(capabilitiesDir);
5031
5330
  const capabilities = [];
5032
5331
  for (const file of files) {
5033
5332
  if (file === "capabilities.json" || !file.endsWith(".json")) {
5034
5333
  continue;
5035
5334
  }
5036
5335
  try {
5037
- const filePath = path17.join(capabilitiesDir, file);
5038
- const content = fs19.readFileSync(filePath, "utf-8");
5336
+ const filePath = path18.join(capabilitiesDir, file);
5337
+ const content = fs20.readFileSync(filePath, "utf-8");
5039
5338
  const capability = JSON.parse(content);
5040
5339
  if (capability.id && capability.pluginKey) {
5041
5340
  capabilities.push(capability);
@@ -5093,9 +5392,9 @@ async function migrateJsonFiles(options) {
5093
5392
  }
5094
5393
  const capabilitiesDir = getCapabilitiesDir2();
5095
5394
  for (const cap of newCapabilities) {
5096
- const filePath = path17.join(capabilitiesDir, `${cap.id}.json`);
5395
+ const filePath = path18.join(capabilitiesDir, `${cap.id}.json`);
5097
5396
  const content = JSON.stringify(cap, null, 2);
5098
- fs19.writeFileSync(filePath, content, "utf-8");
5397
+ fs20.writeFileSync(filePath, content, "utf-8");
5099
5398
  console.log(` \u2713 Created: ${cap.id}.json`);
5100
5399
  }
5101
5400
  return {
@@ -5107,11 +5406,11 @@ async function migrateJsonFiles(options) {
5107
5406
  }
5108
5407
 
5109
5408
  // src/commands/migration/versions/v001_capability/plugin-installer/detector.ts
5110
- import fs20 from "fs";
5409
+ import fs21 from "fs";
5111
5410
  function isPluginInstalled2(pluginKey) {
5112
5411
  const actionPlugins = readActionPlugins();
5113
5412
  const manifestPath = getPluginManifestPath2(pluginKey);
5114
- return fs20.existsSync(manifestPath) && !!actionPlugins[pluginKey];
5413
+ return fs21.existsSync(manifestPath) && !!actionPlugins[pluginKey];
5115
5414
  }
5116
5415
  function detectPluginsToInstall(capabilities) {
5117
5416
  const pluginKeys = /* @__PURE__ */ new Set();
@@ -5187,12 +5486,12 @@ async function installPlugins(capabilities, options) {
5187
5486
  }
5188
5487
 
5189
5488
  // src/commands/migration/versions/v001_capability/code-migrator/index.ts
5190
- import path19 from "path";
5489
+ import path20 from "path";
5191
5490
  import { Project as Project3 } from "ts-morph";
5192
5491
 
5193
5492
  // src/commands/migration/versions/v001_capability/code-migrator/scanner.ts
5194
- import fs21 from "fs";
5195
- import path18 from "path";
5493
+ import fs22 from "fs";
5494
+ import path19 from "path";
5196
5495
  var EXCLUDED_DIRS = [
5197
5496
  "node_modules",
5198
5497
  "dist",
@@ -5207,9 +5506,9 @@ var EXCLUDED_PATTERNS = [
5207
5506
  /\.d\.ts$/
5208
5507
  ];
5209
5508
  function scanDirectory(dir, files = []) {
5210
- const entries = fs21.readdirSync(dir, { withFileTypes: true });
5509
+ const entries = fs22.readdirSync(dir, { withFileTypes: true });
5211
5510
  for (const entry of entries) {
5212
- const fullPath = path18.join(dir, entry.name);
5511
+ const fullPath = path19.join(dir, entry.name);
5213
5512
  if (entry.isDirectory()) {
5214
5513
  if (EXCLUDED_DIRS.includes(entry.name)) {
5215
5514
  continue;
@@ -5225,14 +5524,14 @@ function scanDirectory(dir, files = []) {
5225
5524
  return files;
5226
5525
  }
5227
5526
  function scanServerFiles() {
5228
- const serverDir = path18.join(getProjectRoot3(), "server");
5229
- if (!fs21.existsSync(serverDir)) {
5527
+ const serverDir = path19.join(getProjectRoot3(), "server");
5528
+ if (!fs22.existsSync(serverDir)) {
5230
5529
  return [];
5231
5530
  }
5232
5531
  return scanDirectory(serverDir);
5233
5532
  }
5234
5533
  function hasCapabilityImport(filePath) {
5235
- const content = fs21.readFileSync(filePath, "utf-8");
5534
+ const content = fs22.readFileSync(filePath, "utf-8");
5236
5535
  return /import\s+.*from\s+['"][^'"]*capabilities[^'"]*['"]/.test(content);
5237
5536
  }
5238
5537
  function scanFilesToMigrate() {
@@ -5609,7 +5908,7 @@ function analyzeFile(project, filePath, actionNameMap) {
5609
5908
  const callSites = analyzeCallSites(sourceFile, imports);
5610
5909
  const classInfo = analyzeClass(sourceFile);
5611
5910
  const { canMigrate, reason } = canAutoMigrate(classInfo);
5612
- const relativePath = path19.relative(getProjectRoot3(), filePath);
5911
+ const relativePath = path20.relative(getProjectRoot3(), filePath);
5613
5912
  return {
5614
5913
  filePath: relativePath,
5615
5914
  imports,
@@ -5620,7 +5919,7 @@ function analyzeFile(project, filePath, actionNameMap) {
5620
5919
  };
5621
5920
  }
5622
5921
  function migrateFile(project, analysis, dryRun) {
5623
- const absolutePath = path19.join(getProjectRoot3(), analysis.filePath);
5922
+ const absolutePath = path20.join(getProjectRoot3(), analysis.filePath);
5624
5923
  if (!analysis.canAutoMigrate) {
5625
5924
  return {
5626
5925
  filePath: analysis.filePath,
@@ -5723,17 +6022,17 @@ function getSuggestion(analysis) {
5723
6022
  }
5724
6023
 
5725
6024
  // src/commands/migration/versions/v001_capability/cleanup.ts
5726
- import fs22 from "fs";
5727
- import path20 from "path";
6025
+ import fs23 from "fs";
6026
+ import path21 from "path";
5728
6027
  function cleanupOldFiles(capabilities, dryRun) {
5729
6028
  const deletedFiles = [];
5730
6029
  const errors = [];
5731
6030
  const capabilitiesDir = getCapabilitiesDir2();
5732
- const oldJsonPath = path20.join(capabilitiesDir, "capabilities.json");
5733
- if (fs22.existsSync(oldJsonPath)) {
6031
+ const oldJsonPath = path21.join(capabilitiesDir, "capabilities.json");
6032
+ if (fs23.existsSync(oldJsonPath)) {
5734
6033
  try {
5735
6034
  if (!dryRun) {
5736
- fs22.unlinkSync(oldJsonPath);
6035
+ fs23.unlinkSync(oldJsonPath);
5737
6036
  }
5738
6037
  deletedFiles.push("capabilities.json");
5739
6038
  } catch (error) {
@@ -5741,11 +6040,11 @@ function cleanupOldFiles(capabilities, dryRun) {
5741
6040
  }
5742
6041
  }
5743
6042
  for (const cap of capabilities) {
5744
- const tsFilePath = path20.join(capabilitiesDir, `${cap.id}.ts`);
5745
- if (fs22.existsSync(tsFilePath)) {
6043
+ const tsFilePath = path21.join(capabilitiesDir, `${cap.id}.ts`);
6044
+ if (fs23.existsSync(tsFilePath)) {
5746
6045
  try {
5747
6046
  if (!dryRun) {
5748
- fs22.unlinkSync(tsFilePath);
6047
+ fs23.unlinkSync(tsFilePath);
5749
6048
  }
5750
6049
  deletedFiles.push(`${cap.id}.ts`);
5751
6050
  } catch (error) {
@@ -5761,8 +6060,8 @@ function cleanupOldFiles(capabilities, dryRun) {
5761
6060
  }
5762
6061
 
5763
6062
  // src/commands/migration/versions/v001_capability/report-generator.ts
5764
- import fs23 from "fs";
5765
- import path21 from "path";
6063
+ import fs24 from "fs";
6064
+ import path22 from "path";
5766
6065
  var REPORT_FILE = "capability-migration-report.md";
5767
6066
  function printSummary(result) {
5768
6067
  const { jsonMigration, pluginInstallation, codeMigration, cleanup } = result;
@@ -5925,15 +6224,15 @@ async function generateReport(result) {
5925
6224
  }
5926
6225
  lines.push("");
5927
6226
  const logDir = process.env.LOG_DIR || "logs";
5928
- if (!fs23.existsSync(logDir)) {
6227
+ if (!fs24.existsSync(logDir)) {
5929
6228
  return;
5930
6229
  }
5931
- const reportDir = path21.join(logDir, "migration");
5932
- if (!fs23.existsSync(reportDir)) {
5933
- fs23.mkdirSync(reportDir, { recursive: true });
6230
+ const reportDir = path22.join(logDir, "migration");
6231
+ if (!fs24.existsSync(reportDir)) {
6232
+ fs24.mkdirSync(reportDir, { recursive: true });
5934
6233
  }
5935
- const reportPath = path21.join(reportDir, REPORT_FILE);
5936
- fs23.writeFileSync(reportPath, lines.join("\n"), "utf-8");
6234
+ const reportPath = path22.join(reportDir, REPORT_FILE);
6235
+ fs24.writeFileSync(reportPath, lines.join("\n"), "utf-8");
5937
6236
  console.log(`\u{1F4C4} Report generated: ${reportPath}`);
5938
6237
  }
5939
6238
 
@@ -6465,10 +6764,10 @@ var migrationCommand = {
6465
6764
  };
6466
6765
 
6467
6766
  // src/commands/read-logs/index.ts
6468
- import path22 from "path";
6767
+ import path23 from "path";
6469
6768
 
6470
6769
  // src/commands/read-logs/std-utils.ts
6471
- import fs24 from "fs";
6770
+ import fs25 from "fs";
6472
6771
  function formatStdPrefixTime(localTime) {
6473
6772
  const match = localTime.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/);
6474
6773
  if (!match) return localTime;
@@ -6498,11 +6797,11 @@ function stripPrefixFromStdLine(line) {
6498
6797
  return `[${time}] ${content}`;
6499
6798
  }
6500
6799
  function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarker) {
6501
- const stat = fs24.statSync(filePath);
6800
+ const stat = fs25.statSync(filePath);
6502
6801
  if (stat.size === 0) {
6503
6802
  return { lines: [], markerFound: false, totalLinesCount: 0 };
6504
6803
  }
6505
- const fd = fs24.openSync(filePath, "r");
6804
+ const fd = fs25.openSync(filePath, "r");
6506
6805
  const chunkSize = 64 * 1024;
6507
6806
  let position = stat.size;
6508
6807
  let remainder = "";
@@ -6516,7 +6815,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
6516
6815
  const length = Math.min(chunkSize, position);
6517
6816
  position -= length;
6518
6817
  const buffer = Buffer.alloc(length);
6519
- fs24.readSync(fd, buffer, 0, length, position);
6818
+ fs25.readSync(fd, buffer, 0, length, position);
6520
6819
  let chunk = buffer.toString("utf8");
6521
6820
  if (remainder) {
6522
6821
  chunk += remainder;
@@ -6558,7 +6857,7 @@ function readStdLinesTailFromLastMarkerPaged(filePath, maxLines, offset, isMarke
6558
6857
  }
6559
6858
  }
6560
6859
  } finally {
6561
- fs24.closeSync(fd);
6860
+ fs25.closeSync(fd);
6562
6861
  }
6563
6862
  return { lines: collected.reverse(), markerFound, totalLinesCount };
6564
6863
  }
@@ -6579,21 +6878,21 @@ function readServerStdSegment(filePath, maxLines, offset) {
6579
6878
  }
6580
6879
 
6581
6880
  // src/commands/read-logs/tail.ts
6582
- import fs25 from "fs";
6881
+ import fs26 from "fs";
6583
6882
  function fileExists(filePath) {
6584
6883
  try {
6585
- fs25.accessSync(filePath, fs25.constants.F_OK | fs25.constants.R_OK);
6884
+ fs26.accessSync(filePath, fs26.constants.F_OK | fs26.constants.R_OK);
6586
6885
  return true;
6587
6886
  } catch {
6588
6887
  return false;
6589
6888
  }
6590
6889
  }
6591
6890
  function readFileTailLines(filePath, maxLines) {
6592
- const stat = fs25.statSync(filePath);
6891
+ const stat = fs26.statSync(filePath);
6593
6892
  if (stat.size === 0) {
6594
6893
  return [];
6595
6894
  }
6596
- const fd = fs25.openSync(filePath, "r");
6895
+ const fd = fs26.openSync(filePath, "r");
6597
6896
  const chunkSize = 64 * 1024;
6598
6897
  const chunks = [];
6599
6898
  let position = stat.size;
@@ -6603,13 +6902,13 @@ function readFileTailLines(filePath, maxLines) {
6603
6902
  const length = Math.min(chunkSize, position);
6604
6903
  position -= length;
6605
6904
  const buffer = Buffer.alloc(length);
6606
- fs25.readSync(fd, buffer, 0, length, position);
6905
+ fs26.readSync(fd, buffer, 0, length, position);
6607
6906
  chunks.unshift(buffer.toString("utf8"));
6608
6907
  const chunkLines = buffer.toString("utf8").split("\n").length - 1;
6609
6908
  collectedLines += chunkLines;
6610
6909
  }
6611
6910
  } finally {
6612
- fs25.closeSync(fd);
6911
+ fs26.closeSync(fd);
6613
6912
  }
6614
6913
  const content = chunks.join("");
6615
6914
  const allLines = content.split("\n");
@@ -6625,11 +6924,11 @@ function readFileTailLines(filePath, maxLines) {
6625
6924
  return allLines.slice(allLines.length - maxLines);
6626
6925
  }
6627
6926
  function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
6628
- const stat = fs25.statSync(filePath);
6927
+ const stat = fs26.statSync(filePath);
6629
6928
  if (stat.size === 0) {
6630
6929
  return { lines: [], totalLinesCount: 0 };
6631
6930
  }
6632
- const fd = fs25.openSync(filePath, "r");
6931
+ const fd = fs26.openSync(filePath, "r");
6633
6932
  const chunkSize = 64 * 1024;
6634
6933
  let position = stat.size;
6635
6934
  let remainder = "";
@@ -6641,7 +6940,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
6641
6940
  const length = Math.min(chunkSize, position);
6642
6941
  position -= length;
6643
6942
  const buffer = Buffer.alloc(length);
6644
- fs25.readSync(fd, buffer, 0, length, position);
6943
+ fs26.readSync(fd, buffer, 0, length, position);
6645
6944
  let chunk = buffer.toString("utf8");
6646
6945
  if (remainder) {
6647
6946
  chunk += remainder;
@@ -6672,7 +6971,7 @@ function readFileTailNonEmptyLinesWithOffset(filePath, maxLines, offset) {
6672
6971
  }
6673
6972
  }
6674
6973
  } finally {
6675
- fs25.closeSync(fd);
6974
+ fs26.closeSync(fd);
6676
6975
  }
6677
6976
  return { lines: collected.reverse(), totalLinesCount };
6678
6977
  }
@@ -6814,7 +7113,7 @@ function readDevStdSegment(filePath, maxLines, offset) {
6814
7113
  }
6815
7114
 
6816
7115
  // src/commands/read-logs/json-lines.ts
6817
- import fs26 from "fs";
7116
+ import fs27 from "fs";
6818
7117
  function normalizePid(value) {
6819
7118
  if (typeof value === "number") {
6820
7119
  return String(value);
@@ -6865,11 +7164,11 @@ function buildWantedLevelSet(levels) {
6865
7164
  return set.size > 0 ? set : null;
6866
7165
  }
6867
7166
  function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
6868
- const stat = fs26.statSync(filePath);
7167
+ const stat = fs27.statSync(filePath);
6869
7168
  if (stat.size === 0) {
6870
7169
  return { lines: [], totalLinesCount: 0 };
6871
7170
  }
6872
- const fd = fs26.openSync(filePath, "r");
7171
+ const fd = fs27.openSync(filePath, "r");
6873
7172
  const chunkSize = 64 * 1024;
6874
7173
  let position = stat.size;
6875
7174
  let remainder = "";
@@ -6884,7 +7183,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
6884
7183
  const length = Math.min(chunkSize, position);
6885
7184
  position -= length;
6886
7185
  const buffer = Buffer.alloc(length);
6887
- fs26.readSync(fd, buffer, 0, length, position);
7186
+ fs27.readSync(fd, buffer, 0, length, position);
6888
7187
  let chunk = buffer.toString("utf8");
6889
7188
  if (remainder) {
6890
7189
  chunk += remainder;
@@ -6946,7 +7245,7 @@ function readJsonLinesLastPid(filePath, maxLines, offset, levels) {
6946
7245
  }
6947
7246
  }
6948
7247
  } finally {
6949
- fs26.closeSync(fd);
7248
+ fs27.closeSync(fd);
6950
7249
  }
6951
7250
  return { lines: collected.reverse(), totalLinesCount };
6952
7251
  }
@@ -6989,11 +7288,11 @@ function extractTraceId(obj) {
6989
7288
  function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
6990
7289
  const wanted = traceId.trim();
6991
7290
  if (!wanted) return { lines: [], totalLinesCount: 0 };
6992
- const stat = fs26.statSync(filePath);
7291
+ const stat = fs27.statSync(filePath);
6993
7292
  if (stat.size === 0) {
6994
7293
  return { lines: [], totalLinesCount: 0 };
6995
7294
  }
6996
- const fd = fs26.openSync(filePath, "r");
7295
+ const fd = fs27.openSync(filePath, "r");
6997
7296
  const chunkSize = 64 * 1024;
6998
7297
  let position = stat.size;
6999
7298
  let remainder = "";
@@ -7006,7 +7305,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
7006
7305
  const length = Math.min(chunkSize, position);
7007
7306
  position -= length;
7008
7307
  const buffer = Buffer.alloc(length);
7009
- fs26.readSync(fd, buffer, 0, length, position);
7308
+ fs27.readSync(fd, buffer, 0, length, position);
7010
7309
  let chunk = buffer.toString("utf8");
7011
7310
  if (remainder) {
7012
7311
  chunk += remainder;
@@ -7059,7 +7358,7 @@ function readJsonLinesByTraceId(filePath, traceId, maxLines, offset, levels) {
7059
7358
  }
7060
7359
  }
7061
7360
  } finally {
7062
- fs26.closeSync(fd);
7361
+ fs27.closeSync(fd);
7063
7362
  }
7064
7363
  return { lines: collected.reverse(), totalLinesCount };
7065
7364
  }
@@ -7068,11 +7367,11 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
7068
7367
  if (!wantedLevelSet) {
7069
7368
  return { lines: [], totalLinesCount: 0 };
7070
7369
  }
7071
- const stat = fs26.statSync(filePath);
7370
+ const stat = fs27.statSync(filePath);
7072
7371
  if (stat.size === 0) {
7073
7372
  return { lines: [], totalLinesCount: 0 };
7074
7373
  }
7075
- const fd = fs26.openSync(filePath, "r");
7374
+ const fd = fs27.openSync(filePath, "r");
7076
7375
  const chunkSize = 64 * 1024;
7077
7376
  let position = stat.size;
7078
7377
  let remainder = "";
@@ -7084,7 +7383,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
7084
7383
  const length = Math.min(chunkSize, position);
7085
7384
  position -= length;
7086
7385
  const buffer = Buffer.alloc(length);
7087
- fs26.readSync(fd, buffer, 0, length, position);
7386
+ fs27.readSync(fd, buffer, 0, length, position);
7088
7387
  let chunk = buffer.toString("utf8");
7089
7388
  if (remainder) {
7090
7389
  chunk += remainder;
@@ -7131,7 +7430,7 @@ function readJsonLinesTailByLevel(filePath, maxLines, offset, levels) {
7131
7430
  }
7132
7431
  }
7133
7432
  } finally {
7134
- fs26.closeSync(fd);
7433
+ fs27.closeSync(fd);
7135
7434
  }
7136
7435
  return { lines: collected.reverse(), totalLinesCount };
7137
7436
  }
@@ -7365,30 +7664,30 @@ async function readLogsJsonResult(options) {
7365
7664
  };
7366
7665
  }
7367
7666
  function resolveLogFilePath(logDir, type) {
7368
- const base = path22.isAbsolute(logDir) ? logDir : path22.join(process.cwd(), logDir);
7667
+ const base = path23.isAbsolute(logDir) ? logDir : path23.join(process.cwd(), logDir);
7369
7668
  if (type === "server") {
7370
- return path22.join(base, "server.log");
7669
+ return path23.join(base, "server.log");
7371
7670
  }
7372
7671
  if (type === "trace") {
7373
- return path22.join(base, "trace.log");
7672
+ return path23.join(base, "trace.log");
7374
7673
  }
7375
7674
  if (type === "server-std") {
7376
- return path22.join(base, "server.std.log");
7675
+ return path23.join(base, "server.std.log");
7377
7676
  }
7378
7677
  if (type === "client-std") {
7379
- return path22.join(base, "client.std.log");
7678
+ return path23.join(base, "client.std.log");
7380
7679
  }
7381
7680
  if (type === "dev") {
7382
- return path22.join(base, "dev.log");
7681
+ return path23.join(base, "dev.log");
7383
7682
  }
7384
7683
  if (type === "dev-std") {
7385
- return path22.join(base, "dev.std.log");
7684
+ return path23.join(base, "dev.std.log");
7386
7685
  }
7387
7686
  if (type === "install-dep-std") {
7388
- return path22.join(base, "install-dep.std.log");
7687
+ return path23.join(base, "install-dep.std.log");
7389
7688
  }
7390
7689
  if (type === "browser") {
7391
- return path22.join(base, "browser.log");
7690
+ return path23.join(base, "browser.log");
7392
7691
  }
7393
7692
  throw new Error(`Unsupported log type: ${type}`);
7394
7693
  }
@@ -7565,9 +7864,9 @@ function camelToKebab(str) {
7565
7864
  }
7566
7865
 
7567
7866
  // src/commands/build/upload-static.handler.ts
7568
- import * as fs27 from "fs";
7569
- import * as os from "os";
7570
- import * as path23 from "path";
7867
+ import * as fs28 from "fs";
7868
+ import * as os2 from "os";
7869
+ import * as path24 from "path";
7571
7870
  import { execFileSync } from "child_process";
7572
7871
  function readCredentialsFromEnv() {
7573
7872
  const uploadPrefix = process.env.STATIC_UPLOAD_PREFIX;
@@ -7591,8 +7890,8 @@ async function uploadStatic(options) {
7591
7890
  endpoint = UPLOAD_STATIC_DEFAULTS.endpoint,
7592
7891
  region = UPLOAD_STATIC_DEFAULTS.region
7593
7892
  } = options;
7594
- const resolvedStaticDir = path23.resolve(staticDir);
7595
- if (!fs27.existsSync(resolvedStaticDir)) {
7893
+ const resolvedStaticDir = path24.resolve(staticDir);
7894
+ if (!fs28.existsSync(resolvedStaticDir)) {
7596
7895
  console.error(`${LOG_PREFIX} \u76EE\u5F55\u4E0D\u5B58\u5728: ${resolvedStaticDir}\uFF0C\u8DF3\u8FC7\u4E0A\u4F20`);
7597
7896
  return;
7598
7897
  }
@@ -7625,8 +7924,8 @@ async function uploadStatic(options) {
7625
7924
  ({ AccessKeyID: accessKeyID, SecretAccessKey: secretAccessKey, SessionToken: sessionToken } = uploadCredential);
7626
7925
  }
7627
7926
  console.error(`${LOG_PREFIX} \u4E0A\u4F20\u76EE\u6807: ${uploadPrefix}`);
7628
- const confPath = path23.join(os.tmpdir(), `.tosutilconfig-static-${process.pid}`);
7629
- fs27.writeFileSync(confPath, "");
7927
+ const confPath = path24.join(os2.tmpdir(), `.tosutilconfig-static-${process.pid}`);
7928
+ fs28.writeFileSync(confPath, "");
7630
7929
  try {
7631
7930
  console.error(`${LOG_PREFIX} \u914D\u7F6E tosutil...`);
7632
7931
  configureTosutil(resolvedTosutil, confPath, {
@@ -7640,7 +7939,7 @@ async function uploadStatic(options) {
7640
7939
  uploadToTos(resolvedTosutil, confPath, resolvedStaticDir, uploadPrefix);
7641
7940
  } finally {
7642
7941
  try {
7643
- fs27.unlinkSync(confPath);
7942
+ fs28.unlinkSync(confPath);
7644
7943
  } catch {
7645
7944
  }
7646
7945
  }
@@ -7660,8 +7959,8 @@ async function uploadStatic(options) {
7660
7959
  }
7661
7960
  }
7662
7961
  function resolveTosutilPath(tosutilPath) {
7663
- if (path23.isAbsolute(tosutilPath)) {
7664
- return fs27.existsSync(tosutilPath) ? tosutilPath : null;
7962
+ if (path24.isAbsolute(tosutilPath)) {
7963
+ return fs28.existsSync(tosutilPath) ? tosutilPath : null;
7665
7964
  }
7666
7965
  try {
7667
7966
  const resolved = execFileSync("which", [tosutilPath], { encoding: "utf-8" }).trim();
@@ -7706,7 +8005,7 @@ async function resolveBucketId(appId) {
7706
8005
  return bucketId;
7707
8006
  }
7708
8007
  function isDirEmpty(dirPath) {
7709
- const entries = fs27.readdirSync(dirPath);
8008
+ const entries = fs28.readdirSync(dirPath);
7710
8009
  return entries.length === 0;
7711
8010
  }
7712
8011
 
@@ -7794,18 +8093,19 @@ var commands = [
7794
8093
  upgradeCommand,
7795
8094
  actionPluginCommandGroup,
7796
8095
  capabilityCommandGroup,
8096
+ componentCommandGroup,
7797
8097
  migrationCommand,
7798
8098
  readLogsCommand,
7799
8099
  buildCommandGroup
7800
8100
  ];
7801
8101
 
7802
8102
  // src/index.ts
7803
- var envPath = path24.join(process.cwd(), ".env");
7804
- if (fs28.existsSync(envPath)) {
8103
+ var envPath = path25.join(process.cwd(), ".env");
8104
+ if (fs29.existsSync(envPath)) {
7805
8105
  dotenvConfig({ path: envPath });
7806
8106
  }
7807
- var __dirname = path24.dirname(fileURLToPath5(import.meta.url));
7808
- var pkg = JSON.parse(fs28.readFileSync(path24.join(__dirname, "../package.json"), "utf-8"));
8107
+ var __dirname = path25.dirname(fileURLToPath5(import.meta.url));
8108
+ var pkg = JSON.parse(fs29.readFileSync(path25.join(__dirname, "../package.json"), "utf-8"));
7809
8109
  var cli = new FullstackCLI(pkg.version);
7810
8110
  cli.useAll(commands);
7811
8111
  cli.run();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/fullstack-cli",
3
- "version": "1.1.48-alpha.0",
3
+ "version": "1.1.48-alpha.1",
4
4
  "description": "CLI tool for fullstack template management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -31,7 +31,7 @@
31
31
  "access": "public"
32
32
  },
33
33
  "dependencies": {
34
- "@lark-apaas/http-client": "^0.1.6",
34
+ "@lark-apaas/http-client": "0.1.7-alpha.0",
35
35
  "@lydell/node-pty": "1.1.0",
36
36
  "@vercel/nft": "^0.30.3",
37
37
  "commander": "^13.0.0",
@@ -43,6 +43,7 @@
43
43
  "inflection": "^3.0.2",
44
44
  "pinyin-pro": "^3.27.0",
45
45
  "postgres": "^3.4.3",
46
+ "shadcn": "3.8.2",
46
47
  "ts-morph": "^27.0.0",
47
48
  "zod-to-json-schema": "^3.24.1"
48
49
  },