@xano/cli 0.0.95-beta.2 → 0.0.95-beta.20

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 (100) hide show
  1. package/README.md +22 -12
  2. package/dist/base-command.d.ts +30 -0
  3. package/dist/base-command.js +61 -0
  4. package/dist/commands/auth/index.js +1 -1
  5. package/dist/commands/branch/create/index.d.ts +3 -1
  6. package/dist/commands/branch/create/index.js +21 -17
  7. package/dist/commands/profile/create/index.js +2 -2
  8. package/dist/commands/profile/edit/index.js +2 -2
  9. package/dist/commands/profile/me/index.js +21 -2
  10. package/dist/commands/profile/wizard/index.js +3 -3
  11. package/dist/commands/profile/workspace/set/index.js +1 -1
  12. package/dist/commands/{ephemeral → sandbox}/delete/index.d.ts +1 -5
  13. package/dist/commands/sandbox/delete/index.js +71 -0
  14. package/dist/commands/{ephemeral → sandbox}/env/delete/index.d.ts +1 -4
  15. package/dist/commands/{ephemeral → sandbox}/env/delete/index.js +20 -36
  16. package/dist/commands/{ephemeral → sandbox}/env/get/index.d.ts +1 -4
  17. package/dist/commands/sandbox/env/get/index.js +65 -0
  18. package/dist/commands/{ephemeral → sandbox}/env/get_all/index.d.ts +1 -4
  19. package/dist/commands/sandbox/env/get_all/index.js +78 -0
  20. package/dist/commands/{ephemeral → sandbox}/env/list/index.d.ts +1 -4
  21. package/dist/commands/sandbox/env/list/index.js +67 -0
  22. package/dist/commands/{ephemeral → sandbox}/env/set/index.d.ts +1 -4
  23. package/dist/commands/sandbox/env/set/index.js +74 -0
  24. package/dist/commands/{ephemeral → sandbox}/env/set_all/index.d.ts +1 -4
  25. package/dist/commands/{ephemeral → sandbox}/env/set_all/index.js +19 -35
  26. package/dist/commands/{ephemeral → sandbox}/get/index.d.ts +1 -4
  27. package/dist/commands/sandbox/get/index.js +63 -0
  28. package/dist/commands/sandbox/impersonate/index.d.ts +5 -0
  29. package/dist/commands/sandbox/impersonate/index.js +5 -0
  30. package/dist/commands/{ephemeral → sandbox}/license/get/index.d.ts +1 -4
  31. package/dist/commands/sandbox/license/get/index.js +78 -0
  32. package/dist/commands/{ephemeral → sandbox}/license/set/index.d.ts +1 -4
  33. package/dist/commands/{ephemeral → sandbox}/license/set/index.js +20 -36
  34. package/dist/commands/{ephemeral → sandbox}/pull/index.d.ts +1 -2
  35. package/dist/commands/{ephemeral → sandbox}/pull/index.js +13 -28
  36. package/dist/commands/{ephemeral → sandbox}/push/index.d.ts +3 -2
  37. package/dist/commands/{ephemeral → sandbox}/push/index.js +56 -31
  38. package/dist/commands/sandbox/reset/index.d.ts +12 -0
  39. package/dist/commands/sandbox/reset/index.js +71 -0
  40. package/dist/commands/{ephemeral/impersonate → sandbox/review}/index.d.ts +1 -4
  41. package/dist/commands/{ephemeral/impersonate → sandbox/review}/index.js +17 -33
  42. package/dist/commands/{ephemeral/unit_test/run_all → sandbox/unit_test/list}/index.d.ts +1 -2
  43. package/dist/commands/{ephemeral → sandbox}/unit_test/list/index.js +12 -26
  44. package/dist/commands/{ephemeral → sandbox}/unit_test/run/index.d.ts +1 -2
  45. package/dist/commands/{ephemeral → sandbox}/unit_test/run/index.js +11 -25
  46. package/dist/commands/{ephemeral/unit_test/list → sandbox/unit_test/run_all}/index.d.ts +1 -2
  47. package/dist/commands/{ephemeral → sandbox}/unit_test/run_all/index.js +11 -23
  48. package/dist/commands/{ephemeral/workflow_test/run_all → sandbox/workflow_test/list}/index.d.ts +1 -2
  49. package/dist/commands/{ephemeral → sandbox}/workflow_test/list/index.js +13 -27
  50. package/dist/commands/{ephemeral/workflow_test/get → sandbox/workflow_test/run}/index.d.ts +1 -2
  51. package/dist/commands/{ephemeral → sandbox}/workflow_test/run/index.js +11 -25
  52. package/dist/commands/{ephemeral/workflow_test/list → sandbox/workflow_test/run_all}/index.d.ts +1 -2
  53. package/dist/commands/{ephemeral → sandbox}/workflow_test/run_all/index.js +11 -23
  54. package/dist/commands/tenant/create/index.d.ts +2 -1
  55. package/dist/commands/tenant/create/index.js +23 -6
  56. package/dist/commands/tenant/deploy_release/index.d.ts +1 -0
  57. package/dist/commands/tenant/deploy_release/index.js +9 -1
  58. package/dist/commands/tenant/get/index.js +2 -2
  59. package/dist/commands/tenant/list/index.js +2 -2
  60. package/dist/commands/tenant/push/index.js +0 -34
  61. package/dist/commands/tenant/unit_test/list/index.js +2 -27
  62. package/dist/commands/tenant/unit_test/run/index.js +2 -27
  63. package/dist/commands/tenant/unit_test/run_all/index.js +2 -27
  64. package/dist/commands/tenant/workflow_test/list/index.js +2 -27
  65. package/dist/commands/tenant/workflow_test/run/index.js +2 -27
  66. package/dist/commands/tenant/workflow_test/run_all/index.js +2 -27
  67. package/dist/commands/workspace/edit/index.d.ts +1 -0
  68. package/dist/commands/workspace/edit/index.js +16 -6
  69. package/dist/commands/workspace/get/index.js +9 -7
  70. package/dist/commands/workspace/list/index.d.ts +1 -0
  71. package/dist/commands/workspace/list/index.js +14 -7
  72. package/dist/commands/workspace/push/index.d.ts +2 -0
  73. package/dist/commands/workspace/push/index.js +81 -6
  74. package/dist/utils/reference-checker.d.ts +57 -0
  75. package/dist/utils/reference-checker.js +232 -0
  76. package/oclif.manifest.json +1745 -2451
  77. package/package.json +8 -8
  78. package/dist/commands/ephemeral/access/index.d.ts +0 -15
  79. package/dist/commands/ephemeral/access/index.js +0 -78
  80. package/dist/commands/ephemeral/create/index.d.ts +0 -17
  81. package/dist/commands/ephemeral/create/index.js +0 -102
  82. package/dist/commands/ephemeral/delete/index.js +0 -99
  83. package/dist/commands/ephemeral/env/get/index.js +0 -81
  84. package/dist/commands/ephemeral/env/get_all/index.js +0 -94
  85. package/dist/commands/ephemeral/env/list/index.js +0 -83
  86. package/dist/commands/ephemeral/env/set/index.js +0 -90
  87. package/dist/commands/ephemeral/get/index.js +0 -102
  88. package/dist/commands/ephemeral/license/get/index.js +0 -94
  89. package/dist/commands/ephemeral/list/index.d.ts +0 -15
  90. package/dist/commands/ephemeral/list/index.js +0 -109
  91. package/dist/commands/ephemeral/shared/index.d.ts +0 -15
  92. package/dist/commands/ephemeral/shared/index.js +0 -108
  93. package/dist/commands/ephemeral/workflow_test/delete/index.d.ts +0 -18
  94. package/dist/commands/ephemeral/workflow_test/delete/index.js +0 -75
  95. package/dist/commands/ephemeral/workflow_test/get/index.js +0 -77
  96. package/dist/commands/ephemeral/workflow_test/run/index.d.ts +0 -18
  97. package/dist/commands/tenant/workflow_test/delete/index.d.ts +0 -19
  98. package/dist/commands/tenant/workflow_test/delete/index.js +0 -110
  99. package/dist/commands/tenant/workflow_test/get/index.d.ts +0 -19
  100. package/dist/commands/tenant/workflow_test/get/index.js +0 -112
@@ -0,0 +1,65 @@
1
+ import { Flags } from '@oclif/core';
2
+ import BaseCommand from '../../../../base-command.js';
3
+ export default class SandboxEnvGet extends BaseCommand {
4
+ static description = 'Get a single environment variable for a sandbox environment';
5
+ static examples = [
6
+ `$ xano sandbox env get --name DATABASE_URL
7
+ postgres://localhost:5432/mydb
8
+ `,
9
+ `$ xano sandbox env get --name DATABASE_URL -o json`,
10
+ ];
11
+ static flags = {
12
+ ...BaseCommand.baseFlags,
13
+ name: Flags.string({
14
+ char: 'n',
15
+ description: 'Environment variable name',
16
+ required: true,
17
+ }),
18
+ output: Flags.string({
19
+ char: 'o',
20
+ default: 'summary',
21
+ description: 'Output format',
22
+ options: ['summary', 'json'],
23
+ required: false,
24
+ }),
25
+ };
26
+ async run() {
27
+ const { flags } = await this.parse(SandboxEnvGet);
28
+ const { profile } = this.resolveProfile(flags);
29
+ const envName = flags.name;
30
+ const apiUrl = `${profile.instance_origin}/api:meta/sandbox/env/${envName}`;
31
+ try {
32
+ const response = await this.verboseFetch(apiUrl, {
33
+ headers: {
34
+ accept: 'application/json',
35
+ Authorization: `Bearer ${profile.access_token}`,
36
+ },
37
+ method: 'GET',
38
+ }, flags.verbose, profile.access_token);
39
+ if (!response.ok) {
40
+ const message = await this.parseApiError(response, 'API request failed');
41
+ this.error(message);
42
+ }
43
+ const envVar = (await response.json());
44
+ if (flags.output === 'json') {
45
+ this.log(JSON.stringify(envVar, null, 2));
46
+ }
47
+ else if (envVar) {
48
+ this.log(envVar.value);
49
+ }
50
+ else {
51
+ this.log(`Environment variable '${envName}' not found for sandbox environment`);
52
+ }
53
+ }
54
+ catch (error) {
55
+ if (error instanceof Error && 'oclif' in error)
56
+ throw error;
57
+ if (error instanceof Error) {
58
+ this.error(`Failed to get sandbox environment variable: ${error.message}`);
59
+ }
60
+ else {
61
+ this.error(`Failed to get sandbox environment variable: ${String(error)}`);
62
+ }
63
+ }
64
+ }
65
+ }
@@ -1,8 +1,5 @@
1
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
- };
2
+ export default class SandboxEnvGetAll extends BaseCommand {
6
3
  static description: string;
7
4
  static examples: string[];
8
5
  static flags: {
@@ -0,0 +1,78 @@
1
+ import { Flags } from '@oclif/core';
2
+ import * as yaml from 'js-yaml';
3
+ import * as fs from 'node:fs';
4
+ import * as path from 'node:path';
5
+ import BaseCommand from '../../../../base-command.js';
6
+ export default class SandboxEnvGetAll extends BaseCommand {
7
+ static description = 'Get all environment variables for a sandbox environment and save to a YAML file';
8
+ static examples = [
9
+ `$ xano sandbox env get_all
10
+ Environment variables saved to env_<tenant>.yaml
11
+ `,
12
+ `$ xano sandbox env get_all --file ./my-env.yaml`,
13
+ `$ xano sandbox env get_all --view`,
14
+ `$ xano sandbox env get_all -o json`,
15
+ ];
16
+ static flags = {
17
+ ...BaseCommand.baseFlags,
18
+ file: Flags.string({
19
+ char: 'f',
20
+ description: 'Output file path (default: env_<sandbox_name>.yaml)',
21
+ required: false,
22
+ }),
23
+ output: Flags.string({
24
+ char: 'o',
25
+ default: 'summary',
26
+ description: 'Output format',
27
+ options: ['summary', 'json'],
28
+ required: false,
29
+ }),
30
+ view: Flags.boolean({
31
+ default: false,
32
+ description: 'Print environment variables to stdout instead of saving to file',
33
+ required: false,
34
+ }),
35
+ };
36
+ async run() {
37
+ const { flags } = await this.parse(SandboxEnvGetAll);
38
+ const { profile } = this.resolveProfile(flags);
39
+ const apiUrl = `${profile.instance_origin}/api:meta/sandbox/env_all`;
40
+ try {
41
+ const response = await this.verboseFetch(apiUrl, {
42
+ headers: {
43
+ accept: 'application/json',
44
+ Authorization: `Bearer ${profile.access_token}`,
45
+ },
46
+ method: 'GET',
47
+ }, flags.verbose, profile.access_token);
48
+ if (!response.ok) {
49
+ const message = await this.parseApiError(response, 'API request failed');
50
+ this.error(message);
51
+ }
52
+ const envMap = (await response.json());
53
+ if (flags.output === 'json') {
54
+ this.log(JSON.stringify(envMap, null, 2));
55
+ }
56
+ else if (flags.view) {
57
+ const envYaml = yaml.dump(envMap, { lineWidth: -1, sortKeys: true });
58
+ this.log(envYaml.trimEnd());
59
+ }
60
+ else {
61
+ const filePath = path.resolve(flags.file || `env.yaml`);
62
+ const envYaml = yaml.dump(envMap, { lineWidth: -1, sortKeys: true });
63
+ fs.writeFileSync(filePath, envYaml, 'utf8');
64
+ this.log(`Environment variables saved to ${filePath}`);
65
+ }
66
+ }
67
+ catch (error) {
68
+ if (error instanceof Error && 'oclif' in error)
69
+ throw error;
70
+ if (error instanceof Error) {
71
+ this.error(`Failed to get sandbox environment variables: ${error.message}`);
72
+ }
73
+ else {
74
+ this.error(`Failed to get sandbox environment variables: ${String(error)}`);
75
+ }
76
+ }
77
+ }
78
+ }
@@ -1,8 +1,5 @@
1
1
  import BaseCommand from '../../../../base-command.js';
2
- export default class EphemeralEnvList extends BaseCommand {
3
- static args: {
4
- tenant_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
- };
2
+ export default class SandboxEnvList extends BaseCommand {
6
3
  static description: string;
7
4
  static examples: string[];
8
5
  static flags: {
@@ -0,0 +1,67 @@
1
+ import { Flags } from '@oclif/core';
2
+ import BaseCommand from '../../../../base-command.js';
3
+ export default class SandboxEnvList extends BaseCommand {
4
+ static description = 'List environment variable keys for a sandbox environment';
5
+ static examples = [
6
+ `$ xano sandbox env list
7
+ Environment variables for sandbox environment:
8
+ - DATABASE_URL
9
+ - API_KEY
10
+ `,
11
+ `$ xano sandbox env list -o json`,
12
+ ];
13
+ static flags = {
14
+ ...BaseCommand.baseFlags,
15
+ output: Flags.string({
16
+ char: 'o',
17
+ default: 'summary',
18
+ description: 'Output format',
19
+ options: ['summary', 'json'],
20
+ required: false,
21
+ }),
22
+ };
23
+ async run() {
24
+ const { flags } = await this.parse(SandboxEnvList);
25
+ const { profile } = this.resolveProfile(flags);
26
+ const apiUrl = `${profile.instance_origin}/api:meta/sandbox/env_key`;
27
+ try {
28
+ const response = await this.verboseFetch(apiUrl, {
29
+ headers: {
30
+ accept: 'application/json',
31
+ Authorization: `Bearer ${profile.access_token}`,
32
+ },
33
+ method: 'GET',
34
+ }, flags.verbose, profile.access_token);
35
+ if (!response.ok) {
36
+ const message = await this.parseApiError(response, 'API request failed');
37
+ this.error(message);
38
+ }
39
+ const data = (await response.json());
40
+ if (flags.output === 'json') {
41
+ this.log(JSON.stringify(data, null, 2));
42
+ }
43
+ else {
44
+ const envVars = data.env || [];
45
+ if (envVars.length === 0) {
46
+ this.log(`No environment variables found for sandbox environment`);
47
+ }
48
+ else {
49
+ this.log(`Environment variables for sandbox environment:`);
50
+ for (const envVar of envVars) {
51
+ this.log(` - ${envVar.name}`);
52
+ }
53
+ }
54
+ }
55
+ }
56
+ catch (error) {
57
+ if (error instanceof Error && 'oclif' in error)
58
+ throw error;
59
+ if (error instanceof Error) {
60
+ this.error(`Failed to list sandbox environment variables: ${error.message}`);
61
+ }
62
+ else {
63
+ this.error(`Failed to list sandbox environment variables: ${String(error)}`);
64
+ }
65
+ }
66
+ }
67
+ }
@@ -1,8 +1,5 @@
1
1
  import BaseCommand from '../../../../base-command.js';
2
- export default class EphemeralEnvSet extends BaseCommand {
3
- static args: {
4
- tenant_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
- };
2
+ export default class SandboxEnvSet extends BaseCommand {
6
3
  static description: string;
7
4
  static examples: string[];
8
5
  static flags: {
@@ -0,0 +1,74 @@
1
+ import { Flags } from '@oclif/core';
2
+ import BaseCommand from '../../../../base-command.js';
3
+ export default class SandboxEnvSet extends BaseCommand {
4
+ static description = 'Set (create or update) an environment variable for a sandbox environment';
5
+ static examples = [
6
+ `$ xano sandbox env set --name DATABASE_URL --value postgres://localhost:5432/mydb
7
+ Environment variable 'DATABASE_URL' set
8
+ `,
9
+ `$ xano sandbox env set --name DATABASE_URL --value postgres://localhost:5432/mydb -o json`,
10
+ ];
11
+ static flags = {
12
+ ...BaseCommand.baseFlags,
13
+ name: Flags.string({
14
+ char: 'n',
15
+ description: 'Environment variable name',
16
+ required: true,
17
+ }),
18
+ output: Flags.string({
19
+ char: 'o',
20
+ default: 'summary',
21
+ description: 'Output format',
22
+ options: ['summary', 'json'],
23
+ required: false,
24
+ }),
25
+ value: Flags.string({
26
+ description: 'Environment variable value',
27
+ required: true,
28
+ }),
29
+ };
30
+ async run() {
31
+ const { flags } = await this.parse(SandboxEnvSet);
32
+ const { profile } = this.resolveProfile(flags);
33
+ const envName = flags.name;
34
+ const apiUrl = `${profile.instance_origin}/api:meta/sandbox/env/${envName}`;
35
+ const body = {
36
+ env: {
37
+ name: envName,
38
+ value: flags.value,
39
+ },
40
+ };
41
+ try {
42
+ const response = await this.verboseFetch(apiUrl, {
43
+ body: JSON.stringify(body),
44
+ headers: {
45
+ accept: 'application/json',
46
+ Authorization: `Bearer ${profile.access_token}`,
47
+ 'Content-Type': 'application/json',
48
+ },
49
+ method: 'PATCH',
50
+ }, flags.verbose, profile.access_token);
51
+ if (!response.ok) {
52
+ const message = await this.parseApiError(response, 'API request failed');
53
+ this.error(message);
54
+ }
55
+ if (flags.output === 'json') {
56
+ const result = await response.json();
57
+ this.log(JSON.stringify(result, null, 2));
58
+ }
59
+ else {
60
+ this.log(`Environment variable '${envName}' set for sandbox environment`);
61
+ }
62
+ }
63
+ catch (error) {
64
+ if (error instanceof Error && 'oclif' in error)
65
+ throw error;
66
+ if (error instanceof Error) {
67
+ this.error(`Failed to set sandbox environment variable: ${error.message}`);
68
+ }
69
+ else {
70
+ this.error(`Failed to set sandbox environment variable: ${String(error)}`);
71
+ }
72
+ }
73
+ }
74
+ }
@@ -1,8 +1,5 @@
1
1
  import BaseCommand from '../../../../base-command.js';
2
- export default class EphemeralEnvSetAll extends BaseCommand {
3
- static args: {
4
- tenant_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
- };
2
+ export default class SandboxEnvSetAll extends BaseCommand {
6
3
  static description: string;
7
4
  static examples: string[];
8
5
  static flags: {
@@ -1,22 +1,16 @@
1
- import { Args, Flags } from '@oclif/core';
1
+ import { Flags } from '@oclif/core';
2
2
  import * as yaml from 'js-yaml';
3
3
  import * as fs from 'node:fs';
4
4
  import * as path from 'node:path';
5
5
  import BaseCommand from '../../../../base-command.js';
6
- export default class EphemeralEnvSetAll extends BaseCommand {
7
- static args = {
8
- tenant_name: Args.string({
9
- description: 'Ephemeral tenant name',
10
- required: true,
11
- }),
12
- };
13
- static description = 'Set all environment variables for an ephemeral tenant from a YAML file (replaces all existing)';
6
+ export default class SandboxEnvSetAll extends BaseCommand {
7
+ static description = 'Set all environment variables for a sandbox environment from a YAML file (replaces all existing)';
14
8
  static examples = [
15
- `$ xano ephemeral env set_all my-tenant
16
- Reads from env_my-tenant.yaml
9
+ `$ xano sandbox env set_all
10
+ Reads from env_<tenant>.yaml
17
11
  `,
18
- `$ xano ephemeral env set_all my-tenant --file ./my-env.yaml`,
19
- `$ xano ephemeral env set_all my-tenant -o json`,
12
+ `$ xano sandbox env set_all --file ./my-env.yaml`,
13
+ `$ xano sandbox env set_all -o json`,
20
14
  ];
21
15
  static flags = {
22
16
  ...BaseCommand.baseFlags,
@@ -27,7 +21,7 @@ Reads from env_my-tenant.yaml
27
21
  }),
28
22
  file: Flags.string({
29
23
  char: 'f',
30
- description: 'Path to env file (default: env_<tenant_name>.yaml)',
24
+ description: 'Path to env file (default: env_<sandbox_name>.yaml)',
31
25
  required: false,
32
26
  }),
33
27
  output: Flags.string({
@@ -39,9 +33,9 @@ Reads from env_my-tenant.yaml
39
33
  }),
40
34
  };
41
35
  async run() {
42
- const { args, flags } = await this.parse(EphemeralEnvSetAll);
43
- const tenantName = args.tenant_name;
44
- const sourceFilePath = path.resolve(flags.file || `env_${tenantName}.yaml`);
36
+ const { flags } = await this.parse(SandboxEnvSetAll);
37
+ const { profile } = this.resolveProfile(flags);
38
+ const sourceFilePath = path.resolve(flags.file || `env.yaml`);
45
39
  if (!fs.existsSync(sourceFilePath)) {
46
40
  this.error(`File not found: ${sourceFilePath}`);
47
41
  }
@@ -51,19 +45,7 @@ Reads from env_my-tenant.yaml
51
45
  this.error('Invalid env file format. Expected a YAML map of key: value pairs.');
52
46
  }
53
47
  const envs = Object.entries(envMap).map(([name, value]) => ({ name, value: String(value) }));
54
- const profileName = flags.profile || this.getDefaultProfile();
55
- const credentials = this.loadCredentialsFile();
56
- if (!credentials || !(profileName in credentials.profiles)) {
57
- this.error(`Profile '${profileName}' not found.\n` + `Create a profile using 'xano profile create'`);
58
- }
59
- const profile = credentials.profiles[profileName];
60
- if (!profile.instance_origin) {
61
- this.error(`Profile '${profileName}' is missing instance_origin`);
62
- }
63
- if (!profile.access_token) {
64
- this.error(`Profile '${profileName}' is missing access_token`);
65
- }
66
- const apiUrl = `${profile.instance_origin}/api:meta/ephemeral/tenant/${tenantName}/env_all`;
48
+ const apiUrl = `${profile.instance_origin}/api:meta/sandbox/env_all`;
67
49
  try {
68
50
  const response = await this.verboseFetch(apiUrl, {
69
51
  body: JSON.stringify({ envs }),
@@ -75,15 +57,15 @@ Reads from env_my-tenant.yaml
75
57
  method: 'PUT',
76
58
  }, flags.verbose, profile.access_token);
77
59
  if (!response.ok) {
78
- const errorText = await response.text();
79
- this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
60
+ const message = await this.parseApiError(response, 'API request failed');
61
+ this.error(message);
80
62
  }
81
63
  if (flags.output === 'json') {
82
64
  const result = await response.json();
83
65
  this.log(JSON.stringify(result, null, 2));
84
66
  }
85
67
  else {
86
- this.log(`All environment variables updated for ephemeral tenant ${tenantName} (${envs.length} variables)`);
68
+ this.log(`All environment variables updated for sandbox environment (${envs.length} variables)`);
87
69
  }
88
70
  if (flags.clean && fs.existsSync(sourceFilePath)) {
89
71
  fs.unlinkSync(sourceFilePath);
@@ -91,11 +73,13 @@ Reads from env_my-tenant.yaml
91
73
  }
92
74
  }
93
75
  catch (error) {
76
+ if (error instanceof Error && 'oclif' in error)
77
+ throw error;
94
78
  if (error instanceof Error) {
95
- this.error(`Failed to set ephemeral tenant environment variables: ${error.message}`);
79
+ this.error(`Failed to set sandbox environment variables: ${error.message}`);
96
80
  }
97
81
  else {
98
- this.error(`Failed to set ephemeral tenant environment variables: ${String(error)}`);
82
+ this.error(`Failed to set sandbox environment variables: ${String(error)}`);
99
83
  }
100
84
  }
101
85
  }
@@ -1,8 +1,5 @@
1
1
  import BaseCommand from '../../../base-command.js';
2
- export default class EphemeralGet extends BaseCommand {
3
- static args: {
4
- tenant_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
- };
2
+ export default class SandboxGet extends BaseCommand {
6
3
  static description: string;
7
4
  static examples: string[];
8
5
  static flags: {
@@ -0,0 +1,63 @@
1
+ import { Flags } from '@oclif/core';
2
+ import BaseCommand from '../../../base-command.js';
3
+ export default class SandboxGet extends BaseCommand {
4
+ static description = 'Get your sandbox environment (creates one if it does not exist)';
5
+ static examples = [
6
+ `$ xano sandbox get
7
+ Sandbox Environment: (tc24-abcd-x1y2)
8
+ State: ok
9
+ License: tier1
10
+ `,
11
+ `$ xano sandbox get -o json`,
12
+ ];
13
+ static flags = {
14
+ ...BaseCommand.baseFlags,
15
+ output: Flags.string({
16
+ char: 'o',
17
+ default: 'summary',
18
+ description: 'Output format',
19
+ options: ['summary', 'json'],
20
+ required: false,
21
+ }),
22
+ };
23
+ async run() {
24
+ const { flags } = await this.parse(SandboxGet);
25
+ const { profile } = this.resolveProfile(flags);
26
+ try {
27
+ const tenant = await this.getOrCreateSandbox(profile, flags.verbose);
28
+ if (flags.output === 'json') {
29
+ this.log(JSON.stringify(tenant, null, 2));
30
+ }
31
+ else {
32
+ this.log(`Sandbox Environment: ${tenant.display || tenant.name} (${tenant.name})`);
33
+ if (tenant.state)
34
+ this.log(` State: ${tenant.state}`);
35
+ if (tenant.xano_domain)
36
+ this.log(` Domain: ${tenant.xano_domain}`);
37
+ if (tenant.sandbox_expires_at) {
38
+ const expiresAt = new Date(tenant.sandbox_expires_at);
39
+ if (!isNaN(expiresAt.getTime())) {
40
+ const msLeft = expiresAt.getTime() - Date.now();
41
+ if (msLeft > 0) {
42
+ const minsLeft = Math.ceil(msLeft / 60_000);
43
+ this.log(` Session expires: ${expiresAt.toLocaleString()} (${minsLeft} min remaining)`);
44
+ }
45
+ else {
46
+ this.log(` Session expires: ${expiresAt.toLocaleString()} (expired)`);
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ catch (error) {
53
+ if (error instanceof Error && 'oclif' in error)
54
+ throw error;
55
+ if (error instanceof Error) {
56
+ this.error(`Failed to get sandbox environment: ${error.message}`);
57
+ }
58
+ else {
59
+ this.error(`Failed to get sandbox environment: ${String(error)}`);
60
+ }
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,5 @@
1
+ import SandboxReview from '../review/index.js';
2
+ export default class SandboxImpersonate extends SandboxReview {
3
+ static description: string;
4
+ static hidden: boolean;
5
+ }
@@ -0,0 +1,5 @@
1
+ import SandboxReview from '../review/index.js';
2
+ export default class SandboxImpersonate extends SandboxReview {
3
+ static description = 'Alias for "sandbox review"';
4
+ static hidden = true;
5
+ }
@@ -1,8 +1,5 @@
1
1
  import BaseCommand from '../../../../base-command.js';
2
- export default class EphemeralLicenseGet extends BaseCommand {
3
- static args: {
4
- tenant_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
- };
2
+ export default class SandboxLicenseGet extends BaseCommand {
6
3
  static description: string;
7
4
  static examples: string[];
8
5
  static flags: {
@@ -0,0 +1,78 @@
1
+ import { Flags } from '@oclif/core';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import BaseCommand from '../../../../base-command.js';
5
+ export default class SandboxLicenseGet extends BaseCommand {
6
+ static description = 'Get the license for a sandbox environment';
7
+ static examples = [
8
+ `$ xano sandbox license get
9
+ License saved to license_<tenant>.yaml
10
+ `,
11
+ `$ xano sandbox license get --file ./my-license.yaml`,
12
+ `$ xano sandbox license get --view`,
13
+ `$ xano sandbox license get -o json`,
14
+ ];
15
+ static flags = {
16
+ ...BaseCommand.baseFlags,
17
+ file: Flags.string({
18
+ char: 'f',
19
+ description: 'Output file path (default: license_<sandbox_name>.yaml)',
20
+ required: false,
21
+ }),
22
+ output: Flags.string({
23
+ char: 'o',
24
+ default: 'summary',
25
+ description: 'Output format',
26
+ options: ['summary', 'json'],
27
+ required: false,
28
+ }),
29
+ view: Flags.boolean({
30
+ default: false,
31
+ description: 'Print license to stdout instead of saving to file',
32
+ required: false,
33
+ }),
34
+ };
35
+ async run() {
36
+ const { flags } = await this.parse(SandboxLicenseGet);
37
+ const { profile } = this.resolveProfile(flags);
38
+ const apiUrl = `${profile.instance_origin}/api:meta/sandbox/license`;
39
+ try {
40
+ const response = await this.verboseFetch(apiUrl, {
41
+ headers: {
42
+ accept: 'application/json',
43
+ Authorization: `Bearer ${profile.access_token}`,
44
+ },
45
+ method: 'GET',
46
+ }, flags.verbose, profile.access_token);
47
+ if (!response.ok) {
48
+ const message = await this.parseApiError(response, 'API request failed');
49
+ this.error(message);
50
+ }
51
+ const license = await response.json();
52
+ const licenseContent = typeof license === 'string' ? license : JSON.stringify(license, null, 2);
53
+ if (flags.view || flags.output === 'json') {
54
+ if (flags.output === 'json') {
55
+ this.log(JSON.stringify(license, null, 2));
56
+ }
57
+ else {
58
+ this.log(licenseContent);
59
+ }
60
+ }
61
+ else {
62
+ const filePath = path.resolve(flags.file || `license.yaml`);
63
+ fs.writeFileSync(filePath, licenseContent, 'utf8');
64
+ this.log(`License saved to ${filePath}`);
65
+ }
66
+ }
67
+ catch (error) {
68
+ if (error instanceof Error && 'oclif' in error)
69
+ throw error;
70
+ if (error instanceof Error) {
71
+ this.error(`Failed to get sandbox environment license: ${error.message}`);
72
+ }
73
+ else {
74
+ this.error(`Failed to get sandbox environment license: ${String(error)}`);
75
+ }
76
+ }
77
+ }
78
+ }
@@ -1,8 +1,5 @@
1
1
  import BaseCommand from '../../../../base-command.js';
2
- export default class EphemeralLicenseSet extends BaseCommand {
3
- static args: {
4
- tenant_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
- };
2
+ export default class SandboxLicenseSet extends BaseCommand {
6
3
  static description: string;
7
4
  static examples: string[];
8
5
  static flags: {