sealos-cli 1.1.2 → 1.1.3

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
@@ -117,6 +117,7 @@ sealos-cli logout
117
117
 
118
118
  ```bash
119
119
  # Deploy from the catalog
120
+ sealos-cli template deploy rybbit
120
121
  sealos-cli template deploy perplexica --name my-app --set OPENAI_API_KEY=xxx
121
122
 
122
123
  # Validate raw template YAML without creating resources
@@ -202,6 +203,8 @@ sealos-cli database restart my-db
202
203
  sealos-cli database backup my-db --name manual-backup
203
204
  sealos-cli database backups my-db
204
205
  sealos-cli database restore my-db --from manual-backup --name restored-db
206
+ sealos-cli database expose my-db
207
+ sealos-cli database unexpose my-db
205
208
  sealos-cli database enable-public my-db
206
209
  sealos-cli database disable-public my-db
207
210
  sealos-cli database log-files <pod-name> --db-type postgresql --log-type runtimeLog
package/dist/bin/cli.cjs CHANGED
@@ -5535,6 +5535,40 @@ function normalizeDatabaseType(type) {
5535
5535
  return resolved;
5536
5536
  }
5537
5537
  __name(normalizeDatabaseType, "normalizeDatabaseType");
5538
+ function getDatabaseConnectScheme(type) {
5539
+ const databaseType = normalizeDatabaseType(type);
5540
+ const schemes = {
5541
+ postgresql: "postgresql",
5542
+ mongodb: "mongodb",
5543
+ "apecloud-mysql": "mysql",
5544
+ mysql: "mysql",
5545
+ redis: "redis",
5546
+ kafka: "kafka",
5547
+ qdrant: "qdrant",
5548
+ nebula: "nebula",
5549
+ weaviate: "weaviate",
5550
+ milvus: "milvus",
5551
+ pulsar: "pulsar",
5552
+ clickhouse: "clickhouse"
5553
+ };
5554
+ return schemes[databaseType];
5555
+ }
5556
+ __name(getDatabaseConnectScheme, "getDatabaseConnectScheme");
5557
+ function buildConsolePublicConnection(options) {
5558
+ if (!options.domain || !options.nodePort) return null;
5559
+ const scheme = getDatabaseConnectScheme(options.dbType);
5560
+ const port = String(options.nodePort);
5561
+ if (scheme === "kafka" || scheme === "milvus") {
5562
+ return `${options.domain}:${port}`;
5563
+ }
5564
+ if (!options.username || !options.password) return null;
5565
+ let connection = `${scheme}://${options.username}:${options.password}@${options.domain}:${port}`;
5566
+ if (scheme === "mongodb" || scheme === "postgresql") {
5567
+ connection += "/?directConnection=true";
5568
+ }
5569
+ return connection;
5570
+ }
5571
+ __name(buildConsolePublicConnection, "buildConsolePublicConnection");
5538
5572
  function normalizeLogDbType(type) {
5539
5573
  const normalized = normalizeDatabaseType(type);
5540
5574
  if (!SUPPORTED_LOG_DB_TYPES.includes(normalized)) {
@@ -5703,6 +5737,86 @@ function printConnectionDetail(connection) {
5703
5737
  outputTable(rows);
5704
5738
  }
5705
5739
  __name(printConnectionDetail, "printConnectionDetail");
5740
+ function buildPublicAccessResult(action, name, connection) {
5741
+ return {
5742
+ success: true,
5743
+ action,
5744
+ resource: "database",
5745
+ name,
5746
+ status: action === "enable-public" ? "enabled" : "disabled",
5747
+ publicConnection: connection?.publicConnection ?? null,
5748
+ connection: connection ?? null
5749
+ };
5750
+ }
5751
+ __name(buildPublicAccessResult, "buildPublicAccessResult");
5752
+ function getDatabaseProviderHost() {
5753
+ const override = process.env.SEALOS_DATABASE_HOST?.trim();
5754
+ if (override) {
5755
+ return override.replace(/\/+$/, "");
5756
+ }
5757
+ let authRegion;
5758
+ try {
5759
+ authRegion = loadAuth().region;
5760
+ } catch {
5761
+ authRegion = void 0;
5762
+ }
5763
+ return resolveDbproviderHost(process.env.SEALOS_REGION || authRegion || DEFAULT_SEALOS_REGION);
5764
+ }
5765
+ __name(getDatabaseProviderHost, "getDatabaseProviderHost");
5766
+ async function getLegacyApiData(path, headers) {
5767
+ const url = new URL(path, getDatabaseProviderHost());
5768
+ const response = await fetch(url, {
5769
+ headers: {
5770
+ Authorization: headers.Authorization
5771
+ }
5772
+ });
5773
+ const body = await response.json();
5774
+ if (!response.ok || body.code !== 200) {
5775
+ throw new Error(body.message || `Request failed: ${url.pathname}`);
5776
+ }
5777
+ return body.data;
5778
+ }
5779
+ __name(getLegacyApiData, "getLegacyApiData");
5780
+ async function fetchConsoleConnectionDetails(name, dbType, fallbackConnection, headers) {
5781
+ const [secret, service, config] = await Promise.all([
5782
+ getLegacyApiData(`/api/getSecretByName?dbName=${encodeURIComponent(name)}&dbType=${encodeURIComponent(dbType)}&mock=false`, headers),
5783
+ getLegacyApiData(`/api/getServiceByName?name=${encodeURIComponent(`${name}-export`)}`, headers).catch(() => null),
5784
+ getLegacyApiData("/api/platform/getClientAppConfig", headers).catch(() => null)
5785
+ ]);
5786
+ const nodePort = service?.spec?.ports?.find((port) => port.nodePort)?.nodePort;
5787
+ const publicConnection = buildConsolePublicConnection({
5788
+ dbType,
5789
+ username: secret.username,
5790
+ password: secret.password,
5791
+ domain: config?.domain,
5792
+ nodePort
5793
+ }) ?? fallbackConnection?.publicConnection ?? null;
5794
+ return {
5795
+ privateConnection: {
5796
+ endpoint: `${secret.host}:${secret.port}`,
5797
+ host: secret.host,
5798
+ port: secret.port,
5799
+ username: secret.username,
5800
+ password: secret.password,
5801
+ connectionString: secret.connection
5802
+ },
5803
+ publicConnection
5804
+ };
5805
+ }
5806
+ __name(fetchConsoleConnectionDetails, "fetchConsoleConnectionDetails");
5807
+ async function loadDatabaseConnectionDetails(name, headers) {
5808
+ const client = createDatabaseClient();
5809
+ const { data, error: error2, response } = await client.GET("/databases/{databaseName}", {
5810
+ headers,
5811
+ params: {
5812
+ path: { databaseName: name }
5813
+ }
5814
+ });
5815
+ if (error2) throw mapApiError(response.status, error2);
5816
+ if (!data.type) return data.connection ?? null;
5817
+ return await fetchConsoleConnectionDetails(name, data.type, data.connection, headers);
5818
+ }
5819
+ __name(loadDatabaseConnectionDetails, "loadDatabaseConnectionDetails");
5706
5820
  function createDatabaseCommand() {
5707
5821
  const dbCmd = new import_commander7.Command("database").alias("db").description("Manage databases");
5708
5822
  dbCmd.command("list").description("List databases").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading databases..." }, async (ctx, options) => {
@@ -5832,20 +5946,13 @@ function createDatabaseCommand() {
5832
5946
  printDatabaseDetail(data);
5833
5947
  }));
5834
5948
  dbCmd.command("connection <name>").description("Show database connection details").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading connection details..." }, async (ctx, name, options) => {
5835
- const client = createDatabaseClient();
5836
- const { data, error: error2, response } = await client.GET("/databases/{databaseName}", {
5837
- headers: ctx.auth,
5838
- params: {
5839
- path: { databaseName: name }
5840
- }
5841
- });
5842
- if (error2) throw mapApiError(response.status, error2);
5949
+ const connection = await loadDatabaseConnectionDetails(name, ctx.auth);
5843
5950
  ctx.spinner.stop();
5844
5951
  if (options.output === "json") {
5845
- outputJson(data.connection ?? null);
5952
+ outputJson(connection);
5846
5953
  return;
5847
5954
  }
5848
- printConnectionDetail(data.connection);
5955
+ printConnectionDetail(connection);
5849
5956
  }));
5850
5957
  dbCmd.command("update <name>").description("Update database resources").option("--cpu <cpu>", "CPU cores per replica").option("--memory <memory>", "Memory in GB per replica").option("--storage <storage>", "Storage in GB per replica").option("--replicas <replicas>", "Replica count").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({
5851
5958
  spinnerText: "Updating database..."
@@ -6082,7 +6189,7 @@ function createDatabaseCommand() {
6082
6189
  }
6083
6190
  ctx.spinner.succeed(`Restore requested from backup "${options.from}"`);
6084
6191
  }));
6085
- dbCmd.command("enable-public <name>").description("Enable public access for a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Enabling public access..." }, async (ctx, name, options) => {
6192
+ dbCmd.command("enable-public <name>").alias("expose").description("Enable public access for a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Enabling public access..." }, async (ctx, name, options) => {
6086
6193
  const client = createDatabaseClient();
6087
6194
  const { error: error2, response } = await client.POST("/databases/{databaseName}/enable-public", {
6088
6195
  headers: ctx.auth,
@@ -6091,20 +6198,16 @@ function createDatabaseCommand() {
6091
6198
  }
6092
6199
  });
6093
6200
  if (error2) throw mapApiError(response.status, error2);
6201
+ const connection = await loadDatabaseConnectionDetails(name, ctx.auth);
6094
6202
  if (options.output === "json") {
6095
6203
  ctx.spinner.stop();
6096
- outputJson({
6097
- success: true,
6098
- action: "enable-public",
6099
- resource: "database",
6100
- name,
6101
- status: "enabled"
6102
- });
6204
+ outputJson(buildPublicAccessResult("enable-public", name, connection));
6103
6205
  return;
6104
6206
  }
6105
6207
  ctx.spinner.succeed(`Public access enabled for "${name}"`);
6208
+ printConnectionDetail(connection);
6106
6209
  }));
6107
- dbCmd.command("disable-public <name>").description("Disable public access for a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Disabling public access..." }, async (ctx, name, options) => {
6210
+ dbCmd.command("disable-public <name>").alias("unexpose").description("Disable public access for a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Disabling public access..." }, async (ctx, name, options) => {
6108
6211
  const client = createDatabaseClient();
6109
6212
  const { error: error2, response } = await client.POST("/databases/{databaseName}/disable-public", {
6110
6213
  headers: ctx.auth,
@@ -6115,13 +6218,7 @@ function createDatabaseCommand() {
6115
6218
  if (error2) throw mapApiError(response.status, error2);
6116
6219
  if (options.output === "json") {
6117
6220
  ctx.spinner.stop();
6118
- outputJson({
6119
- success: true,
6120
- action: "disable-public",
6121
- resource: "database",
6122
- name,
6123
- status: "disabled"
6124
- });
6221
+ outputJson(buildPublicAccessResult("disable-public", name));
6125
6222
  return;
6126
6223
  }
6127
6224
  ctx.spinner.succeed(`Public access disabled for "${name}"`);
@@ -6207,6 +6304,22 @@ page=${data.data.metadata.page} total=${data.data.metadata.total} hasMore=${Stri
6207
6304
  }
6208
6305
  outputTable(rows);
6209
6306
  }));
6307
+ dbCmd.command("* [args...]", { hidden: true }).option("-o, --output <format>", "Output format (json|table)", "json").allowUnknownOption().action(async (args, options) => {
6308
+ const [name, operation, ...rest] = args;
6309
+ const aliases = {
6310
+ connection: "connection",
6311
+ connect: "connection",
6312
+ "enable-public": "enable-public",
6313
+ expose: "expose",
6314
+ "disable-public": "disable-public",
6315
+ unexpose: "unexpose"
6316
+ };
6317
+ const command = operation ? aliases[operation] : void 0;
6318
+ if (!name || !command) {
6319
+ throw new Error('Unknown database command. Use "sealos-cli database --help" to list supported commands.');
6320
+ }
6321
+ await dbCmd.parseAsync([command, name, ...rest, "--output", options.output], { from: "user" });
6322
+ });
6210
6323
  return dbCmd;
6211
6324
  }
6212
6325
  __name(createDatabaseCommand, "createDatabaseCommand");
@@ -6253,17 +6366,15 @@ async function resolveYaml(options, spinner2) {
6253
6366
  }
6254
6367
  __name(resolveYaml, "resolveYaml");
6255
6368
  function resolveTemplateDeployMode(template, options, stdinIsTTY = process.stdin.isTTY) {
6256
- const isRaw = !!(options.file || options.yaml || !stdinIsTTY);
6257
- if (template && isRaw) {
6258
- throw new Error("Cannot specify both a template name and --file/--yaml/stdin. Use one or the other.");
6369
+ const hasExplicitRawInput = !!(options.file || options.yaml);
6370
+ const isRaw = hasExplicitRawInput || !template && !stdinIsTTY;
6371
+ if (template && hasExplicitRawInput) {
6372
+ throw new Error("Cannot specify both a template name and --file/--yaml. Use one or the other.");
6259
6373
  }
6260
6374
  if (!template && !isRaw) {
6261
6375
  throw new Error("Provide a template name or use --file/--yaml/stdin to supply raw YAML.");
6262
6376
  }
6263
6377
  if (template) {
6264
- if (!options.name) {
6265
- throw new Error("--name is required when deploying from the template catalog.");
6266
- }
6267
6378
  if (options.dryRun) {
6268
6379
  throw new Error("--dry-run is only supported for raw template deploys (--file, --yaml, or stdin).");
6269
6380
  }
@@ -6274,7 +6385,7 @@ function resolveTemplateDeployMode(template, options, stdinIsTTY = process.stdin
6274
6385
  __name(resolveTemplateDeployMode, "resolveTemplateDeployMode");
6275
6386
  function buildCatalogTemplateDeployBody(template, options) {
6276
6387
  const body = {
6277
- name: options.name,
6388
+ name: options.name ?? template,
6278
6389
  template
6279
6390
  };
6280
6391
  if (options.set.length > 0) {
@@ -6484,9 +6595,10 @@ function createTemplateCommand() {
6484
6595
  }
6485
6596
  ctx.spinner.succeed(`Instance "${instance}" deleted`);
6486
6597
  }));
6487
- tplCmd.command("deploy [template]").description("Deploy a template (from catalog or raw YAML)").option("--name <name>", "Instance name (required when deploying from catalog)").option("--file <path>", "Path to template YAML file").option("--yaml <yaml>", "Template YAML string").option("--set <KEY=VALUE...>", "Set template arguments", (val, prev) => [...prev, val], []).option("--dry-run", "Validate raw template YAML without creating resources").option("-o, --output <format>", "Output format (json|table)", "json").addHelpText("after", `
6598
+ tplCmd.command("deploy [template]").description("Deploy a template (from catalog or raw YAML)").option("--name <name>", "Instance name (defaults to the catalog template name)").option("--file <path>", "Path to template YAML file").option("--yaml <yaml>", "Template YAML string").option("--set <KEY=VALUE...>", "Set template arguments", (val, prev) => [...prev, val], []).option("--dry-run", "Validate raw template YAML without creating resources").option("-o, --output <format>", "Output format (json|table)", "json").addHelpText("after", `
6488
6599
  Examples:
6489
6600
  Catalog:
6601
+ sealos-cli template deploy rybbit
6490
6602
  sealos-cli template deploy perplexica --name my-app --set OPENAI_API_KEY=xxx
6491
6603
 
6492
6604
  Raw:
@@ -6496,8 +6608,12 @@ kind: Template
6496
6608
  ...'
6497
6609
  cat template.yaml | sealos-cli template deploy --dry-run
6498
6610
  `).action(async (template, options) => {
6499
- const mode = resolveTemplateDeployMode(template, options);
6500
- await deployTemplate(template, options, mode);
6611
+ try {
6612
+ const mode = resolveTemplateDeployMode(template, options);
6613
+ await deployTemplate(template, options, mode);
6614
+ } catch (error2) {
6615
+ handleError(error2);
6616
+ }
6501
6617
  });
6502
6618
  return tplCmd;
6503
6619
  }
@@ -6506,7 +6622,7 @@ __name(createTemplateCommand, "createTemplateCommand");
6506
6622
  // package.json
6507
6623
  var package_default = {
6508
6624
  name: "sealos-cli",
6509
- version: "1.1.2",
6625
+ version: "1.1.3",
6510
6626
  description: "Official CLI tool for Sealos Cloud - Manage auth, workspaces, devboxes, databases, and templates",
6511
6627
  types: "dist/main.d.ts",
6512
6628
  type: "module",
package/dist/bin/cli.mjs CHANGED
@@ -5513,6 +5513,40 @@ function normalizeDatabaseType(type) {
5513
5513
  return resolved;
5514
5514
  }
5515
5515
  __name(normalizeDatabaseType, "normalizeDatabaseType");
5516
+ function getDatabaseConnectScheme(type) {
5517
+ const databaseType = normalizeDatabaseType(type);
5518
+ const schemes = {
5519
+ postgresql: "postgresql",
5520
+ mongodb: "mongodb",
5521
+ "apecloud-mysql": "mysql",
5522
+ mysql: "mysql",
5523
+ redis: "redis",
5524
+ kafka: "kafka",
5525
+ qdrant: "qdrant",
5526
+ nebula: "nebula",
5527
+ weaviate: "weaviate",
5528
+ milvus: "milvus",
5529
+ pulsar: "pulsar",
5530
+ clickhouse: "clickhouse"
5531
+ };
5532
+ return schemes[databaseType];
5533
+ }
5534
+ __name(getDatabaseConnectScheme, "getDatabaseConnectScheme");
5535
+ function buildConsolePublicConnection(options) {
5536
+ if (!options.domain || !options.nodePort) return null;
5537
+ const scheme = getDatabaseConnectScheme(options.dbType);
5538
+ const port = String(options.nodePort);
5539
+ if (scheme === "kafka" || scheme === "milvus") {
5540
+ return `${options.domain}:${port}`;
5541
+ }
5542
+ if (!options.username || !options.password) return null;
5543
+ let connection = `${scheme}://${options.username}:${options.password}@${options.domain}:${port}`;
5544
+ if (scheme === "mongodb" || scheme === "postgresql") {
5545
+ connection += "/?directConnection=true";
5546
+ }
5547
+ return connection;
5548
+ }
5549
+ __name(buildConsolePublicConnection, "buildConsolePublicConnection");
5516
5550
  function normalizeLogDbType(type) {
5517
5551
  const normalized = normalizeDatabaseType(type);
5518
5552
  if (!SUPPORTED_LOG_DB_TYPES.includes(normalized)) {
@@ -5681,6 +5715,86 @@ function printConnectionDetail(connection) {
5681
5715
  outputTable(rows);
5682
5716
  }
5683
5717
  __name(printConnectionDetail, "printConnectionDetail");
5718
+ function buildPublicAccessResult(action, name, connection) {
5719
+ return {
5720
+ success: true,
5721
+ action,
5722
+ resource: "database",
5723
+ name,
5724
+ status: action === "enable-public" ? "enabled" : "disabled",
5725
+ publicConnection: connection?.publicConnection ?? null,
5726
+ connection: connection ?? null
5727
+ };
5728
+ }
5729
+ __name(buildPublicAccessResult, "buildPublicAccessResult");
5730
+ function getDatabaseProviderHost() {
5731
+ const override = process.env.SEALOS_DATABASE_HOST?.trim();
5732
+ if (override) {
5733
+ return override.replace(/\/+$/, "");
5734
+ }
5735
+ let authRegion;
5736
+ try {
5737
+ authRegion = loadAuth().region;
5738
+ } catch {
5739
+ authRegion = void 0;
5740
+ }
5741
+ return resolveDbproviderHost(process.env.SEALOS_REGION || authRegion || DEFAULT_SEALOS_REGION);
5742
+ }
5743
+ __name(getDatabaseProviderHost, "getDatabaseProviderHost");
5744
+ async function getLegacyApiData(path, headers) {
5745
+ const url = new URL(path, getDatabaseProviderHost());
5746
+ const response = await fetch(url, {
5747
+ headers: {
5748
+ Authorization: headers.Authorization
5749
+ }
5750
+ });
5751
+ const body = await response.json();
5752
+ if (!response.ok || body.code !== 200) {
5753
+ throw new Error(body.message || `Request failed: ${url.pathname}`);
5754
+ }
5755
+ return body.data;
5756
+ }
5757
+ __name(getLegacyApiData, "getLegacyApiData");
5758
+ async function fetchConsoleConnectionDetails(name, dbType, fallbackConnection, headers) {
5759
+ const [secret, service, config] = await Promise.all([
5760
+ getLegacyApiData(`/api/getSecretByName?dbName=${encodeURIComponent(name)}&dbType=${encodeURIComponent(dbType)}&mock=false`, headers),
5761
+ getLegacyApiData(`/api/getServiceByName?name=${encodeURIComponent(`${name}-export`)}`, headers).catch(() => null),
5762
+ getLegacyApiData("/api/platform/getClientAppConfig", headers).catch(() => null)
5763
+ ]);
5764
+ const nodePort = service?.spec?.ports?.find((port) => port.nodePort)?.nodePort;
5765
+ const publicConnection = buildConsolePublicConnection({
5766
+ dbType,
5767
+ username: secret.username,
5768
+ password: secret.password,
5769
+ domain: config?.domain,
5770
+ nodePort
5771
+ }) ?? fallbackConnection?.publicConnection ?? null;
5772
+ return {
5773
+ privateConnection: {
5774
+ endpoint: `${secret.host}:${secret.port}`,
5775
+ host: secret.host,
5776
+ port: secret.port,
5777
+ username: secret.username,
5778
+ password: secret.password,
5779
+ connectionString: secret.connection
5780
+ },
5781
+ publicConnection
5782
+ };
5783
+ }
5784
+ __name(fetchConsoleConnectionDetails, "fetchConsoleConnectionDetails");
5785
+ async function loadDatabaseConnectionDetails(name, headers) {
5786
+ const client = createDatabaseClient();
5787
+ const { data, error: error2, response } = await client.GET("/databases/{databaseName}", {
5788
+ headers,
5789
+ params: {
5790
+ path: { databaseName: name }
5791
+ }
5792
+ });
5793
+ if (error2) throw mapApiError(response.status, error2);
5794
+ if (!data.type) return data.connection ?? null;
5795
+ return await fetchConsoleConnectionDetails(name, data.type, data.connection, headers);
5796
+ }
5797
+ __name(loadDatabaseConnectionDetails, "loadDatabaseConnectionDetails");
5684
5798
  function createDatabaseCommand() {
5685
5799
  const dbCmd = new Command7("database").alias("db").description("Manage databases");
5686
5800
  dbCmd.command("list").description("List databases").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading databases..." }, async (ctx, options) => {
@@ -5810,20 +5924,13 @@ function createDatabaseCommand() {
5810
5924
  printDatabaseDetail(data);
5811
5925
  }));
5812
5926
  dbCmd.command("connection <name>").description("Show database connection details").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading connection details..." }, async (ctx, name, options) => {
5813
- const client = createDatabaseClient();
5814
- const { data, error: error2, response } = await client.GET("/databases/{databaseName}", {
5815
- headers: ctx.auth,
5816
- params: {
5817
- path: { databaseName: name }
5818
- }
5819
- });
5820
- if (error2) throw mapApiError(response.status, error2);
5927
+ const connection = await loadDatabaseConnectionDetails(name, ctx.auth);
5821
5928
  ctx.spinner.stop();
5822
5929
  if (options.output === "json") {
5823
- outputJson(data.connection ?? null);
5930
+ outputJson(connection);
5824
5931
  return;
5825
5932
  }
5826
- printConnectionDetail(data.connection);
5933
+ printConnectionDetail(connection);
5827
5934
  }));
5828
5935
  dbCmd.command("update <name>").description("Update database resources").option("--cpu <cpu>", "CPU cores per replica").option("--memory <memory>", "Memory in GB per replica").option("--storage <storage>", "Storage in GB per replica").option("--replicas <replicas>", "Replica count").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({
5829
5936
  spinnerText: "Updating database..."
@@ -6060,7 +6167,7 @@ function createDatabaseCommand() {
6060
6167
  }
6061
6168
  ctx.spinner.succeed(`Restore requested from backup "${options.from}"`);
6062
6169
  }));
6063
- dbCmd.command("enable-public <name>").description("Enable public access for a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Enabling public access..." }, async (ctx, name, options) => {
6170
+ dbCmd.command("enable-public <name>").alias("expose").description("Enable public access for a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Enabling public access..." }, async (ctx, name, options) => {
6064
6171
  const client = createDatabaseClient();
6065
6172
  const { error: error2, response } = await client.POST("/databases/{databaseName}/enable-public", {
6066
6173
  headers: ctx.auth,
@@ -6069,20 +6176,16 @@ function createDatabaseCommand() {
6069
6176
  }
6070
6177
  });
6071
6178
  if (error2) throw mapApiError(response.status, error2);
6179
+ const connection = await loadDatabaseConnectionDetails(name, ctx.auth);
6072
6180
  if (options.output === "json") {
6073
6181
  ctx.spinner.stop();
6074
- outputJson({
6075
- success: true,
6076
- action: "enable-public",
6077
- resource: "database",
6078
- name,
6079
- status: "enabled"
6080
- });
6182
+ outputJson(buildPublicAccessResult("enable-public", name, connection));
6081
6183
  return;
6082
6184
  }
6083
6185
  ctx.spinner.succeed(`Public access enabled for "${name}"`);
6186
+ printConnectionDetail(connection);
6084
6187
  }));
6085
- dbCmd.command("disable-public <name>").description("Disable public access for a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Disabling public access..." }, async (ctx, name, options) => {
6188
+ dbCmd.command("disable-public <name>").alias("unexpose").description("Disable public access for a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Disabling public access..." }, async (ctx, name, options) => {
6086
6189
  const client = createDatabaseClient();
6087
6190
  const { error: error2, response } = await client.POST("/databases/{databaseName}/disable-public", {
6088
6191
  headers: ctx.auth,
@@ -6093,13 +6196,7 @@ function createDatabaseCommand() {
6093
6196
  if (error2) throw mapApiError(response.status, error2);
6094
6197
  if (options.output === "json") {
6095
6198
  ctx.spinner.stop();
6096
- outputJson({
6097
- success: true,
6098
- action: "disable-public",
6099
- resource: "database",
6100
- name,
6101
- status: "disabled"
6102
- });
6199
+ outputJson(buildPublicAccessResult("disable-public", name));
6103
6200
  return;
6104
6201
  }
6105
6202
  ctx.spinner.succeed(`Public access disabled for "${name}"`);
@@ -6185,6 +6282,22 @@ page=${data.data.metadata.page} total=${data.data.metadata.total} hasMore=${Stri
6185
6282
  }
6186
6283
  outputTable(rows);
6187
6284
  }));
6285
+ dbCmd.command("* [args...]", { hidden: true }).option("-o, --output <format>", "Output format (json|table)", "json").allowUnknownOption().action(async (args, options) => {
6286
+ const [name, operation, ...rest] = args;
6287
+ const aliases = {
6288
+ connection: "connection",
6289
+ connect: "connection",
6290
+ "enable-public": "enable-public",
6291
+ expose: "expose",
6292
+ "disable-public": "disable-public",
6293
+ unexpose: "unexpose"
6294
+ };
6295
+ const command = operation ? aliases[operation] : void 0;
6296
+ if (!name || !command) {
6297
+ throw new Error('Unknown database command. Use "sealos-cli database --help" to list supported commands.');
6298
+ }
6299
+ await dbCmd.parseAsync([command, name, ...rest, "--output", options.output], { from: "user" });
6300
+ });
6188
6301
  return dbCmd;
6189
6302
  }
6190
6303
  __name(createDatabaseCommand, "createDatabaseCommand");
@@ -6231,17 +6344,15 @@ async function resolveYaml(options, spinner2) {
6231
6344
  }
6232
6345
  __name(resolveYaml, "resolveYaml");
6233
6346
  function resolveTemplateDeployMode(template, options, stdinIsTTY = process.stdin.isTTY) {
6234
- const isRaw = !!(options.file || options.yaml || !stdinIsTTY);
6235
- if (template && isRaw) {
6236
- throw new Error("Cannot specify both a template name and --file/--yaml/stdin. Use one or the other.");
6347
+ const hasExplicitRawInput = !!(options.file || options.yaml);
6348
+ const isRaw = hasExplicitRawInput || !template && !stdinIsTTY;
6349
+ if (template && hasExplicitRawInput) {
6350
+ throw new Error("Cannot specify both a template name and --file/--yaml. Use one or the other.");
6237
6351
  }
6238
6352
  if (!template && !isRaw) {
6239
6353
  throw new Error("Provide a template name or use --file/--yaml/stdin to supply raw YAML.");
6240
6354
  }
6241
6355
  if (template) {
6242
- if (!options.name) {
6243
- throw new Error("--name is required when deploying from the template catalog.");
6244
- }
6245
6356
  if (options.dryRun) {
6246
6357
  throw new Error("--dry-run is only supported for raw template deploys (--file, --yaml, or stdin).");
6247
6358
  }
@@ -6252,7 +6363,7 @@ function resolveTemplateDeployMode(template, options, stdinIsTTY = process.stdin
6252
6363
  __name(resolveTemplateDeployMode, "resolveTemplateDeployMode");
6253
6364
  function buildCatalogTemplateDeployBody(template, options) {
6254
6365
  const body = {
6255
- name: options.name,
6366
+ name: options.name ?? template,
6256
6367
  template
6257
6368
  };
6258
6369
  if (options.set.length > 0) {
@@ -6462,9 +6573,10 @@ function createTemplateCommand() {
6462
6573
  }
6463
6574
  ctx.spinner.succeed(`Instance "${instance}" deleted`);
6464
6575
  }));
6465
- tplCmd.command("deploy [template]").description("Deploy a template (from catalog or raw YAML)").option("--name <name>", "Instance name (required when deploying from catalog)").option("--file <path>", "Path to template YAML file").option("--yaml <yaml>", "Template YAML string").option("--set <KEY=VALUE...>", "Set template arguments", (val, prev) => [...prev, val], []).option("--dry-run", "Validate raw template YAML without creating resources").option("-o, --output <format>", "Output format (json|table)", "json").addHelpText("after", `
6576
+ tplCmd.command("deploy [template]").description("Deploy a template (from catalog or raw YAML)").option("--name <name>", "Instance name (defaults to the catalog template name)").option("--file <path>", "Path to template YAML file").option("--yaml <yaml>", "Template YAML string").option("--set <KEY=VALUE...>", "Set template arguments", (val, prev) => [...prev, val], []).option("--dry-run", "Validate raw template YAML without creating resources").option("-o, --output <format>", "Output format (json|table)", "json").addHelpText("after", `
6466
6577
  Examples:
6467
6578
  Catalog:
6579
+ sealos-cli template deploy rybbit
6468
6580
  sealos-cli template deploy perplexica --name my-app --set OPENAI_API_KEY=xxx
6469
6581
 
6470
6582
  Raw:
@@ -6474,8 +6586,12 @@ kind: Template
6474
6586
  ...'
6475
6587
  cat template.yaml | sealos-cli template deploy --dry-run
6476
6588
  `).action(async (template, options) => {
6477
- const mode = resolveTemplateDeployMode(template, options);
6478
- await deployTemplate(template, options, mode);
6589
+ try {
6590
+ const mode = resolveTemplateDeployMode(template, options);
6591
+ await deployTemplate(template, options, mode);
6592
+ } catch (error2) {
6593
+ handleError(error2);
6594
+ }
6479
6595
  });
6480
6596
  return tplCmd;
6481
6597
  }
@@ -6484,7 +6600,7 @@ __name(createTemplateCommand, "createTemplateCommand");
6484
6600
  // package.json
6485
6601
  var package_default = {
6486
6602
  name: "sealos-cli",
6487
- version: "1.1.2",
6603
+ version: "1.1.3",
6488
6604
  description: "Official CLI tool for Sealos Cloud - Manage auth, workspaces, devboxes, databases, and templates",
6489
6605
  types: "dist/main.d.ts",
6490
6606
  type: "module",