mano-coding 0.1.23 → 0.1.25

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/dist/bin.js CHANGED
@@ -23947,7 +23947,7 @@ var init_errors3 = __esm({
23947
23947
 
23948
23948
  // packages/core/src/resolvers/registry-client.ts
23949
23949
  function selectRelease(entry, versionRange) {
23950
- const stableVersion = entry.channels?.stable;
23950
+ const packageId = entry.id ?? entry.metadata?.id ?? "unknown";
23951
23951
  const normalizedRange = normalizeRange(versionRange);
23952
23952
  const candidates = entry.releases.filter((r) => {
23953
23953
  if (import_semver2.default.prerelease(r.version) && !rangeAllowsPrerelease(normalizedRange)) {
@@ -23957,12 +23957,13 @@ function selectRelease(entry, versionRange) {
23957
23957
  });
23958
23958
  if (candidates.length === 0) {
23959
23959
  throw new RegistryError(
23960
- `Package ${entry.metadata.id} \u6CA1\u6709\u6EE1\u8DB3\u7248\u672C\u8303\u56F4 '${versionRange}' \u7684 Release`,
23960
+ `Package ${packageId} \u6CA1\u6709\u6EE1\u8DB3\u7248\u672C\u8303\u56F4 '${versionRange}' \u7684 Release`,
23961
23961
  "REGISTRY_NO_MATCHING_RELEASE",
23962
- entry.metadata.id
23962
+ packageId
23963
23963
  );
23964
23964
  }
23965
23965
  candidates.sort((a, b2) => import_semver2.default.rcompare(a.version, b2.version));
23966
+ const stableVersion = entry.channels?.stable ?? candidates.find((r) => !import_semver2.default.prerelease(r.version))?.version;
23966
23967
  if (stableVersion) {
23967
23968
  const stableMatch = candidates.find((r) => r.version === stableVersion);
23968
23969
  if (stableMatch) return stableMatch;
@@ -28159,9 +28160,18 @@ var init_gitlab_registry_client = __esm({
28159
28160
  );
28160
28161
  }
28161
28162
  const entry = value;
28162
- if (entry.metadata.id !== packageId) {
28163
+ const entryId = entry.id ?? entry.metadata?.id;
28164
+ if (entryId && entryId !== packageId) {
28163
28165
  throw new RegistryError(`Registry Entry \u6807\u8BC6\u4E0D\u5339\u914D: \u671F\u671B ${packageId}`, "REGISTRY_ENTRY_INVALID", packageId);
28164
28166
  }
28167
+ if (!entry.metadata) {
28168
+ entry.metadata = {
28169
+ id: entry.id ?? packageId,
28170
+ name: entry.name,
28171
+ displayName: entry.displayName ?? entry.name,
28172
+ description: entry.description
28173
+ };
28174
+ }
28165
28175
  const { isGitLabShorthand: isGitLabShorthand2, parseGitLabShorthand: parseGitLabShorthand2 } = await Promise.resolve().then(() => (init_gitlab_shorthand(), gitlab_shorthand_exports));
28166
28176
  for (const release of entry.releases) {
28167
28177
  if (typeof release.source === "string" && isGitLabShorthand2(release.source)) {
@@ -31978,10 +31988,11 @@ function interpolateString(template, ctx) {
31978
31988
  }
31979
31989
  function generateTaskSummary(tasks, ctx) {
31980
31990
  return tasks.map((task, idx) => {
31991
+ const taskLabel = task.name ? `${task.name} (${task.id})` : task.id;
31981
31992
  const command = interpolateString(task.command, ctx);
31982
31993
  const args = (task.args ?? []).map((arg) => interpolateString(arg, ctx));
31983
31994
  const fullCmd = [command, ...args].join(" ");
31984
- return `[${idx + 1}/${tasks.length}] ${task.id}: ${fullCmd}`;
31995
+ return `[${idx + 1}/${tasks.length}] ${taskLabel}: ${fullCmd}`;
31985
31996
  });
31986
31997
  }
31987
31998
  function resolveTaskExecutable(command, platform = process.platform, envPath) {
@@ -32040,8 +32051,9 @@ async function executeTasks(tasks, ctx, options = {}) {
32040
32051
  env[k2] = interpolateString(v2, ctx);
32041
32052
  }
32042
32053
  }
32054
+ const taskLabel = task.name ? `${task.name} (${task.id})` : task.id;
32043
32055
  if (options.onProgress) {
32044
- options.onProgress(`\u6B63\u5728\u6267\u884C\u4EFB\u52A1 [${i + 1}/${tasks.length}] (${task.id}): ${command} ${effectiveArgs.join(" ")}`);
32056
+ options.onProgress(`\u6B63\u5728\u6267\u884C\u4EFB\u52A1 [${i + 1}/${tasks.length}] (${taskLabel}): ${command} ${effectiveArgs.join(" ")}`);
32045
32057
  }
32046
32058
  const executable = resolveTaskExecutable(command, process.platform, env.PATH);
32047
32059
  await new Promise((resolve22, reject) => {
@@ -38886,6 +38898,102 @@ var init_searchable_select = __esm({
38886
38898
  }
38887
38899
  });
38888
38900
 
38901
+ // packages/cli/src/commands/spinner.ts
38902
+ async function withSpinner(text, action, options) {
38903
+ const spinner = new Spinner(text, { enabled: options?.enabled });
38904
+ spinner.start();
38905
+ try {
38906
+ const result = await action(spinner);
38907
+ const successMsg = typeof options?.successText === "function" ? options.successText(result) : options?.successText ?? text;
38908
+ spinner.succeed(successMsg);
38909
+ return result;
38910
+ } catch (error) {
38911
+ spinner.fail(options?.failText);
38912
+ throw error;
38913
+ }
38914
+ }
38915
+ var Spinner;
38916
+ var init_spinner = __esm({
38917
+ "packages/cli/src/commands/spinner.ts"() {
38918
+ "use strict";
38919
+ init_src2();
38920
+ Spinner = class {
38921
+ text;
38922
+ timer = null;
38923
+ frameIndex = 0;
38924
+ isSpinning = false;
38925
+ enabled;
38926
+ frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
38927
+ interval = 80;
38928
+ constructor(text = "", options = {}) {
38929
+ this.text = text;
38930
+ this.enabled = options.enabled ?? (Boolean(process.stdout.isTTY) && process.env.NODE_ENV !== "test" && !process.env.CI);
38931
+ }
38932
+ start(text) {
38933
+ if (text !== void 0) this.text = text;
38934
+ if (!this.enabled || this.isSpinning) return this;
38935
+ this.isSpinning = true;
38936
+ this.frameIndex = 0;
38937
+ process.stdout.write("\x1B[?25l");
38938
+ this.render();
38939
+ this.timer = setInterval(() => {
38940
+ this.frameIndex = (this.frameIndex + 1) % this.frames.length;
38941
+ this.render();
38942
+ }, this.interval);
38943
+ return this;
38944
+ }
38945
+ update(text) {
38946
+ this.text = text;
38947
+ if (this.isSpinning && this.enabled) {
38948
+ this.render();
38949
+ }
38950
+ return this;
38951
+ }
38952
+ succeed(text) {
38953
+ return this.stopAndPersist("\u2714", text ?? this.text, "\x1B[32m");
38954
+ }
38955
+ fail(text) {
38956
+ return this.stopAndPersist("\u2716", text ?? this.text, "\x1B[31m");
38957
+ }
38958
+ warn(text) {
38959
+ return this.stopAndPersist("\u26A0", text ?? this.text, "\x1B[33m");
38960
+ }
38961
+ info(text) {
38962
+ return this.stopAndPersist("\u2139", text ?? this.text, "\x1B[34m");
38963
+ }
38964
+ stop() {
38965
+ if (!this.isSpinning) return this;
38966
+ if (this.timer) {
38967
+ clearInterval(this.timer);
38968
+ this.timer = null;
38969
+ }
38970
+ this.isSpinning = false;
38971
+ if (this.enabled) {
38972
+ process.stdout.write("\r\x1B[2K\x1B[?25h");
38973
+ }
38974
+ return this;
38975
+ }
38976
+ stopAndPersist(symbol, text, color = "") {
38977
+ this.stop();
38978
+ if (this.enabled) {
38979
+ const reset = "\x1B[0m";
38980
+ const cleanText = text.replace(/^[✔✖⚠ℹ\s]+/, "");
38981
+ const output = `${color}${symbol}${reset} ${redactString(cleanText)}
38982
+ `;
38983
+ process.stdout.write(output);
38984
+ }
38985
+ return this;
38986
+ }
38987
+ render() {
38988
+ const frame = this.frames[this.frameIndex];
38989
+ const cyan = "\x1B[36m";
38990
+ const reset = "\x1B[0m";
38991
+ process.stdout.write(`\r\x1B[2K${cyan}${frame}${reset} ${redactString(this.text)}`);
38992
+ }
38993
+ };
38994
+ }
38995
+ });
38996
+
38889
38997
  // packages/cli/src/commands/tty-confirm.ts
38890
38998
  var tty_confirm_exports = {};
38891
38999
  __export(tty_confirm_exports, {
@@ -39097,19 +39205,36 @@ async function executeCreate(templateSpec, directory, options, cliVersion, event
39097
39205
  throw error;
39098
39206
  }
39099
39207
  }
39100
- const templateResolution = await events.measure("resolve", () => resolvePackageWith(
39101
- service,
39102
- templateSpec,
39103
- options,
39104
- cliVersion
39105
- ), { packageId: templateSpec });
39106
- const addonResolutions = [];
39107
- for (const addonSpec of options.addons ?? []) {
39108
- const addonResolution = await events.measure("resolve", () => resolvePackageWith(
39208
+ const spinnerEnabled = !output.json && Boolean(process.stdout.isTTY) && process.env.NODE_ENV !== "test";
39209
+ const templateResolution = await events.measure("resolve", () => withSpinner(
39210
+ `\u6B63\u5728\u62C9\u53D6\u5E76\u89E3\u6790\u6A21\u677F (${templateSpec})...`,
39211
+ () => resolvePackageWith(
39109
39212
  service,
39110
- addonSpec,
39213
+ templateSpec,
39111
39214
  options,
39112
39215
  cliVersion
39216
+ ),
39217
+ {
39218
+ enabled: spinnerEnabled,
39219
+ successText: (res) => `\u2714 \u6A21\u677F\u89E3\u6790\u5B8C\u6210: ${res.manifest.displayName ?? res.manifest.name ?? res.manifest.id ?? templateSpec} (v${res.manifest.version ?? "0.0.0"})`,
39220
+ failText: `\u2716 \u6A21\u677F\u89E3\u6790\u5931\u8D25: ${templateSpec}`
39221
+ }
39222
+ ), { packageId: templateSpec });
39223
+ const addonResolutions = [];
39224
+ for (const addonSpec of options.addons ?? []) {
39225
+ const addonResolution = await events.measure("resolve", () => withSpinner(
39226
+ `\u6B63\u5728\u62C9\u53D6\u5E76\u89E3\u6790\u6269\u5C55 (${addonSpec})...`,
39227
+ () => resolvePackageWith(
39228
+ service,
39229
+ addonSpec,
39230
+ options,
39231
+ cliVersion
39232
+ ),
39233
+ {
39234
+ enabled: spinnerEnabled,
39235
+ successText: (res) => `\u2714 \u6269\u5C55\u89E3\u6790\u5B8C\u6210: ${res.manifest.displayName ?? res.manifest.name ?? res.manifest.id ?? addonSpec} (v${res.manifest.version ?? "0.0.0"})`,
39236
+ failText: `\u2716 \u6269\u5C55\u89E3\u6790\u5931\u8D25: ${addonSpec}`
39237
+ }
39113
39238
  ), { packageId: addonSpec });
39114
39239
  addonResolutions.push(addonResolution);
39115
39240
  }
@@ -39185,7 +39310,15 @@ ${taskValidation.missingInputs.map((k2) => `--set ${k2}=<value>`).join("\n")}`,
39185
39310
  projectTargets
39186
39311
  );
39187
39312
  const userInstallationKeys = /* @__PURE__ */ new Set();
39188
- const intents = await buildIntentsFromPlan(planResult.plan, allResolutions, service, projectTargets, userInstallationKeys);
39313
+ const intents = await withSpinner(
39314
+ "\u6B63\u5728\u8BA1\u7B97\u53D7\u7BA1\u8D44\u6E90\u5E76\u751F\u6210\u6267\u884C\u8BA1\u5212...",
39315
+ () => buildIntentsFromPlan(planResult.plan, allResolutions, service, projectTargets, userInstallationKeys),
39316
+ {
39317
+ enabled: spinnerEnabled,
39318
+ successText: (res) => `\u2714 \u6267\u884C\u8BA1\u5212\u5DF2\u5C31\u7EEA (\u5171 ${res.length} \u9879\u8D44\u6E90\u53D8\u66F4)`,
39319
+ failText: "\u2716 \u6267\u884C\u8BA1\u5212\u751F\u6210\u5931\u8D25"
39320
+ }
39321
+ );
39189
39322
  planResult = materializePlan(planResult.plan, intents);
39190
39323
  events.report("plan", "success", Date.now() - planStartedAt, { planDigest: planResult.plan.planDigest, details: { intentCount: intents.length } });
39191
39324
  if (planResult.conflicts.length > 0) {
@@ -39499,6 +39632,7 @@ var init_create = __esm({
39499
39632
  init_service_locator();
39500
39633
  init_plan_execution();
39501
39634
  init_searchable_select();
39635
+ init_spinner();
39502
39636
  init_i18n();
39503
39637
  }
39504
39638
  });
@@ -39561,17 +39695,33 @@ async function executeApply(packageSpec, options, cliVersion, events) {
39561
39695
  }
39562
39696
  let templateResolution;
39563
39697
  let addonResolutions = [];
39698
+ const spinnerEnabled = !output.json && Boolean(process.stdout.isTTY) && process.env.NODE_ENV !== "test";
39564
39699
  if (existingLock) {
39565
- const existing = await resolveLockedPackages(existingLock, service);
39700
+ const existing = await withSpinner(
39701
+ "\u6B63\u5728\u4ECE\u9501\u5B9A\u6587\u4EF6\u89E3\u6790\u5DF2\u5B89\u88C5\u5305...",
39702
+ () => resolveLockedPackages(existingLock, service),
39703
+ {
39704
+ enabled: spinnerEnabled,
39705
+ successText: "\u2714 \u5DF2\u52A0\u8F7D\u9501\u5B9A\u914D\u7F6E"
39706
+ }
39707
+ );
39566
39708
  templateResolution = existing.template;
39567
39709
  addonResolutions = existing.addons;
39568
39710
  }
39569
39711
  if (packageSpec) {
39570
- const newAddonResolution = await resolvePackageWith2(
39571
- service,
39572
- packageSpec,
39573
- options,
39574
- cliVersion
39712
+ const newAddonResolution = await withSpinner(
39713
+ `\u6B63\u5728\u62C9\u53D6\u5E76\u89E3\u6790\u6269\u5C55 (${packageSpec})...`,
39714
+ () => resolvePackageWith2(
39715
+ service,
39716
+ packageSpec,
39717
+ options,
39718
+ cliVersion
39719
+ ),
39720
+ {
39721
+ enabled: spinnerEnabled,
39722
+ successText: (res) => `\u2714 \u6269\u5C55\u89E3\u6790\u5B8C\u6210: ${res.manifest.displayName ?? res.manifest.name ?? res.manifest.id ?? packageSpec} (v${res.manifest.version ?? "0.0.0"})`,
39723
+ failText: `\u2716 \u6269\u5C55\u89E3\u6790\u5931\u8D25: ${packageSpec}`
39724
+ }
39575
39725
  );
39576
39726
  addonResolutions = [...addonResolutions.filter((resolution) => resolution.packageId !== newAddonResolution.packageId), newAddonResolution];
39577
39727
  }
@@ -39612,7 +39762,15 @@ async function executeApply(packageSpec, options, cliVersion, events) {
39612
39762
  projectTargets
39613
39763
  );
39614
39764
  const userInstallationKeys = /* @__PURE__ */ new Set();
39615
- const intents = await buildIntentsFromPlan(planResult.plan, allResolutions, service, projectTargets, userInstallationKeys);
39765
+ const intents = await withSpinner(
39766
+ "\u6B63\u5728\u8BA1\u7B97\u53D7\u7BA1\u8D44\u6E90\u5E76\u751F\u6210\u6267\u884C\u8BA1\u5212...",
39767
+ () => buildIntentsFromPlan(planResult.plan, allResolutions, service, projectTargets, userInstallationKeys),
39768
+ {
39769
+ enabled: spinnerEnabled,
39770
+ successText: (res) => `\u2714 \u6267\u884C\u8BA1\u5212\u5DF2\u5C31\u7EEA (\u5171 ${res.length} \u9879\u8D44\u6E90\u53D8\u66F4)`,
39771
+ failText: "\u2716 \u6267\u884C\u8BA1\u5212\u751F\u6210\u5931\u8D25"
39772
+ }
39773
+ );
39616
39774
  planResult = materializePlan(planResult.plan, intents);
39617
39775
  events.report("plan", "success", Date.now() - planStartedAt, { planDigest: planResult.plan.planDigest, details: { intentCount: intents.length } });
39618
39776
  if (planResult.conflicts.length > 0) {
@@ -39874,6 +40032,7 @@ var init_apply = __esm({
39874
40032
  init_shared_options();
39875
40033
  init_cli_output();
39876
40034
  init_service_locator();
40035
+ init_spinner();
39877
40036
  init_i18n();
39878
40037
  init_plan_execution();
39879
40038
  }
@@ -42101,7 +42260,7 @@ import { createRequire as createRequire2 } from "node:module";
42101
42260
  import { readFileSync as readFileSync4 } from "node:fs";
42102
42261
  import { fileURLToPath as fileURLToPath5 } from "node:url";
42103
42262
  function resolveVersion() {
42104
- if (true) return "0.1.23";
42263
+ if (true) return "0.1.25";
42105
42264
  const candidates = [
42106
42265
  new URL("../package.json", import.meta.url),
42107
42266
  new URL("../../package.json", import.meta.url),
@@ -35,6 +35,11 @@
35
35
  "pattern": "^[a-zA-Z][a-zA-Z0-9_-]*$",
36
36
  "maxLength": 64
37
37
  },
38
+ "name": {
39
+ "type": "string",
40
+ "minLength": 1,
41
+ "maxLength": 100
42
+ },
38
43
  "command": {
39
44
  "type": "string",
40
45
  "minLength": 1,
@@ -4,10 +4,16 @@
4
4
  "title": "Mano Coding Registry Entry",
5
5
  "type": "object",
6
6
  "additionalProperties": true,
7
- "required": ["metadata", "releases"],
7
+ "required": ["releases"],
8
8
  "properties": {
9
+ "apiVersion": { "type": "string" },
9
10
  "kind": { "type": "string" },
11
+ "id": { "$ref": "#/$defs/packageName" },
12
+ "name": { "type": "string", "minLength": 1, "maxLength": 80 },
13
+ "displayName": { "type": "string", "minLength": 1, "maxLength": 80 },
14
+ "description": { "type": "string", "maxLength": 500 },
10
15
  "metadata": { "$ref": "#/$defs/metadata" },
16
+ "channels": { "type": "object" },
11
17
  "releases": {
12
18
  "type": "array",
13
19
  "minItems": 1,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mano-coding",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "Mano Coding CLI and toolchain",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -35,6 +35,11 @@
35
35
  "pattern": "^[a-zA-Z][a-zA-Z0-9_-]*$",
36
36
  "maxLength": 64
37
37
  },
38
+ "name": {
39
+ "type": "string",
40
+ "minLength": 1,
41
+ "maxLength": 100
42
+ },
38
43
  "command": {
39
44
  "type": "string",
40
45
  "minLength": 1,
@@ -4,10 +4,16 @@
4
4
  "title": "Mano Coding Registry Entry",
5
5
  "type": "object",
6
6
  "additionalProperties": true,
7
- "required": ["metadata", "releases"],
7
+ "required": ["releases"],
8
8
  "properties": {
9
+ "apiVersion": { "type": "string" },
9
10
  "kind": { "type": "string" },
11
+ "id": { "$ref": "#/$defs/packageName" },
12
+ "name": { "type": "string", "minLength": 1, "maxLength": 80 },
13
+ "displayName": { "type": "string", "minLength": 1, "maxLength": 80 },
14
+ "description": { "type": "string", "maxLength": 500 },
10
15
  "metadata": { "$ref": "#/$defs/metadata" },
16
+ "channels": { "type": "object" },
11
17
  "releases": {
12
18
  "type": "array",
13
19
  "minItems": 1,