@xano/cli 0.0.94 → 0.0.95-beta.2

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 (76) hide show
  1. package/README.md +19 -0
  2. package/dist/commands/ephemeral/access/index.d.ts +15 -0
  3. package/dist/commands/ephemeral/access/index.js +78 -0
  4. package/dist/commands/ephemeral/create/index.d.ts +17 -0
  5. package/dist/commands/ephemeral/create/index.js +102 -0
  6. package/dist/commands/ephemeral/delete/index.d.ts +16 -0
  7. package/dist/commands/ephemeral/delete/index.js +99 -0
  8. package/dist/commands/ephemeral/env/delete/index.d.ts +17 -0
  9. package/dist/commands/ephemeral/env/delete/index.js +105 -0
  10. package/dist/commands/ephemeral/env/get/index.d.ts +15 -0
  11. package/dist/commands/ephemeral/env/get/index.js +81 -0
  12. package/dist/commands/ephemeral/env/get_all/index.d.ts +16 -0
  13. package/dist/commands/ephemeral/env/get_all/index.js +94 -0
  14. package/dist/commands/ephemeral/env/list/index.d.ts +14 -0
  15. package/dist/commands/ephemeral/env/list/index.js +83 -0
  16. package/dist/commands/ephemeral/env/set/index.d.ts +16 -0
  17. package/dist/commands/ephemeral/env/set/index.js +90 -0
  18. package/dist/commands/ephemeral/env/set_all/index.d.ts +16 -0
  19. package/dist/commands/ephemeral/env/set_all/index.js +102 -0
  20. package/dist/commands/ephemeral/get/index.d.ts +14 -0
  21. package/dist/commands/ephemeral/get/index.js +102 -0
  22. package/dist/commands/ephemeral/impersonate/index.d.ts +16 -0
  23. package/dist/commands/ephemeral/impersonate/index.js +110 -0
  24. package/dist/commands/ephemeral/license/get/index.d.ts +16 -0
  25. package/dist/commands/ephemeral/license/get/index.js +94 -0
  26. package/dist/commands/ephemeral/license/set/index.d.ts +17 -0
  27. package/dist/commands/ephemeral/license/set/index.js +111 -0
  28. package/dist/commands/ephemeral/list/index.d.ts +15 -0
  29. package/dist/commands/ephemeral/list/index.js +109 -0
  30. package/dist/commands/ephemeral/pull/index.d.ts +18 -0
  31. package/dist/commands/ephemeral/pull/index.js +197 -0
  32. package/dist/commands/ephemeral/push/index.d.ts +19 -0
  33. package/dist/commands/ephemeral/push/index.js +158 -0
  34. package/dist/commands/ephemeral/shared/index.d.ts +15 -0
  35. package/dist/commands/ephemeral/shared/index.js +108 -0
  36. package/dist/commands/ephemeral/unit_test/list/index.d.ts +14 -0
  37. package/dist/commands/ephemeral/unit_test/list/index.js +105 -0
  38. package/dist/commands/ephemeral/unit_test/run/index.d.ts +15 -0
  39. package/dist/commands/ephemeral/unit_test/run/index.js +93 -0
  40. package/dist/commands/ephemeral/unit_test/run_all/index.d.ts +14 -0
  41. package/dist/commands/ephemeral/unit_test/run_all/index.js +183 -0
  42. package/dist/commands/ephemeral/workflow_test/delete/index.d.ts +18 -0
  43. package/dist/commands/ephemeral/workflow_test/delete/index.js +75 -0
  44. package/dist/commands/ephemeral/workflow_test/get/index.d.ts +18 -0
  45. package/dist/commands/ephemeral/workflow_test/get/index.js +77 -0
  46. package/dist/commands/ephemeral/workflow_test/list/index.d.ts +13 -0
  47. package/dist/commands/ephemeral/workflow_test/list/index.js +98 -0
  48. package/dist/commands/ephemeral/workflow_test/run/index.d.ts +18 -0
  49. package/dist/commands/ephemeral/workflow_test/run/index.js +91 -0
  50. package/dist/commands/ephemeral/workflow_test/run_all/index.d.ts +13 -0
  51. package/dist/commands/ephemeral/workflow_test/run_all/index.js +169 -0
  52. package/dist/commands/release/deploy/index.d.ts +17 -0
  53. package/dist/commands/release/deploy/index.js +107 -0
  54. package/dist/commands/tenant/create/index.d.ts +0 -1
  55. package/dist/commands/tenant/create/index.js +0 -5
  56. package/dist/commands/tenant/push/index.js +1 -1
  57. package/dist/commands/tenant/unit_test/list/index.d.ts +15 -0
  58. package/dist/commands/tenant/unit_test/list/index.js +140 -0
  59. package/dist/commands/tenant/unit_test/run/index.d.ts +16 -0
  60. package/dist/commands/tenant/unit_test/run/index.js +128 -0
  61. package/dist/commands/tenant/unit_test/run_all/index.d.ts +15 -0
  62. package/dist/commands/tenant/unit_test/run_all/index.js +215 -0
  63. package/dist/commands/tenant/workflow_test/delete/index.d.ts +19 -0
  64. package/dist/commands/tenant/workflow_test/delete/index.js +110 -0
  65. package/dist/commands/tenant/workflow_test/get/index.d.ts +19 -0
  66. package/dist/commands/tenant/workflow_test/get/index.js +112 -0
  67. package/dist/commands/tenant/workflow_test/list/index.d.ts +14 -0
  68. package/dist/commands/tenant/workflow_test/list/index.js +133 -0
  69. package/dist/commands/tenant/workflow_test/run/index.d.ts +19 -0
  70. package/dist/commands/tenant/workflow_test/run/index.js +126 -0
  71. package/dist/commands/tenant/workflow_test/run_all/index.d.ts +14 -0
  72. package/dist/commands/tenant/workflow_test/run_all/index.js +201 -0
  73. package/dist/help.d.ts +2 -1
  74. package/dist/help.js +39 -1
  75. package/oclif.manifest.json +5193 -2303
  76. package/package.json +16 -1
package/README.md CHANGED
@@ -235,6 +235,11 @@ xano release pull ./my-release -r v1.0 --env --records
235
235
  xano release push ./my-release -n "v2.0"
236
236
  xano release push ./my-release -n "v2.0" --hotfix -d "Critical fix"
237
237
  xano release push ./my-release -n "v2.0" --no-records --no-env
238
+
239
+ # Deploy a release to its workspace as a new branch
240
+ xano release deploy "v1.0"
241
+ xano release deploy "v1.0" --branch "restore-v1" --no-set_live
242
+ xano release deploy "v1.0" -w 40 -o json
238
243
  ```
239
244
 
240
245
  ### Platforms
@@ -440,6 +445,20 @@ xano tenant cluster license set <cluster_id>
440
445
  xano tenant cluster license set <cluster_id> --file ./kubeconfig.yaml
441
446
  ```
442
447
 
448
+ ### Ephemeral
449
+
450
+ Manage ephemeral tenants. Ephemeral tenants are workspace-agnostic (tier1 only) and do not run background tasks.
451
+
452
+ ```bash
453
+ # Create an ephemeral tenant
454
+ xano ephemeral create "My Ephemeral"
455
+ xano ephemeral create "CI Tenant" -d "For CI/CD" -o json
456
+
457
+ # Get ephemeral tenant details
458
+ xano ephemeral get <tenant_name>
459
+ xano ephemeral get <tenant_name> -o json
460
+ ```
461
+
443
462
  ### Static Hosts
444
463
 
445
464
  ```bash
@@ -0,0 +1,15 @@
1
+ import BaseCommand from '../../../base-command.js';
2
+ export default class EphemeralAccess extends BaseCommand {
3
+ static args: {
4
+ tenant_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ access: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ static flags: {
10
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ };
14
+ run(): Promise<void>;
15
+ }
@@ -0,0 +1,78 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import BaseCommand from '../../../base-command.js';
3
+ export default class EphemeralAccess extends BaseCommand {
4
+ static args = {
5
+ tenant_name: Args.string({
6
+ description: 'Ephemeral tenant name',
7
+ required: true,
8
+ }),
9
+ access: Args.string({
10
+ description: 'Access level to set',
11
+ options: ['private', 'shared'],
12
+ required: true,
13
+ }),
14
+ };
15
+ static description = 'Change the access level of an ephemeral tenant';
16
+ static examples = [
17
+ `$ xano ephemeral access e1a2-b3c4-x5y6 shared
18
+ Access updated to shared for tenant e1a2-b3c4-x5y6
19
+ `,
20
+ `$ xano ephemeral access e1a2-b3c4-x5y6 private`,
21
+ ];
22
+ static flags = {
23
+ ...BaseCommand.baseFlags,
24
+ output: Flags.string({
25
+ char: 'o',
26
+ default: 'summary',
27
+ description: 'Output format',
28
+ options: ['summary', 'json'],
29
+ required: false,
30
+ }),
31
+ };
32
+ async run() {
33
+ const { args, flags } = await this.parse(EphemeralAccess);
34
+ const profileName = flags.profile || this.getDefaultProfile();
35
+ const credentials = this.loadCredentialsFile();
36
+ if (!credentials || !(profileName in credentials.profiles)) {
37
+ this.error(`Profile '${profileName}' not found.\n` + `Create a profile using 'xano profile create'`);
38
+ }
39
+ const profile = credentials.profiles[profileName];
40
+ if (!profile.instance_origin) {
41
+ this.error(`Profile '${profileName}' is missing instance_origin`);
42
+ }
43
+ if (!profile.access_token) {
44
+ this.error(`Profile '${profileName}' is missing access_token`);
45
+ }
46
+ const apiUrl = `${profile.instance_origin}/api:meta/ephemeral/tenant/${encodeURIComponent(args.tenant_name)}/access`;
47
+ try {
48
+ const response = await this.verboseFetch(apiUrl, {
49
+ body: JSON.stringify({ access: args.access }),
50
+ headers: {
51
+ accept: 'application/json',
52
+ Authorization: `Bearer ${profile.access_token}`,
53
+ 'Content-Type': 'application/json',
54
+ },
55
+ method: 'PATCH',
56
+ }, flags.verbose, profile.access_token);
57
+ if (!response.ok) {
58
+ const errorText = await response.text();
59
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
60
+ }
61
+ const tenant = await response.json();
62
+ if (flags.output === 'json') {
63
+ this.log(JSON.stringify(tenant, null, 2));
64
+ }
65
+ else {
66
+ this.log(`Access updated to ${args.access} for tenant ${args.tenant_name}`);
67
+ }
68
+ }
69
+ catch (error) {
70
+ if (error instanceof Error) {
71
+ this.error(`Failed to update access: ${error.message}`);
72
+ }
73
+ else {
74
+ this.error(`Failed to update access: ${String(error)}`);
75
+ }
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,17 @@
1
+ import BaseCommand from '../../../base-command.js';
2
+ export default class EphemeralCreate extends BaseCommand {
3
+ static args: {
4
+ display: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ access: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ domain: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
+ };
16
+ run(): Promise<void>;
17
+ }
@@ -0,0 +1,102 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import BaseCommand from '../../../base-command.js';
3
+ export default class EphemeralCreate extends BaseCommand {
4
+ static args = {
5
+ display: Args.string({
6
+ description: 'Optional display name for the ephemeral tenant',
7
+ required: false,
8
+ }),
9
+ };
10
+ static description = 'Create an ephemeral tenant (workspace-agnostic, no background tasks)';
11
+ static examples = [
12
+ `$ xano ephemeral create
13
+ Created ephemeral tenant: e1a2-b3c4-x5y6 - ID: 42
14
+ `,
15
+ `$ xano ephemeral create "My Ephemeral"`,
16
+ `$ xano ephemeral create "CI Tenant" -d "For CI/CD" -o json`,
17
+ ];
18
+ static flags = {
19
+ ...BaseCommand.baseFlags,
20
+ access: Flags.string({
21
+ char: 'a',
22
+ default: 'private',
23
+ description: 'Access level (private or shared)',
24
+ options: ['private', 'shared'],
25
+ required: false,
26
+ }),
27
+ description: Flags.string({
28
+ char: 'd',
29
+ description: 'Tenant description',
30
+ required: false,
31
+ }),
32
+ domain: Flags.string({
33
+ description: 'Custom domain for the tenant',
34
+ required: false,
35
+ }),
36
+ output: Flags.string({
37
+ char: 'o',
38
+ default: 'summary',
39
+ description: 'Output format',
40
+ options: ['summary', 'json'],
41
+ required: false,
42
+ }),
43
+ };
44
+ async run() {
45
+ const { args, flags } = await this.parse(EphemeralCreate);
46
+ const profileName = flags.profile || this.getDefaultProfile();
47
+ const credentials = this.loadCredentialsFile();
48
+ if (!credentials || !(profileName in credentials.profiles)) {
49
+ this.error(`Profile '${profileName}' not found.\n` + `Create a profile using 'xano profile create'`);
50
+ }
51
+ const profile = credentials.profiles[profileName];
52
+ if (!profile.instance_origin) {
53
+ this.error(`Profile '${profileName}' is missing instance_origin`);
54
+ }
55
+ if (!profile.access_token) {
56
+ this.error(`Profile '${profileName}' is missing access_token`);
57
+ }
58
+ const body = {
59
+ access: flags.access,
60
+ display: args.display || '',
61
+ tag: [],
62
+ };
63
+ if (flags.description)
64
+ body.description = flags.description;
65
+ if (flags.domain)
66
+ body.domain = flags.domain;
67
+ const apiUrl = `${profile.instance_origin}/api:meta/ephemeral/tenant`;
68
+ try {
69
+ const response = await this.verboseFetch(apiUrl, {
70
+ body: JSON.stringify(body),
71
+ headers: {
72
+ accept: 'application/json',
73
+ Authorization: `Bearer ${profile.access_token}`,
74
+ 'Content-Type': 'application/json',
75
+ },
76
+ method: 'POST',
77
+ }, flags.verbose, profile.access_token);
78
+ if (!response.ok) {
79
+ const errorText = await response.text();
80
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
81
+ }
82
+ const tenant = (await response.json());
83
+ if (flags.output === 'json') {
84
+ this.log(JSON.stringify(tenant, null, 2));
85
+ }
86
+ else {
87
+ this.log(`Created ephemeral tenant: ${tenant.display || tenant.name} (${tenant.name}) - ID: ${tenant.id}`);
88
+ if (tenant.state) {
89
+ this.log(` State: ${tenant.state}`);
90
+ }
91
+ }
92
+ }
93
+ catch (error) {
94
+ if (error instanceof Error) {
95
+ this.error(`Failed to create ephemeral tenant: ${error.message}`);
96
+ }
97
+ else {
98
+ this.error(`Failed to create ephemeral tenant: ${String(error)}`);
99
+ }
100
+ }
101
+ }
102
+ }
@@ -0,0 +1,16 @@
1
+ import BaseCommand from '../../../base-command.js';
2
+ export default class EphemeralDelete extends BaseCommand {
3
+ static args: {
4
+ tenant_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ };
14
+ run(): Promise<void>;
15
+ private confirm;
16
+ }
@@ -0,0 +1,99 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import BaseCommand from '../../../base-command.js';
3
+ export default class EphemeralDelete extends BaseCommand {
4
+ static args = {
5
+ tenant_name: Args.string({
6
+ description: 'Ephemeral tenant name to delete',
7
+ required: true,
8
+ }),
9
+ };
10
+ static description = 'Delete an ephemeral tenant permanently. This cannot be undone.';
11
+ static examples = [
12
+ `$ xano ephemeral delete my-tenant
13
+ Are you sure you want to delete ephemeral tenant my-tenant? This action cannot be undone. (y/N) y
14
+ Deleted ephemeral tenant my-tenant
15
+ `,
16
+ `$ xano ephemeral delete my-tenant --force`,
17
+ `$ xano ephemeral delete my-tenant -f -o json`,
18
+ ];
19
+ static flags = {
20
+ ...BaseCommand.baseFlags,
21
+ force: Flags.boolean({
22
+ char: 'f',
23
+ default: false,
24
+ description: 'Skip confirmation prompt',
25
+ required: false,
26
+ }),
27
+ output: Flags.string({
28
+ char: 'o',
29
+ default: 'summary',
30
+ description: 'Output format',
31
+ options: ['summary', 'json'],
32
+ required: false,
33
+ }),
34
+ };
35
+ async run() {
36
+ const { args, flags } = await this.parse(EphemeralDelete);
37
+ const profileName = flags.profile || this.getDefaultProfile();
38
+ const credentials = this.loadCredentialsFile();
39
+ if (!credentials || !(profileName in credentials.profiles)) {
40
+ this.error(`Profile '${profileName}' not found.\n` + `Create a profile using 'xano profile create'`);
41
+ }
42
+ const profile = credentials.profiles[profileName];
43
+ if (!profile.instance_origin) {
44
+ this.error(`Profile '${profileName}' is missing instance_origin`);
45
+ }
46
+ if (!profile.access_token) {
47
+ this.error(`Profile '${profileName}' is missing access_token`);
48
+ }
49
+ const tenantName = args.tenant_name;
50
+ if (!flags.force) {
51
+ const confirmed = await this.confirm(`Are you sure you want to delete ephemeral tenant ${tenantName}? This action cannot be undone.`);
52
+ if (!confirmed) {
53
+ this.log('Deletion cancelled.');
54
+ return;
55
+ }
56
+ }
57
+ const apiUrl = `${profile.instance_origin}/api:meta/ephemeral/tenant/${encodeURIComponent(tenantName)}`;
58
+ try {
59
+ const response = await this.verboseFetch(apiUrl, {
60
+ headers: {
61
+ accept: 'application/json',
62
+ Authorization: `Bearer ${profile.access_token}`,
63
+ },
64
+ method: 'DELETE',
65
+ }, flags.verbose, profile.access_token);
66
+ if (!response.ok) {
67
+ const errorText = await response.text();
68
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
69
+ }
70
+ if (flags.output === 'json') {
71
+ this.log(JSON.stringify({ deleted: true, tenant_name: tenantName }, null, 2));
72
+ }
73
+ else {
74
+ this.log(`Deleted ephemeral tenant ${tenantName}`);
75
+ }
76
+ }
77
+ catch (error) {
78
+ if (error instanceof Error) {
79
+ this.error(`Failed to delete ephemeral tenant: ${error.message}`);
80
+ }
81
+ else {
82
+ this.error(`Failed to delete ephemeral tenant: ${String(error)}`);
83
+ }
84
+ }
85
+ }
86
+ async confirm(message) {
87
+ const readline = await import('node:readline');
88
+ const rl = readline.createInterface({
89
+ input: process.stdin,
90
+ output: process.stdout,
91
+ });
92
+ return new Promise((resolve) => {
93
+ rl.question(`${message} (y/N) `, (answer) => {
94
+ rl.close();
95
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
96
+ });
97
+ });
98
+ }
99
+ }
@@ -0,0 +1,17 @@
1
+ import BaseCommand from '../../../../base-command.js';
2
+ export default class EphemeralEnvDelete extends BaseCommand {
3
+ static args: {
4
+ tenant_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
12
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ private confirm;
17
+ }
@@ -0,0 +1,105 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import BaseCommand from '../../../../base-command.js';
3
+ export default class EphemeralEnvDelete extends BaseCommand {
4
+ static args = {
5
+ tenant_name: Args.string({
6
+ description: 'Ephemeral tenant name',
7
+ required: true,
8
+ }),
9
+ };
10
+ static description = 'Delete an environment variable from an ephemeral tenant';
11
+ static examples = [
12
+ `$ xano ephemeral env delete my-tenant --name DATABASE_URL
13
+ Are you sure you want to delete environment variable 'DATABASE_URL' from ephemeral tenant my-tenant? (y/N) y
14
+ Environment variable 'DATABASE_URL' deleted from ephemeral tenant my-tenant
15
+ `,
16
+ `$ xano ephemeral env delete my-tenant --name DATABASE_URL --force`,
17
+ `$ xano ephemeral env delete my-tenant --name DATABASE_URL -f -o json`,
18
+ ];
19
+ static flags = {
20
+ ...BaseCommand.baseFlags,
21
+ force: Flags.boolean({
22
+ char: 'f',
23
+ default: false,
24
+ description: 'Skip confirmation prompt',
25
+ required: false,
26
+ }),
27
+ name: Flags.string({
28
+ char: 'n',
29
+ description: 'Environment variable name',
30
+ required: true,
31
+ }),
32
+ output: Flags.string({
33
+ char: 'o',
34
+ default: 'summary',
35
+ description: 'Output format',
36
+ options: ['summary', 'json'],
37
+ required: false,
38
+ }),
39
+ };
40
+ async run() {
41
+ const { args, flags } = await this.parse(EphemeralEnvDelete);
42
+ const profileName = flags.profile || this.getDefaultProfile();
43
+ const credentials = this.loadCredentialsFile();
44
+ if (!credentials || !(profileName in credentials.profiles)) {
45
+ this.error(`Profile '${profileName}' not found.\n` + `Create a profile using 'xano profile create'`);
46
+ }
47
+ const profile = credentials.profiles[profileName];
48
+ if (!profile.instance_origin) {
49
+ this.error(`Profile '${profileName}' is missing instance_origin`);
50
+ }
51
+ if (!profile.access_token) {
52
+ this.error(`Profile '${profileName}' is missing access_token`);
53
+ }
54
+ const tenantName = args.tenant_name;
55
+ const envName = flags.name;
56
+ if (!flags.force) {
57
+ const confirmed = await this.confirm(`Are you sure you want to delete environment variable '${envName}' from ephemeral tenant ${tenantName}?`);
58
+ if (!confirmed) {
59
+ this.log('Deletion cancelled.');
60
+ return;
61
+ }
62
+ }
63
+ const apiUrl = `${profile.instance_origin}/api:meta/ephemeral/tenant/${tenantName}/env/${envName}`;
64
+ try {
65
+ const response = await this.verboseFetch(apiUrl, {
66
+ headers: {
67
+ accept: 'application/json',
68
+ Authorization: `Bearer ${profile.access_token}`,
69
+ },
70
+ method: 'DELETE',
71
+ }, flags.verbose, profile.access_token);
72
+ if (!response.ok) {
73
+ const errorText = await response.text();
74
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
75
+ }
76
+ if (flags.output === 'json') {
77
+ this.log(JSON.stringify({ deleted: true, env_name: envName, tenant_name: tenantName }, null, 2));
78
+ }
79
+ else {
80
+ this.log(`Environment variable '${envName}' deleted from ephemeral tenant ${tenantName}`);
81
+ }
82
+ }
83
+ catch (error) {
84
+ if (error instanceof Error) {
85
+ this.error(`Failed to delete ephemeral tenant environment variable: ${error.message}`);
86
+ }
87
+ else {
88
+ this.error(`Failed to delete ephemeral tenant environment variable: ${String(error)}`);
89
+ }
90
+ }
91
+ }
92
+ async confirm(message) {
93
+ const readline = await import('node:readline');
94
+ const rl = readline.createInterface({
95
+ input: process.stdin,
96
+ output: process.stdout,
97
+ });
98
+ return new Promise((resolve) => {
99
+ rl.question(`${message} (y/N) `, (answer) => {
100
+ rl.close();
101
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
102
+ });
103
+ });
104
+ }
105
+ }
@@ -0,0 +1,15 @@
1
+ import BaseCommand from '../../../../base-command.js';
2
+ export default class EphemeralEnvGet extends BaseCommand {
3
+ static args: {
4
+ tenant_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ };
14
+ run(): Promise<void>;
15
+ }
@@ -0,0 +1,81 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import BaseCommand from '../../../../base-command.js';
3
+ export default class EphemeralEnvGet extends BaseCommand {
4
+ static args = {
5
+ tenant_name: Args.string({
6
+ description: 'Ephemeral tenant name',
7
+ required: true,
8
+ }),
9
+ };
10
+ static description = 'Get a single environment variable for an ephemeral tenant';
11
+ static examples = [
12
+ `$ xano ephemeral env get my-tenant --name DATABASE_URL
13
+ postgres://localhost:5432/mydb
14
+ `,
15
+ `$ xano ephemeral env get my-tenant --name DATABASE_URL -o json`,
16
+ ];
17
+ static flags = {
18
+ ...BaseCommand.baseFlags,
19
+ name: Flags.string({
20
+ char: 'n',
21
+ description: 'Environment variable name',
22
+ required: true,
23
+ }),
24
+ output: Flags.string({
25
+ char: 'o',
26
+ default: 'summary',
27
+ description: 'Output format',
28
+ options: ['summary', 'json'],
29
+ required: false,
30
+ }),
31
+ };
32
+ async run() {
33
+ const { args, flags } = await this.parse(EphemeralEnvGet);
34
+ const profileName = flags.profile || this.getDefaultProfile();
35
+ const credentials = this.loadCredentialsFile();
36
+ if (!credentials || !(profileName in credentials.profiles)) {
37
+ this.error(`Profile '${profileName}' not found.\n` + `Create a profile using 'xano profile create'`);
38
+ }
39
+ const profile = credentials.profiles[profileName];
40
+ if (!profile.instance_origin) {
41
+ this.error(`Profile '${profileName}' is missing instance_origin`);
42
+ }
43
+ if (!profile.access_token) {
44
+ this.error(`Profile '${profileName}' is missing access_token`);
45
+ }
46
+ const tenantName = args.tenant_name;
47
+ const envName = flags.name;
48
+ const apiUrl = `${profile.instance_origin}/api:meta/ephemeral/tenant/${tenantName}/env/${envName}`;
49
+ try {
50
+ const response = await this.verboseFetch(apiUrl, {
51
+ headers: {
52
+ accept: 'application/json',
53
+ Authorization: `Bearer ${profile.access_token}`,
54
+ },
55
+ method: 'GET',
56
+ }, flags.verbose, profile.access_token);
57
+ if (!response.ok) {
58
+ const errorText = await response.text();
59
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
60
+ }
61
+ const envVar = (await response.json());
62
+ if (flags.output === 'json') {
63
+ this.log(JSON.stringify(envVar, null, 2));
64
+ }
65
+ else if (envVar) {
66
+ this.log(envVar.value);
67
+ }
68
+ else {
69
+ this.log(`Environment variable '${envName}' not found for ephemeral tenant ${tenantName}`);
70
+ }
71
+ }
72
+ catch (error) {
73
+ if (error instanceof Error) {
74
+ this.error(`Failed to get ephemeral tenant environment variable: ${error.message}`);
75
+ }
76
+ else {
77
+ this.error(`Failed to get ephemeral tenant environment variable: ${String(error)}`);
78
+ }
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,16 @@
1
+ import BaseCommand from '../../../../base-command.js';
2
+ export default class EphemeralEnvGetAll extends BaseCommand {
3
+ static args: {
4
+ tenant_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ view: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ }