@xano/cli 0.0.95-beta.2 → 0.0.95

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 +2 -20
  2. package/dist/commands/tenant/create/index.d.ts +3 -1
  3. package/dist/commands/tenant/create/index.js +28 -6
  4. package/dist/commands/tenant/push/index.js +1 -1
  5. package/dist/help.d.ts +1 -2
  6. package/dist/help.js +1 -39
  7. package/oclif.manifest.json +2251 -5131
  8. package/package.json +1 -16
  9. package/dist/commands/ephemeral/access/index.d.ts +0 -15
  10. package/dist/commands/ephemeral/access/index.js +0 -78
  11. package/dist/commands/ephemeral/create/index.d.ts +0 -17
  12. package/dist/commands/ephemeral/create/index.js +0 -102
  13. package/dist/commands/ephemeral/delete/index.d.ts +0 -16
  14. package/dist/commands/ephemeral/delete/index.js +0 -99
  15. package/dist/commands/ephemeral/env/delete/index.d.ts +0 -17
  16. package/dist/commands/ephemeral/env/delete/index.js +0 -105
  17. package/dist/commands/ephemeral/env/get/index.d.ts +0 -15
  18. package/dist/commands/ephemeral/env/get/index.js +0 -81
  19. package/dist/commands/ephemeral/env/get_all/index.d.ts +0 -16
  20. package/dist/commands/ephemeral/env/get_all/index.js +0 -94
  21. package/dist/commands/ephemeral/env/list/index.d.ts +0 -14
  22. package/dist/commands/ephemeral/env/list/index.js +0 -83
  23. package/dist/commands/ephemeral/env/set/index.d.ts +0 -16
  24. package/dist/commands/ephemeral/env/set/index.js +0 -90
  25. package/dist/commands/ephemeral/env/set_all/index.d.ts +0 -16
  26. package/dist/commands/ephemeral/env/set_all/index.js +0 -102
  27. package/dist/commands/ephemeral/get/index.d.ts +0 -14
  28. package/dist/commands/ephemeral/get/index.js +0 -102
  29. package/dist/commands/ephemeral/impersonate/index.d.ts +0 -16
  30. package/dist/commands/ephemeral/impersonate/index.js +0 -110
  31. package/dist/commands/ephemeral/license/get/index.d.ts +0 -16
  32. package/dist/commands/ephemeral/license/get/index.js +0 -94
  33. package/dist/commands/ephemeral/license/set/index.d.ts +0 -17
  34. package/dist/commands/ephemeral/license/set/index.js +0 -111
  35. package/dist/commands/ephemeral/list/index.d.ts +0 -15
  36. package/dist/commands/ephemeral/list/index.js +0 -109
  37. package/dist/commands/ephemeral/pull/index.d.ts +0 -18
  38. package/dist/commands/ephemeral/pull/index.js +0 -197
  39. package/dist/commands/ephemeral/push/index.d.ts +0 -19
  40. package/dist/commands/ephemeral/push/index.js +0 -158
  41. package/dist/commands/ephemeral/shared/index.d.ts +0 -15
  42. package/dist/commands/ephemeral/shared/index.js +0 -108
  43. package/dist/commands/ephemeral/unit_test/list/index.d.ts +0 -14
  44. package/dist/commands/ephemeral/unit_test/list/index.js +0 -105
  45. package/dist/commands/ephemeral/unit_test/run/index.d.ts +0 -15
  46. package/dist/commands/ephemeral/unit_test/run/index.js +0 -93
  47. package/dist/commands/ephemeral/unit_test/run_all/index.d.ts +0 -14
  48. package/dist/commands/ephemeral/unit_test/run_all/index.js +0 -183
  49. package/dist/commands/ephemeral/workflow_test/delete/index.d.ts +0 -18
  50. package/dist/commands/ephemeral/workflow_test/delete/index.js +0 -75
  51. package/dist/commands/ephemeral/workflow_test/get/index.d.ts +0 -18
  52. package/dist/commands/ephemeral/workflow_test/get/index.js +0 -77
  53. package/dist/commands/ephemeral/workflow_test/list/index.d.ts +0 -13
  54. package/dist/commands/ephemeral/workflow_test/list/index.js +0 -98
  55. package/dist/commands/ephemeral/workflow_test/run/index.d.ts +0 -18
  56. package/dist/commands/ephemeral/workflow_test/run/index.js +0 -91
  57. package/dist/commands/ephemeral/workflow_test/run_all/index.d.ts +0 -13
  58. package/dist/commands/ephemeral/workflow_test/run_all/index.js +0 -169
  59. package/dist/commands/release/deploy/index.d.ts +0 -17
  60. package/dist/commands/release/deploy/index.js +0 -107
  61. package/dist/commands/tenant/unit_test/list/index.d.ts +0 -15
  62. package/dist/commands/tenant/unit_test/list/index.js +0 -140
  63. package/dist/commands/tenant/unit_test/run/index.d.ts +0 -16
  64. package/dist/commands/tenant/unit_test/run/index.js +0 -128
  65. package/dist/commands/tenant/unit_test/run_all/index.d.ts +0 -15
  66. package/dist/commands/tenant/unit_test/run_all/index.js +0 -215
  67. package/dist/commands/tenant/workflow_test/delete/index.d.ts +0 -19
  68. package/dist/commands/tenant/workflow_test/delete/index.js +0 -110
  69. package/dist/commands/tenant/workflow_test/get/index.d.ts +0 -19
  70. package/dist/commands/tenant/workflow_test/get/index.js +0 -112
  71. package/dist/commands/tenant/workflow_test/list/index.d.ts +0 -14
  72. package/dist/commands/tenant/workflow_test/list/index.js +0 -133
  73. package/dist/commands/tenant/workflow_test/run/index.d.ts +0 -19
  74. package/dist/commands/tenant/workflow_test/run/index.js +0 -126
  75. package/dist/commands/tenant/workflow_test/run_all/index.d.ts +0 -14
  76. package/dist/commands/tenant/workflow_test/run_all/index.js +0 -201
@@ -1,169 +0,0 @@
1
- import { Flags } from '@oclif/core';
2
- import BaseCommand from '../../../../base-command.js';
3
- export default class EphemeralWorkflowTestRunAll extends BaseCommand {
4
- static description = 'Run all workflow tests for an ephemeral tenant';
5
- static examples = [
6
- `$ xano ephemeral workflow-test run-all -t e1a2-b3c4-x5y6
7
- Running 3 workflow tests...
8
-
9
- PASS my-test (0.25s)
10
- FAIL data-check (0.10s)
11
- Error: assertion failed
12
-
13
- Results: 2 passed, 1 failed
14
- `,
15
- `$ xano ephemeral workflow-test run-all -t e1a2-b3c4-x5y6 -o json`,
16
- ];
17
- static flags = {
18
- ...BaseCommand.baseFlags,
19
- branch: Flags.string({
20
- char: 'b',
21
- description: 'Filter by branch name',
22
- required: false,
23
- }),
24
- output: Flags.string({
25
- char: 'o',
26
- default: 'summary',
27
- description: 'Output format',
28
- options: ['summary', 'json'],
29
- required: false,
30
- }),
31
- tenant: Flags.string({
32
- char: 't',
33
- description: 'Ephemeral tenant name',
34
- required: true,
35
- }),
36
- };
37
- async run() {
38
- const { flags } = await this.parse(EphemeralWorkflowTestRunAll);
39
- const profileName = flags.profile || this.getDefaultProfile();
40
- const credentials = this.loadCredentialsFile();
41
- if (!credentials || !(profileName in credentials.profiles)) {
42
- this.error(`Profile '${profileName}' not found.\nCreate a profile using 'xano profile create'`);
43
- }
44
- const profile = credentials.profiles[profileName];
45
- if (!profile.instance_origin) {
46
- this.error(`Profile '${profileName}' is missing instance_origin`);
47
- }
48
- if (!profile.access_token) {
49
- this.error(`Profile '${profileName}' is missing access_token`);
50
- }
51
- const baseUrl = `${profile.instance_origin}/api:meta/ephemeral/tenant/${encodeURIComponent(flags.tenant)}/workflow_test`;
52
- try {
53
- // Step 1: List all workflow tests
54
- const listParams = new URLSearchParams();
55
- listParams.set('per_page', '10000');
56
- if (flags.branch)
57
- listParams.set('branch', flags.branch);
58
- const listResponse = await this.verboseFetch(`${baseUrl}?${listParams}`, {
59
- headers: {
60
- accept: 'application/json',
61
- Authorization: `Bearer ${profile.access_token}`,
62
- },
63
- method: 'GET',
64
- }, flags.verbose, profile.access_token);
65
- if (!listResponse.ok) {
66
- const errorText = await listResponse.text();
67
- this.error(`Failed to list workflow tests: ${listResponse.status}: ${listResponse.statusText}\n${errorText}`);
68
- }
69
- const data = (await listResponse.json());
70
- let tests;
71
- if (Array.isArray(data)) {
72
- tests = data;
73
- }
74
- else if (data && typeof data === 'object' && 'items' in data && Array.isArray(data.items)) {
75
- tests = data.items;
76
- }
77
- else {
78
- this.error('Unexpected API response format');
79
- }
80
- if (tests.length === 0) {
81
- this.log('No workflow tests found');
82
- return;
83
- }
84
- if (flags.output === 'summary') {
85
- this.log(`Running ${tests.length} workflow test${tests.length === 1 ? '' : 's'}...\n`);
86
- }
87
- // Step 2: Run each test
88
- const results = [];
89
- for (const test of tests) {
90
- const runUrl = `${baseUrl}/${test.id}/run`;
91
- try {
92
- const runResponse = await this.verboseFetch(runUrl, {
93
- headers: {
94
- accept: 'application/json',
95
- Authorization: `Bearer ${profile.access_token}`,
96
- 'Content-Type': 'application/json',
97
- },
98
- method: 'POST',
99
- }, flags.verbose, profile.access_token);
100
- if (!runResponse.ok) {
101
- const errorText = await runResponse.text();
102
- results.push({
103
- message: `API error ${runResponse.status}: ${errorText}`,
104
- name: test.name,
105
- status: 'fail',
106
- });
107
- if (flags.output === 'summary') {
108
- this.log(`FAIL ${test.name}`);
109
- this.log(` Error: API error ${runResponse.status}`);
110
- }
111
- continue;
112
- }
113
- const runResult = (await runResponse.json());
114
- const passed = runResult.status === 'ok';
115
- results.push({
116
- message: runResult.message,
117
- name: test.name,
118
- status: passed ? 'pass' : 'fail',
119
- timing: runResult.timing,
120
- });
121
- if (flags.output === 'summary') {
122
- const timing = runResult.timing ? ` (${runResult.timing}s)` : '';
123
- if (passed) {
124
- this.log(`PASS ${test.name}${timing}`);
125
- }
126
- else {
127
- this.log(`FAIL ${test.name}${timing}`);
128
- if (runResult.message) {
129
- this.log(` Error: ${runResult.message}`);
130
- }
131
- }
132
- }
133
- }
134
- catch (error) {
135
- const message = error instanceof Error ? error.message : String(error);
136
- results.push({
137
- message,
138
- name: test.name,
139
- status: 'fail',
140
- });
141
- if (flags.output === 'summary') {
142
- this.log(`FAIL ${test.name}`);
143
- this.log(` Error: ${message}`);
144
- }
145
- }
146
- }
147
- // Step 3: Summary
148
- const passed = results.filter((r) => r.status === 'pass').length;
149
- const failed = results.filter((r) => r.status === 'fail').length;
150
- if (flags.output === 'json') {
151
- this.log(JSON.stringify({ failed, passed, results }, null, 2));
152
- }
153
- else {
154
- this.log(`\nResults: ${passed} passed, ${failed} failed`);
155
- }
156
- if (failed > 0) {
157
- process.exitCode = 1;
158
- }
159
- }
160
- catch (error) {
161
- if (error instanceof Error) {
162
- this.error(`Failed to run workflow tests: ${error.message}`);
163
- }
164
- else {
165
- this.error(`Failed to run workflow tests: ${String(error)}`);
166
- }
167
- }
168
- }
169
- }
@@ -1,17 +0,0 @@
1
- import BaseCommand from '../../../base-command.js';
2
- export default class ReleaseDeploy extends BaseCommand {
3
- static args: {
4
- release_name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
- };
6
- static description: string;
7
- static examples: string[];
8
- static flags: {
9
- branch: 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
- set_live: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
- workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, 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
- }
@@ -1,107 +0,0 @@
1
- import { Args, Flags } from '@oclif/core';
2
- import BaseCommand from '../../../base-command.js';
3
- export default class ReleaseDeploy extends BaseCommand {
4
- static args = {
5
- release_name: Args.string({
6
- description: 'Name of the release to deploy',
7
- required: true,
8
- }),
9
- };
10
- static description = 'Deploy a release to its workspace as a new branch';
11
- static examples = [
12
- `$ xano release deploy "v1.0"
13
- Deployed release "v1.0" to workspace 40 (branch: v1.0, set live)
14
- `,
15
- `$ xano release deploy "v1.0" --branch "restore-v1" --no-set_live`,
16
- `$ xano release deploy "v1.0" -w 40 -o json`,
17
- ];
18
- static flags = {
19
- ...BaseCommand.baseFlags,
20
- branch: Flags.string({
21
- char: 'b',
22
- description: 'Branch label for the new branch (defaults to release branch name)',
23
- required: false,
24
- }),
25
- output: Flags.string({
26
- char: 'o',
27
- default: 'summary',
28
- description: 'Output format',
29
- options: ['summary', 'json'],
30
- required: false,
31
- }),
32
- set_live: Flags.boolean({
33
- default: false,
34
- description: 'Set the new branch as live',
35
- required: false,
36
- }),
37
- workspace: Flags.string({
38
- char: 'w',
39
- description: 'Workspace ID (uses profile workspace if not provided)',
40
- required: false,
41
- }),
42
- };
43
- async run() {
44
- const { args, flags } = await this.parse(ReleaseDeploy);
45
- const profileName = flags.profile || this.getDefaultProfile();
46
- const credentials = this.loadCredentialsFile();
47
- if (!credentials || !(profileName in credentials.profiles)) {
48
- this.error(`Profile '${profileName}' not found.\n` + `Create a profile using 'xano profile create'`);
49
- }
50
- const profile = credentials.profiles[profileName];
51
- if (!profile.instance_origin) {
52
- this.error(`Profile '${profileName}' is missing instance_origin`);
53
- }
54
- if (!profile.access_token) {
55
- this.error(`Profile '${profileName}' is missing access_token`);
56
- }
57
- const workspaceId = flags.workspace || profile.workspace;
58
- if (!workspaceId) {
59
- this.error('No workspace ID provided. Use --workspace flag or set one in your profile.');
60
- }
61
- const releaseName = encodeURIComponent(args.release_name);
62
- const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/release/${releaseName}/deploy`;
63
- const body = {
64
- set_live: flags.set_live,
65
- };
66
- if (flags.branch)
67
- body.branch = flags.branch;
68
- this.warn('This may take a few minutes. Please be patient.');
69
- const startTime = Date.now();
70
- try {
71
- const response = await this.verboseFetch(apiUrl, {
72
- body: JSON.stringify(body),
73
- headers: {
74
- accept: 'application/json',
75
- Authorization: `Bearer ${profile.access_token}`,
76
- 'Content-Type': 'application/json',
77
- },
78
- method: 'POST',
79
- }, flags.verbose, profile.access_token);
80
- if (!response.ok) {
81
- const errorText = await response.text();
82
- this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
83
- }
84
- const release = (await response.json());
85
- if (flags.output === 'json') {
86
- this.log(JSON.stringify(release, null, 2));
87
- }
88
- else {
89
- const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
90
- const branchLabel = flags.branch || release.branch || 'default';
91
- const liveStatus = flags.set_live ? ', set live' : '';
92
- this.log(`Deployed release "${release.name}" to workspace ${workspaceId} (branch: ${branchLabel}${liveStatus})`);
93
- if (release.description)
94
- this.log(` Description: ${release.description}`);
95
- this.log(` Time: ${elapsed}s`);
96
- }
97
- }
98
- catch (error) {
99
- if (error instanceof Error) {
100
- this.error(`Failed to deploy release: ${error.message}`);
101
- }
102
- else {
103
- this.error(`Failed to deploy release: ${String(error)}`);
104
- }
105
- }
106
- }
107
- }
@@ -1,15 +0,0 @@
1
- import BaseCommand from '../../../../base-command.js';
2
- export default class TenantUnitTestList extends BaseCommand {
3
- static description: string;
4
- static examples: string[];
5
- static flags: {
6
- branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
- 'obj-type': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
- output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
- tenant: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
- workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, 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
- }
@@ -1,140 +0,0 @@
1
- import { Flags } from '@oclif/core';
2
- import BaseCommand from '../../../../base-command.js';
3
- export default class TenantUnitTestList extends BaseCommand {
4
- static description = 'List all unit tests for a tenant';
5
- static examples = [
6
- `$ xano tenant unit-test list -t my-tenant
7
- Unit tests for tenant my-tenant:
8
- - my-test (ID: abc-123) [function: math]
9
- `,
10
- `$ xano tenant unit-test list -t my-tenant -w 5 -o json`,
11
- ];
12
- static flags = {
13
- ...BaseCommand.baseFlags,
14
- branch: Flags.string({
15
- char: 'b',
16
- description: 'Filter by branch name',
17
- required: false,
18
- }),
19
- 'obj-type': Flags.string({
20
- description: 'Filter by object type',
21
- options: ['function', 'query', 'middleware'],
22
- required: false,
23
- }),
24
- output: Flags.string({
25
- char: 'o',
26
- default: 'summary',
27
- description: 'Output format',
28
- options: ['summary', 'json'],
29
- required: false,
30
- }),
31
- tenant: Flags.string({
32
- char: 't',
33
- description: 'Tenant name',
34
- required: true,
35
- }),
36
- workspace: Flags.string({
37
- char: 'w',
38
- description: 'Workspace ID (uses profile workspace if not provided)',
39
- required: false,
40
- }),
41
- };
42
- async run() {
43
- const { flags } = await this.parse(TenantUnitTestList);
44
- const profileName = flags.profile || this.getDefaultProfile();
45
- const credentials = this.loadCredentialsFile();
46
- if (!credentials || !(profileName in credentials.profiles)) {
47
- this.error(`Profile '${profileName}' not found.\nCreate a profile using 'xano profile create'`);
48
- }
49
- const profile = credentials.profiles[profileName];
50
- if (!profile.instance_origin) {
51
- this.error(`Profile '${profileName}' is missing instance_origin`);
52
- }
53
- if (!profile.access_token) {
54
- this.error(`Profile '${profileName}' is missing access_token`);
55
- }
56
- const workspaceId = flags.workspace || profile.workspace;
57
- if (!workspaceId) {
58
- this.error('No workspace ID provided. Use --workspace flag or set one in your profile.');
59
- }
60
- // Resolve tenant to get its workspace
61
- const tenantUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/tenant/${encodeURIComponent(flags.tenant)}`;
62
- let tenantWorkspaceId;
63
- try {
64
- const tenantResponse = await this.verboseFetch(tenantUrl, {
65
- headers: {
66
- accept: 'application/json',
67
- Authorization: `Bearer ${profile.access_token}`,
68
- },
69
- method: 'GET',
70
- }, flags.verbose, profile.access_token);
71
- if (!tenantResponse.ok) {
72
- const errorText = await tenantResponse.text();
73
- this.error(`Failed to find tenant '${flags.tenant}': ${tenantResponse.status}\n${errorText}`);
74
- }
75
- const tenant = (await tenantResponse.json());
76
- tenantWorkspaceId = String(tenant.workspace?.id || workspaceId);
77
- }
78
- catch (error) {
79
- if (error instanceof Error) {
80
- this.error(`Failed to resolve tenant: ${error.message}`);
81
- }
82
- else {
83
- this.error(`Failed to resolve tenant: ${String(error)}`);
84
- }
85
- }
86
- const params = new URLSearchParams();
87
- params.set('per_page', '10000');
88
- if (flags.branch)
89
- params.set('branch', flags.branch);
90
- if (flags['obj-type'])
91
- params.set('obj_type', flags['obj-type']);
92
- const apiUrl = `${profile.instance_origin}/api:meta/workspace/${tenantWorkspaceId}/unit_test?${params}`;
93
- try {
94
- const response = await this.verboseFetch(apiUrl, {
95
- headers: {
96
- accept: 'application/json',
97
- Authorization: `Bearer ${profile.access_token}`,
98
- },
99
- method: 'GET',
100
- }, flags.verbose, profile.access_token);
101
- if (!response.ok) {
102
- const errorText = await response.text();
103
- this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
104
- }
105
- const data = (await response.json());
106
- let tests;
107
- if (Array.isArray(data)) {
108
- tests = data;
109
- }
110
- else if (data && typeof data === 'object' && 'items' in data && Array.isArray(data.items)) {
111
- tests = data.items;
112
- }
113
- else {
114
- this.error('Unexpected API response format');
115
- }
116
- if (flags.output === 'json') {
117
- this.log(JSON.stringify(tests, null, 2));
118
- }
119
- else {
120
- if (tests.length === 0) {
121
- this.log('No unit tests found');
122
- }
123
- else {
124
- this.log(`Unit tests for tenant ${flags.tenant}:`);
125
- for (const test of tests) {
126
- this.log(` - ${test.name} (ID: ${test.id}) [${test.obj_type}: ${test.obj_name}]`);
127
- }
128
- }
129
- }
130
- }
131
- catch (error) {
132
- if (error instanceof Error) {
133
- this.error(`Failed to list unit tests: ${error.message}`);
134
- }
135
- else {
136
- this.error(`Failed to list unit tests: ${String(error)}`);
137
- }
138
- }
139
- }
140
- }
@@ -1,16 +0,0 @@
1
- import BaseCommand from '../../../../base-command.js';
2
- export default class TenantUnitTestRun extends BaseCommand {
3
- static args: {
4
- unit_test_id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
- };
6
- static description: string;
7
- static examples: string[];
8
- static flags: {
9
- output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
- tenant: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
- workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, 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
- }
@@ -1,128 +0,0 @@
1
- import { Args, Flags } from '@oclif/core';
2
- import BaseCommand from '../../../../base-command.js';
3
- export default class TenantUnitTestRun extends BaseCommand {
4
- static args = {
5
- unit_test_id: Args.string({
6
- description: 'ID of the unit test to run',
7
- required: true,
8
- }),
9
- };
10
- static description = 'Run a unit test for a tenant';
11
- static examples = [
12
- `$ xano tenant unit-test run abc-123 -t my-tenant
13
- Running unit test abc-123...
14
- Result: PASS
15
- `,
16
- `$ xano tenant unit-test run abc-123 -t my-tenant -o json`,
17
- ];
18
- static flags = {
19
- ...BaseCommand.baseFlags,
20
- output: Flags.string({
21
- char: 'o',
22
- default: 'summary',
23
- description: 'Output format',
24
- options: ['summary', 'json'],
25
- required: false,
26
- }),
27
- tenant: Flags.string({
28
- char: 't',
29
- description: 'Tenant name',
30
- required: true,
31
- }),
32
- workspace: Flags.string({
33
- char: 'w',
34
- description: 'Workspace ID (uses profile workspace if not provided)',
35
- required: false,
36
- }),
37
- };
38
- async run() {
39
- const { args, flags } = await this.parse(TenantUnitTestRun);
40
- const profileName = flags.profile || this.getDefaultProfile();
41
- const credentials = this.loadCredentialsFile();
42
- if (!credentials || !(profileName in credentials.profiles)) {
43
- this.error(`Profile '${profileName}' not found.\nCreate a profile using 'xano profile create'`);
44
- }
45
- const profile = credentials.profiles[profileName];
46
- if (!profile.instance_origin) {
47
- this.error(`Profile '${profileName}' is missing instance_origin`);
48
- }
49
- if (!profile.access_token) {
50
- this.error(`Profile '${profileName}' is missing access_token`);
51
- }
52
- const workspaceId = flags.workspace || profile.workspace;
53
- if (!workspaceId) {
54
- this.error('No workspace ID provided. Use --workspace flag or set one in your profile.');
55
- }
56
- // Resolve tenant to get its workspace
57
- const tenantUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/tenant/${encodeURIComponent(flags.tenant)}`;
58
- let tenantWorkspaceId;
59
- try {
60
- const tenantResponse = await this.verboseFetch(tenantUrl, {
61
- headers: {
62
- accept: 'application/json',
63
- Authorization: `Bearer ${profile.access_token}`,
64
- },
65
- method: 'GET',
66
- }, flags.verbose, profile.access_token);
67
- if (!tenantResponse.ok) {
68
- const errorText = await tenantResponse.text();
69
- this.error(`Failed to find tenant '${flags.tenant}': ${tenantResponse.status}\n${errorText}`);
70
- }
71
- const tenant = (await tenantResponse.json());
72
- tenantWorkspaceId = String(tenant.workspace?.id || workspaceId);
73
- }
74
- catch (error) {
75
- if (error instanceof Error) {
76
- this.error(`Failed to resolve tenant: ${error.message}`);
77
- }
78
- else {
79
- this.error(`Failed to resolve tenant: ${String(error)}`);
80
- }
81
- }
82
- const apiUrl = `${profile.instance_origin}/api:meta/workspace/${tenantWorkspaceId}/unit_test/${encodeURIComponent(args.unit_test_id)}/run`;
83
- try {
84
- if (flags.output === 'summary') {
85
- this.log(`Running unit test ${args.unit_test_id}...`);
86
- }
87
- const response = await this.verboseFetch(apiUrl, {
88
- headers: {
89
- accept: 'application/json',
90
- Authorization: `Bearer ${profile.access_token}`,
91
- 'Content-Type': 'application/json',
92
- },
93
- method: 'POST',
94
- }, flags.verbose, profile.access_token);
95
- if (!response.ok) {
96
- const errorText = await response.text();
97
- this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
98
- }
99
- const result = (await response.json());
100
- if (flags.output === 'json') {
101
- this.log(JSON.stringify(result, null, 2));
102
- }
103
- else {
104
- if (result.status === 'ok') {
105
- this.log('Result: PASS');
106
- }
107
- else {
108
- this.log('Result: FAIL');
109
- const failedExpects = result.results?.filter((r) => r.status === 'fail') ?? [];
110
- for (const expect of failedExpects) {
111
- if (expect.message) {
112
- this.log(` Error: ${expect.message}`);
113
- }
114
- }
115
- this.exit(1);
116
- }
117
- }
118
- }
119
- catch (error) {
120
- if (error instanceof Error) {
121
- this.error(`Failed to run unit test: ${error.message}`);
122
- }
123
- else {
124
- this.error(`Failed to run unit test: ${String(error)}`);
125
- }
126
- }
127
- }
128
- }
@@ -1,15 +0,0 @@
1
- import BaseCommand from '../../../../base-command.js';
2
- export default class TenantUnitTestRunAll extends BaseCommand {
3
- static description: string;
4
- static examples: string[];
5
- static flags: {
6
- branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
- 'obj-type': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
- output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
- tenant: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
- workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, 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
- }