@xano/cli 0.0.95 → 1.0.1
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 +133 -66
- package/dist/base-command.d.ts +41 -1
- package/dist/base-command.js +92 -3
- package/dist/commands/auth/index.d.ts +1 -0
- package/dist/commands/auth/index.js +16 -11
- package/dist/commands/branch/create/index.d.ts +4 -1
- package/dist/commands/branch/create/index.js +22 -21
- package/dist/commands/branch/delete/index.d.ts +1 -0
- package/dist/commands/branch/delete/index.js +1 -4
- package/dist/commands/branch/edit/index.d.ts +1 -0
- package/dist/commands/branch/edit/index.js +1 -4
- package/dist/commands/branch/get/index.d.ts +1 -0
- package/dist/commands/branch/get/index.js +1 -4
- package/dist/commands/branch/list/index.d.ts +2 -6
- package/dist/commands/branch/list/index.js +13 -17
- package/dist/commands/branch/set_live/index.d.ts +1 -0
- package/dist/commands/branch/set_live/index.js +1 -4
- package/dist/commands/function/create/index.d.ts +1 -0
- package/dist/commands/function/create/index.js +1 -2
- package/dist/commands/function/edit/index.d.ts +1 -0
- package/dist/commands/function/edit/index.js +1 -2
- package/dist/commands/function/get/index.d.ts +1 -0
- package/dist/commands/function/get/index.js +1 -4
- package/dist/commands/function/list/index.d.ts +1 -0
- package/dist/commands/function/list/index.js +1 -4
- package/dist/commands/platform/get/index.d.ts +1 -0
- package/dist/commands/platform/get/index.js +1 -4
- package/dist/commands/platform/list/index.d.ts +1 -0
- package/dist/commands/platform/list/index.js +1 -4
- package/dist/commands/profile/create/index.d.ts +1 -0
- package/dist/commands/profile/create/index.js +12 -6
- package/dist/commands/profile/delete/index.d.ts +1 -0
- package/dist/commands/profile/delete/index.js +8 -4
- package/dist/commands/profile/edit/index.d.ts +1 -0
- package/dist/commands/profile/edit/index.js +3 -6
- package/dist/commands/profile/get/index.d.ts +3 -0
- package/dist/commands/profile/get/index.js +12 -5
- package/dist/commands/profile/list/index.d.ts +1 -0
- package/dist/commands/profile/list/index.js +8 -4
- package/dist/commands/profile/me/index.d.ts +1 -0
- package/dist/commands/profile/me/index.js +22 -6
- package/dist/commands/profile/set/index.d.ts +3 -0
- package/dist/commands/profile/set/index.js +12 -6
- package/dist/commands/profile/token/index.d.ts +3 -0
- package/dist/commands/profile/token/index.js +12 -5
- package/dist/commands/profile/wizard/index.d.ts +1 -0
- package/dist/commands/profile/wizard/index.js +16 -12
- package/dist/commands/profile/workspace/index.d.ts +3 -0
- package/dist/commands/profile/workspace/index.js +12 -5
- package/dist/commands/profile/workspace/set/index.d.ts +1 -0
- package/dist/commands/profile/workspace/set/index.js +2 -4
- package/dist/commands/release/create/index.d.ts +4 -1
- package/dist/commands/release/create/index.js +12 -14
- package/dist/commands/release/delete/index.d.ts +1 -0
- package/dist/commands/release/delete/index.js +1 -4
- package/dist/commands/release/deploy/index.d.ts +20 -0
- package/dist/commands/release/deploy/index.js +137 -0
- package/dist/commands/release/edit/index.d.ts +1 -0
- package/dist/commands/release/edit/index.js +1 -4
- package/dist/commands/release/export/index.d.ts +1 -0
- package/dist/commands/release/export/index.js +1 -3
- package/dist/commands/release/get/index.d.ts +1 -0
- package/dist/commands/release/get/index.js +1 -4
- package/dist/commands/release/import/index.d.ts +1 -0
- package/dist/commands/release/import/index.js +1 -3
- package/dist/commands/release/list/index.d.ts +1 -0
- package/dist/commands/release/list/index.js +1 -4
- package/dist/commands/release/pull/index.d.ts +2 -3
- package/dist/commands/release/pull/index.js +19 -18
- package/dist/commands/release/push/index.d.ts +2 -3
- package/dist/commands/release/push/index.js +19 -22
- package/dist/commands/sandbox/delete/index.d.ts +13 -0
- package/dist/commands/sandbox/delete/index.js +71 -0
- package/dist/commands/sandbox/env/delete/index.d.ts +15 -0
- package/dist/commands/sandbox/env/delete/index.js +89 -0
- package/dist/commands/sandbox/env/get/index.d.ts +13 -0
- package/dist/commands/sandbox/env/get/index.js +65 -0
- package/dist/commands/sandbox/env/get_all/index.d.ts +14 -0
- package/dist/commands/sandbox/env/get_all/index.js +78 -0
- package/dist/commands/sandbox/env/list/index.d.ts +12 -0
- package/dist/commands/sandbox/env/list/index.js +67 -0
- package/dist/commands/sandbox/env/set/index.d.ts +14 -0
- package/dist/commands/sandbox/env/set/index.js +74 -0
- package/dist/commands/sandbox/env/set_all/index.d.ts +14 -0
- package/dist/commands/sandbox/env/set_all/index.js +86 -0
- package/dist/commands/sandbox/get/index.d.ts +12 -0
- package/dist/commands/sandbox/get/index.js +63 -0
- package/dist/commands/sandbox/impersonate/index.d.ts +5 -0
- package/dist/commands/sandbox/impersonate/index.js +5 -0
- package/dist/commands/sandbox/license/get/index.d.ts +14 -0
- package/dist/commands/sandbox/license/get/index.js +78 -0
- package/dist/commands/sandbox/license/set/index.d.ts +15 -0
- package/dist/commands/sandbox/license/set/index.js +95 -0
- package/dist/commands/sandbox/pull/index.d.ts +16 -0
- package/dist/commands/sandbox/pull/index.js +185 -0
- package/dist/commands/sandbox/push/index.d.ts +26 -0
- package/dist/commands/sandbox/push/index.js +196 -0
- package/dist/commands/sandbox/reset/index.d.ts +13 -0
- package/dist/commands/sandbox/reset/index.js +71 -0
- package/dist/commands/sandbox/review/index.d.ts +14 -0
- package/dist/commands/sandbox/review/index.js +94 -0
- package/dist/commands/sandbox/unit_test/list/index.d.ts +14 -0
- package/dist/commands/sandbox/unit_test/list/index.js +91 -0
- package/dist/commands/sandbox/unit_test/run/index.d.ts +15 -0
- package/dist/commands/sandbox/unit_test/run/index.js +79 -0
- package/dist/commands/sandbox/unit_test/run_all/index.d.ts +14 -0
- package/dist/commands/sandbox/unit_test/run_all/index.js +171 -0
- package/dist/commands/sandbox/workflow_test/list/index.d.ts +13 -0
- package/dist/commands/sandbox/workflow_test/list/index.js +84 -0
- package/dist/commands/sandbox/workflow_test/run/index.d.ts +18 -0
- package/dist/commands/sandbox/workflow_test/run/index.js +77 -0
- package/dist/commands/sandbox/workflow_test/run_all/index.d.ts +13 -0
- package/dist/commands/sandbox/workflow_test/run_all/index.js +157 -0
- package/dist/commands/static_host/build/create/index.d.ts +1 -0
- package/dist/commands/static_host/build/create/index.js +1 -3
- package/dist/commands/static_host/build/get/index.d.ts +1 -0
- package/dist/commands/static_host/build/get/index.js +1 -4
- package/dist/commands/static_host/build/list/index.d.ts +1 -0
- package/dist/commands/static_host/build/list/index.js +1 -4
- package/dist/commands/static_host/list/index.d.ts +1 -0
- package/dist/commands/static_host/list/index.js +1 -4
- package/dist/commands/tenant/backup/create/index.d.ts +1 -0
- package/dist/commands/tenant/backup/create/index.js +1 -4
- package/dist/commands/tenant/backup/delete/index.d.ts +1 -0
- package/dist/commands/tenant/backup/delete/index.js +1 -4
- package/dist/commands/tenant/backup/export/index.d.ts +1 -0
- package/dist/commands/tenant/backup/export/index.js +1 -3
- package/dist/commands/tenant/backup/import/index.d.ts +1 -0
- package/dist/commands/tenant/backup/import/index.js +1 -3
- package/dist/commands/tenant/backup/list/index.d.ts +1 -0
- package/dist/commands/tenant/backup/list/index.js +1 -4
- package/dist/commands/tenant/backup/restore/index.d.ts +1 -0
- package/dist/commands/tenant/backup/restore/index.js +1 -4
- package/dist/commands/tenant/cluster/create/index.d.ts +1 -0
- package/dist/commands/tenant/cluster/create/index.js +1 -3
- package/dist/commands/tenant/cluster/delete/index.d.ts +1 -0
- package/dist/commands/tenant/cluster/delete/index.js +1 -4
- package/dist/commands/tenant/cluster/edit/index.d.ts +1 -0
- package/dist/commands/tenant/cluster/edit/index.js +1 -4
- package/dist/commands/tenant/cluster/get/index.d.ts +1 -0
- package/dist/commands/tenant/cluster/get/index.js +1 -4
- package/dist/commands/tenant/cluster/license/get/index.d.ts +1 -0
- package/dist/commands/tenant/cluster/license/get/index.js +1 -3
- package/dist/commands/tenant/cluster/license/set/index.d.ts +1 -0
- package/dist/commands/tenant/cluster/license/set/index.js +1 -3
- package/dist/commands/tenant/cluster/list/index.d.ts +1 -0
- package/dist/commands/tenant/cluster/list/index.js +1 -4
- package/dist/commands/tenant/create/index.d.ts +1 -1
- package/dist/commands/tenant/create/index.js +1 -8
- package/dist/commands/tenant/delete/index.d.ts +1 -0
- package/dist/commands/tenant/delete/index.js +1 -4
- package/dist/commands/tenant/deploy_platform/index.d.ts +1 -0
- package/dist/commands/tenant/deploy_platform/index.js +1 -3
- package/dist/commands/tenant/deploy_release/index.d.ts +1 -0
- package/dist/commands/tenant/deploy_release/index.js +1 -4
- package/dist/commands/tenant/edit/index.d.ts +1 -0
- package/dist/commands/tenant/edit/index.js +1 -4
- package/dist/commands/tenant/env/delete/index.d.ts +1 -0
- package/dist/commands/tenant/env/delete/index.js +1 -4
- package/dist/commands/tenant/env/get/index.d.ts +1 -0
- package/dist/commands/tenant/env/get/index.js +1 -4
- package/dist/commands/tenant/env/get_all/index.d.ts +1 -0
- package/dist/commands/tenant/env/get_all/index.js +1 -3
- package/dist/commands/tenant/env/list/index.d.ts +1 -0
- package/dist/commands/tenant/env/list/index.js +1 -4
- package/dist/commands/tenant/env/set/index.d.ts +1 -0
- package/dist/commands/tenant/env/set/index.js +1 -4
- package/dist/commands/tenant/env/set_all/index.d.ts +1 -0
- package/dist/commands/tenant/env/set_all/index.js +1 -3
- package/dist/commands/tenant/get/index.d.ts +1 -0
- package/dist/commands/tenant/get/index.js +3 -6
- package/dist/commands/tenant/impersonate/index.d.ts +1 -0
- package/dist/commands/tenant/impersonate/index.js +1 -4
- package/dist/commands/tenant/license/get/index.d.ts +1 -0
- package/dist/commands/tenant/license/get/index.js +1 -3
- package/dist/commands/tenant/license/set/index.d.ts +1 -0
- package/dist/commands/tenant/license/set/index.js +1 -3
- package/dist/commands/tenant/list/index.d.ts +1 -0
- package/dist/commands/tenant/list/index.js +3 -6
- package/dist/commands/tenant/pull/index.d.ts +2 -3
- package/dist/commands/tenant/pull/index.js +20 -21
- package/dist/commands/tenant/push/index.d.ts +2 -22
- package/dist/commands/tenant/push/index.js +7 -259
- package/dist/commands/tenant/unit_test/list/index.d.ts +16 -0
- package/dist/commands/tenant/unit_test/list/index.js +115 -0
- package/dist/commands/tenant/unit_test/run/index.d.ts +17 -0
- package/dist/commands/tenant/unit_test/run/index.js +103 -0
- package/dist/commands/tenant/unit_test/run_all/index.d.ts +16 -0
- package/dist/commands/tenant/unit_test/run_all/index.js +190 -0
- package/dist/commands/tenant/workflow_test/list/index.d.ts +15 -0
- package/dist/commands/tenant/workflow_test/list/index.js +108 -0
- package/dist/commands/tenant/workflow_test/run/index.d.ts +20 -0
- package/dist/commands/tenant/workflow_test/run/index.js +101 -0
- package/dist/commands/tenant/workflow_test/run_all/index.d.ts +15 -0
- package/dist/commands/tenant/workflow_test/run_all/index.js +176 -0
- package/dist/commands/unit_test/list/index.d.ts +1 -0
- package/dist/commands/unit_test/list/index.js +1 -4
- package/dist/commands/unit_test/run/index.d.ts +1 -0
- package/dist/commands/unit_test/run/index.js +1 -4
- package/dist/commands/unit_test/run_all/index.d.ts +1 -0
- package/dist/commands/unit_test/run_all/index.js +1 -4
- package/dist/commands/update/index.d.ts +1 -0
- package/dist/commands/workflow_test/delete/index.d.ts +1 -0
- package/dist/commands/workflow_test/delete/index.js +1 -4
- package/dist/commands/workflow_test/get/index.d.ts +1 -0
- package/dist/commands/workflow_test/get/index.js +1 -4
- package/dist/commands/workflow_test/list/index.d.ts +1 -0
- package/dist/commands/workflow_test/list/index.js +1 -4
- package/dist/commands/workflow_test/run/index.d.ts +1 -0
- package/dist/commands/workflow_test/run/index.js +1 -4
- package/dist/commands/workflow_test/run_all/index.d.ts +1 -0
- package/dist/commands/workflow_test/run_all/index.js +1 -4
- package/dist/commands/workspace/create/index.d.ts +1 -0
- package/dist/commands/workspace/create/index.js +1 -4
- package/dist/commands/workspace/delete/index.d.ts +2 -6
- package/dist/commands/workspace/delete/index.js +17 -16
- package/dist/commands/workspace/edit/index.d.ts +3 -6
- package/dist/commands/workspace/edit/index.js +31 -25
- package/dist/commands/workspace/get/index.d.ts +2 -6
- package/dist/commands/workspace/get/index.js +23 -25
- package/dist/commands/workspace/git/pull/index.d.ts +2 -3
- package/dist/commands/workspace/git/pull/index.js +18 -17
- package/dist/commands/workspace/list/index.d.ts +2 -0
- package/dist/commands/workspace/list/index.js +15 -11
- package/dist/commands/workspace/pull/index.d.ts +2 -3
- package/dist/commands/workspace/pull/index.js +21 -24
- package/dist/commands/workspace/push/index.d.ts +7 -16
- package/dist/commands/workspace/push/index.js +85 -674
- package/dist/help.d.ts +2 -1
- package/dist/help.js +39 -1
- package/dist/utils/multidoc-push.d.ts +63 -0
- package/dist/utils/multidoc-push.js +690 -0
- package/dist/utils/reference-checker.d.ts +57 -0
- package/dist/utils/reference-checker.js +232 -0
- package/oclif.manifest.json +5562 -2228
- package/package.json +19 -3
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import snakeCase from 'lodash.snakecase';
|
|
3
|
+
import BaseCommand from '../../../base-command.js';
|
|
4
|
+
import { buildApiGroupFolderResolver, parseDocument } from '../../../utils/document-parser.js';
|
|
5
|
+
import * as fs from 'node:fs';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
export default class SandboxPull extends BaseCommand {
|
|
8
|
+
static description = 'Pull documents from your sandbox environment and split into individual files';
|
|
9
|
+
static examples = [
|
|
10
|
+
`$ xano sandbox pull
|
|
11
|
+
Pulled 42 documents from sandbox environment to current directory
|
|
12
|
+
`,
|
|
13
|
+
`$ xano sandbox pull -d ./my-sandbox
|
|
14
|
+
Pulled 42 documents from sandbox environment to ./my-sandbox
|
|
15
|
+
`,
|
|
16
|
+
`$ xano sandbox pull --env --records`,
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
...BaseCommand.baseFlags,
|
|
20
|
+
directory: Flags.string({
|
|
21
|
+
char: 'd',
|
|
22
|
+
default: '.',
|
|
23
|
+
description: 'Output directory for pulled documents (defaults to current directory)',
|
|
24
|
+
required: false,
|
|
25
|
+
}),
|
|
26
|
+
draft: Flags.boolean({
|
|
27
|
+
default: false,
|
|
28
|
+
description: 'Include draft versions',
|
|
29
|
+
required: false,
|
|
30
|
+
}),
|
|
31
|
+
env: Flags.boolean({
|
|
32
|
+
default: false,
|
|
33
|
+
description: 'Include environment variables',
|
|
34
|
+
required: false,
|
|
35
|
+
}),
|
|
36
|
+
records: Flags.boolean({
|
|
37
|
+
default: false,
|
|
38
|
+
description: 'Include records',
|
|
39
|
+
required: false,
|
|
40
|
+
}),
|
|
41
|
+
};
|
|
42
|
+
async run() {
|
|
43
|
+
const { flags } = await this.parse(SandboxPull);
|
|
44
|
+
const { profile } = this.resolveProfile(flags);
|
|
45
|
+
const queryParams = new URLSearchParams({
|
|
46
|
+
env: flags.env.toString(),
|
|
47
|
+
include_draft: flags.draft.toString(),
|
|
48
|
+
records: flags.records.toString(),
|
|
49
|
+
});
|
|
50
|
+
const apiUrl = `${profile.instance_origin}/api:meta/sandbox/multidoc?${queryParams.toString()}`;
|
|
51
|
+
let responseText;
|
|
52
|
+
try {
|
|
53
|
+
const response = await this.verboseFetch(apiUrl, {
|
|
54
|
+
headers: {
|
|
55
|
+
accept: 'application/json',
|
|
56
|
+
Authorization: `Bearer ${profile.access_token}`,
|
|
57
|
+
},
|
|
58
|
+
method: 'GET',
|
|
59
|
+
}, flags.verbose, profile.access_token);
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
const message = await this.parseApiError(response, 'API request failed');
|
|
62
|
+
this.error(message);
|
|
63
|
+
}
|
|
64
|
+
responseText = await response.text();
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (error instanceof Error && 'oclif' in error)
|
|
68
|
+
throw error;
|
|
69
|
+
if (error instanceof Error) {
|
|
70
|
+
this.error(`Failed to fetch multidoc: ${error.message}`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.error(`Failed to fetch multidoc: ${String(error)}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const rawDocuments = responseText.split('\n---\n');
|
|
77
|
+
const documents = [];
|
|
78
|
+
for (const raw of rawDocuments) {
|
|
79
|
+
const trimmed = raw.trim();
|
|
80
|
+
if (!trimmed) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const parsed = parseDocument(trimmed);
|
|
84
|
+
if (parsed) {
|
|
85
|
+
documents.push(parsed);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (documents.length === 0) {
|
|
89
|
+
this.log('No documents found in response');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const outputDir = path.resolve(flags.directory);
|
|
93
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
94
|
+
const getApiGroupFolder = buildApiGroupFolderResolver(documents, snakeCase);
|
|
95
|
+
const filenameCounters = new Map();
|
|
96
|
+
let writtenCount = 0;
|
|
97
|
+
for (const doc of documents) {
|
|
98
|
+
let typeDir;
|
|
99
|
+
let baseName;
|
|
100
|
+
if (doc.type === 'workspace') {
|
|
101
|
+
typeDir = path.join(outputDir, 'workspace');
|
|
102
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
103
|
+
}
|
|
104
|
+
else if (doc.type === 'workspace_trigger') {
|
|
105
|
+
typeDir = path.join(outputDir, 'workspace', 'trigger');
|
|
106
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
107
|
+
}
|
|
108
|
+
else if (doc.type === 'agent') {
|
|
109
|
+
typeDir = path.join(outputDir, 'ai', 'agent');
|
|
110
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
111
|
+
}
|
|
112
|
+
else if (doc.type === 'mcp_server') {
|
|
113
|
+
typeDir = path.join(outputDir, 'ai', 'mcp_server');
|
|
114
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
115
|
+
}
|
|
116
|
+
else if (doc.type === 'tool') {
|
|
117
|
+
typeDir = path.join(outputDir, 'ai', 'tool');
|
|
118
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
119
|
+
}
|
|
120
|
+
else if (doc.type === 'agent_trigger') {
|
|
121
|
+
typeDir = path.join(outputDir, 'ai', 'agent', 'trigger');
|
|
122
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
123
|
+
}
|
|
124
|
+
else if (doc.type === 'mcp_server_trigger') {
|
|
125
|
+
typeDir = path.join(outputDir, 'ai', 'mcp_server', 'trigger');
|
|
126
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
127
|
+
}
|
|
128
|
+
else if (doc.type === 'table_trigger') {
|
|
129
|
+
typeDir = path.join(outputDir, 'table', 'trigger');
|
|
130
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
131
|
+
}
|
|
132
|
+
else if (doc.type === 'realtime_channel') {
|
|
133
|
+
typeDir = path.join(outputDir, 'realtime', 'channel');
|
|
134
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
135
|
+
}
|
|
136
|
+
else if (doc.type === 'realtime_trigger') {
|
|
137
|
+
typeDir = path.join(outputDir, 'realtime', 'trigger');
|
|
138
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
139
|
+
}
|
|
140
|
+
else if (doc.type === 'api_group') {
|
|
141
|
+
const groupFolder = getApiGroupFolder(doc.name);
|
|
142
|
+
typeDir = path.join(outputDir, 'api', groupFolder);
|
|
143
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
144
|
+
}
|
|
145
|
+
else if (doc.type === 'query' && doc.apiGroup) {
|
|
146
|
+
const groupFolder = getApiGroupFolder(doc.apiGroup);
|
|
147
|
+
const nameParts = doc.name.split('/');
|
|
148
|
+
const leafName = nameParts.pop();
|
|
149
|
+
const folderParts = nameParts.map((part) => snakeCase(part));
|
|
150
|
+
typeDir = path.join(outputDir, 'api', groupFolder, ...folderParts);
|
|
151
|
+
baseName = this.sanitizeFilename(leafName);
|
|
152
|
+
if (doc.verb) {
|
|
153
|
+
baseName = `${baseName}_${doc.verb}`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const nameParts = doc.name.split('/');
|
|
158
|
+
const leafName = nameParts.pop();
|
|
159
|
+
const folderParts = nameParts.map((part) => snakeCase(part));
|
|
160
|
+
typeDir = path.join(outputDir, doc.type, ...folderParts);
|
|
161
|
+
baseName = this.sanitizeFilename(leafName);
|
|
162
|
+
if (doc.verb) {
|
|
163
|
+
baseName = `${baseName}_${doc.verb}`;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
fs.mkdirSync(typeDir, { recursive: true });
|
|
167
|
+
const dirKey = path.relative(outputDir, typeDir);
|
|
168
|
+
if (!filenameCounters.has(dirKey)) {
|
|
169
|
+
filenameCounters.set(dirKey, new Map());
|
|
170
|
+
}
|
|
171
|
+
const typeCounters = filenameCounters.get(dirKey);
|
|
172
|
+
const count = typeCounters.get(baseName) || 0;
|
|
173
|
+
typeCounters.set(baseName, count + 1);
|
|
174
|
+
let filename;
|
|
175
|
+
filename = count === 0 ? `${baseName}.xs` : `${baseName}_${count + 1}.xs`;
|
|
176
|
+
const filePath = path.join(typeDir, filename);
|
|
177
|
+
fs.writeFileSync(filePath, doc.content, 'utf8');
|
|
178
|
+
writtenCount++;
|
|
179
|
+
}
|
|
180
|
+
this.log(`Pulled ${writtenCount} documents from sandbox environment to ${flags.directory}`);
|
|
181
|
+
}
|
|
182
|
+
sanitizeFilename(name) {
|
|
183
|
+
return snakeCase(name.replaceAll('"', ''));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import BaseCommand from '../../../base-command.js';
|
|
2
|
+
export default class SandboxPush extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
directory: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
delete: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
env: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
exclude: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
guids: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
include: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
records: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
review: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
+
sync: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
|
+
transaction: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
+
truncate: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
|
+
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
|
+
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
22
|
+
};
|
|
23
|
+
run(): Promise<void>;
|
|
24
|
+
private openReview;
|
|
25
|
+
private getFrontendUrl;
|
|
26
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import open from 'open';
|
|
5
|
+
import BaseCommand from '../../../base-command.js';
|
|
6
|
+
import { executePush } from '../../../utils/multidoc-push.js';
|
|
7
|
+
export default class SandboxPush extends BaseCommand {
|
|
8
|
+
static description = 'Push local documents to your sandbox environment via multidoc import. By default, only changed files are pushed (partial mode). Use --sync to push all files. Shows a preview of changes before pushing unless --force is specified. Use --dry-run to preview only.';
|
|
9
|
+
static examples = [
|
|
10
|
+
`$ xano sandbox push
|
|
11
|
+
Push from current directory (default partial mode)
|
|
12
|
+
`,
|
|
13
|
+
`$ xano sandbox push -d ./my-workspace
|
|
14
|
+
Push from a specific directory
|
|
15
|
+
`,
|
|
16
|
+
`$ xano sandbox push --sync
|
|
17
|
+
Push all files to the sandbox
|
|
18
|
+
`,
|
|
19
|
+
`$ xano sandbox push --sync --delete
|
|
20
|
+
Push all files and delete remote objects not included
|
|
21
|
+
`,
|
|
22
|
+
`$ xano sandbox push --dry-run
|
|
23
|
+
Preview changes without pushing
|
|
24
|
+
`,
|
|
25
|
+
`$ xano sandbox push --force
|
|
26
|
+
Skip preview and push immediately
|
|
27
|
+
`,
|
|
28
|
+
`$ xano sandbox push --records --env`,
|
|
29
|
+
`$ xano sandbox push --truncate`,
|
|
30
|
+
`$ xano sandbox push -i "**/func*"
|
|
31
|
+
Push only files matching the glob pattern
|
|
32
|
+
`,
|
|
33
|
+
`$ xano sandbox push -i "function/*" -i "table/*"
|
|
34
|
+
Push files matching multiple patterns
|
|
35
|
+
`,
|
|
36
|
+
`$ xano sandbox push -e "table/*"
|
|
37
|
+
Push all files except tables
|
|
38
|
+
`,
|
|
39
|
+
`$ xano sandbox push --review
|
|
40
|
+
Push and open sandbox review in the browser
|
|
41
|
+
`,
|
|
42
|
+
];
|
|
43
|
+
static flags = {
|
|
44
|
+
...BaseCommand.baseFlags,
|
|
45
|
+
directory: Flags.string({
|
|
46
|
+
char: 'd',
|
|
47
|
+
default: '.',
|
|
48
|
+
description: 'Directory containing documents to push (defaults to current directory)',
|
|
49
|
+
required: false,
|
|
50
|
+
}),
|
|
51
|
+
delete: Flags.boolean({
|
|
52
|
+
default: false,
|
|
53
|
+
description: 'Delete sandbox objects not included in the push (requires --sync)',
|
|
54
|
+
required: false,
|
|
55
|
+
}),
|
|
56
|
+
'dry-run': Flags.boolean({
|
|
57
|
+
default: false,
|
|
58
|
+
description: 'Show preview of changes without pushing (exit after preview)',
|
|
59
|
+
required: false,
|
|
60
|
+
}),
|
|
61
|
+
env: Flags.boolean({
|
|
62
|
+
default: false,
|
|
63
|
+
description: 'Include environment variables in import',
|
|
64
|
+
required: false,
|
|
65
|
+
}),
|
|
66
|
+
exclude: Flags.string({
|
|
67
|
+
char: 'e',
|
|
68
|
+
description: 'Glob pattern to exclude files (e.g. "table/*", "**/test*"). Matched against relative paths from the push directory.',
|
|
69
|
+
multiple: true,
|
|
70
|
+
required: false,
|
|
71
|
+
}),
|
|
72
|
+
force: Flags.boolean({
|
|
73
|
+
default: false,
|
|
74
|
+
description: 'Skip preview and confirmation prompt (for CI/CD pipelines)',
|
|
75
|
+
required: false,
|
|
76
|
+
}),
|
|
77
|
+
guids: Flags.boolean({
|
|
78
|
+
allowNo: true,
|
|
79
|
+
default: true,
|
|
80
|
+
description: 'Write server-assigned GUIDs back to local files (use --no-guids to skip)',
|
|
81
|
+
required: false,
|
|
82
|
+
}),
|
|
83
|
+
include: Flags.string({
|
|
84
|
+
char: 'i',
|
|
85
|
+
description: 'Glob pattern to include files (e.g. "**/func*", "table/*.xs"). Matched against relative paths from the push directory.',
|
|
86
|
+
multiple: true,
|
|
87
|
+
required: false,
|
|
88
|
+
}),
|
|
89
|
+
records: Flags.boolean({
|
|
90
|
+
default: false,
|
|
91
|
+
description: 'Include records in import',
|
|
92
|
+
required: false,
|
|
93
|
+
}),
|
|
94
|
+
review: Flags.boolean({
|
|
95
|
+
default: false,
|
|
96
|
+
description: 'Open sandbox review in the browser after pushing',
|
|
97
|
+
required: false,
|
|
98
|
+
}),
|
|
99
|
+
sync: Flags.boolean({
|
|
100
|
+
default: false,
|
|
101
|
+
description: 'Full push — send all files, not just changed ones. Required for --delete.',
|
|
102
|
+
required: false,
|
|
103
|
+
}),
|
|
104
|
+
transaction: Flags.boolean({
|
|
105
|
+
allowNo: true,
|
|
106
|
+
default: true,
|
|
107
|
+
description: 'Wrap import in a database transaction (use --no-transaction for debugging purposes)',
|
|
108
|
+
required: false,
|
|
109
|
+
}),
|
|
110
|
+
truncate: Flags.boolean({
|
|
111
|
+
default: false,
|
|
112
|
+
description: 'Truncate all table records before importing',
|
|
113
|
+
required: false,
|
|
114
|
+
}),
|
|
115
|
+
};
|
|
116
|
+
async run() {
|
|
117
|
+
const { flags } = await this.parse(SandboxPush);
|
|
118
|
+
const { profile } = this.resolveProfile(flags);
|
|
119
|
+
const inputDir = resolve(flags.directory);
|
|
120
|
+
if (!fs.existsSync(inputDir)) {
|
|
121
|
+
this.error(`Directory not found: ${inputDir}`);
|
|
122
|
+
}
|
|
123
|
+
if (!fs.statSync(inputDir).isDirectory()) {
|
|
124
|
+
this.error(`Not a directory: ${inputDir}`);
|
|
125
|
+
}
|
|
126
|
+
const baseUrl = `${profile.instance_origin}/api:meta/sandbox`;
|
|
127
|
+
const target = {
|
|
128
|
+
buildDryRunUrl: (params) => `${baseUrl}/multidoc/dry-run?${params.toString()}`,
|
|
129
|
+
buildPushUrl: (params) => `${baseUrl}/multidoc?${params.toString()}`,
|
|
130
|
+
cliVersion: this.config.version,
|
|
131
|
+
instanceOrigin: profile.instance_origin,
|
|
132
|
+
label: 'sandbox environment',
|
|
133
|
+
supportsBranches: false,
|
|
134
|
+
supportsPartial: true,
|
|
135
|
+
};
|
|
136
|
+
const pushFlags = {
|
|
137
|
+
delete: flags.delete,
|
|
138
|
+
'dry-run': flags['dry-run'],
|
|
139
|
+
env: flags.env,
|
|
140
|
+
exclude: flags.exclude,
|
|
141
|
+
force: flags.force,
|
|
142
|
+
guids: flags.guids,
|
|
143
|
+
include: flags.include,
|
|
144
|
+
records: flags.records,
|
|
145
|
+
sync: flags.sync,
|
|
146
|
+
transaction: flags.transaction,
|
|
147
|
+
truncate: flags.truncate,
|
|
148
|
+
verbose: flags.verbose,
|
|
149
|
+
};
|
|
150
|
+
await executePush({
|
|
151
|
+
accessToken: profile.access_token,
|
|
152
|
+
branch: '',
|
|
153
|
+
command: this,
|
|
154
|
+
inputDir,
|
|
155
|
+
verboseFetch: this.verboseFetch.bind(this),
|
|
156
|
+
}, target, pushFlags);
|
|
157
|
+
if (flags.review) {
|
|
158
|
+
await this.openReview(profile.instance_origin, profile.access_token, flags.verbose);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async openReview(instanceOrigin, accessToken, verbose) {
|
|
162
|
+
const response = await this.verboseFetch(`${instanceOrigin}/api:meta/sandbox/impersonate`, {
|
|
163
|
+
headers: {
|
|
164
|
+
accept: 'application/json',
|
|
165
|
+
Authorization: `Bearer ${accessToken}`,
|
|
166
|
+
},
|
|
167
|
+
method: 'GET',
|
|
168
|
+
}, verbose, accessToken);
|
|
169
|
+
if (!response.ok) {
|
|
170
|
+
const message = await this.parseApiError(response, 'Failed to open sandbox review');
|
|
171
|
+
this.error(message);
|
|
172
|
+
}
|
|
173
|
+
const result = (await response.json());
|
|
174
|
+
if (!result._ti) {
|
|
175
|
+
this.error('No one-time token returned from impersonate API');
|
|
176
|
+
}
|
|
177
|
+
const frontendUrl = this.getFrontendUrl(instanceOrigin);
|
|
178
|
+
const params = new URLSearchParams({ _ti: result._ti });
|
|
179
|
+
const reviewUrl = `${frontendUrl}/impersonate?${params.toString()}`;
|
|
180
|
+
this.log('Opening sandbox review...');
|
|
181
|
+
await open(reviewUrl);
|
|
182
|
+
}
|
|
183
|
+
getFrontendUrl(instanceOrigin) {
|
|
184
|
+
try {
|
|
185
|
+
const url = new URL(instanceOrigin);
|
|
186
|
+
if (url.hostname === 'localhost' || url.hostname === '127.0.0.1') {
|
|
187
|
+
url.port = '4200';
|
|
188
|
+
return url.origin;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// fall through
|
|
193
|
+
}
|
|
194
|
+
return instanceOrigin;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import BaseCommand from '../../../base-command.js';
|
|
2
|
+
export default class SandboxReset extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
private confirm;
|
|
13
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import BaseCommand from '../../../base-command.js';
|
|
3
|
+
export default class SandboxReset extends BaseCommand {
|
|
4
|
+
static description = 'Reset your sandbox environment (clears all workspace data and drafts)';
|
|
5
|
+
static examples = [
|
|
6
|
+
`$ xano sandbox reset
|
|
7
|
+
Are you sure you want to reset your sandbox environment? All workspace data and drafts will be cleared. (y/N) y
|
|
8
|
+
Sandbox environment has been reset.
|
|
9
|
+
`,
|
|
10
|
+
`$ xano sandbox reset --force`,
|
|
11
|
+
];
|
|
12
|
+
static flags = {
|
|
13
|
+
...BaseCommand.baseFlags,
|
|
14
|
+
force: Flags.boolean({
|
|
15
|
+
char: 'f',
|
|
16
|
+
default: false,
|
|
17
|
+
description: 'Skip confirmation prompt',
|
|
18
|
+
required: false,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
async run() {
|
|
22
|
+
const { flags } = await this.parse(SandboxReset);
|
|
23
|
+
const { profile } = this.resolveProfile(flags);
|
|
24
|
+
if (!flags.force) {
|
|
25
|
+
const confirmed = await this.confirm(`Are you sure you want to reset your sandbox environment? All workspace data and drafts will be cleared.`);
|
|
26
|
+
if (!confirmed) {
|
|
27
|
+
this.log('Reset cancelled.');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const apiUrl = `${profile.instance_origin}/api:meta/sandbox/reset`;
|
|
32
|
+
try {
|
|
33
|
+
const response = await this.verboseFetch(apiUrl, {
|
|
34
|
+
headers: {
|
|
35
|
+
accept: 'application/json',
|
|
36
|
+
Authorization: `Bearer ${profile.access_token}`,
|
|
37
|
+
'Content-Type': 'application/json',
|
|
38
|
+
},
|
|
39
|
+
method: 'POST',
|
|
40
|
+
}, flags.verbose, profile.access_token);
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
const message = await this.parseApiError(response, 'API request failed');
|
|
43
|
+
this.error(message);
|
|
44
|
+
}
|
|
45
|
+
this.log('Sandbox environment has been reset.');
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (error instanceof Error && 'oclif' in error)
|
|
49
|
+
throw error;
|
|
50
|
+
if (error instanceof Error) {
|
|
51
|
+
this.error(`Failed to reset sandbox environment: ${error.message}`);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
this.error(`Failed to reset sandbox environment: ${String(error)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async confirm(message) {
|
|
59
|
+
const readline = await import('node:readline');
|
|
60
|
+
const rl = readline.createInterface({
|
|
61
|
+
input: process.stdin,
|
|
62
|
+
output: process.stdout,
|
|
63
|
+
});
|
|
64
|
+
return new Promise((resolve) => {
|
|
65
|
+
rl.question(`${message} (y/N) `, (answer) => {
|
|
66
|
+
rl.close();
|
|
67
|
+
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import BaseCommand from '../../../base-command.js';
|
|
2
|
+
export default class SandboxReview extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
'url-only': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
private getFrontendUrl;
|
|
14
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import open from 'open';
|
|
3
|
+
import BaseCommand from '../../../base-command.js';
|
|
4
|
+
export default class SandboxReview extends BaseCommand {
|
|
5
|
+
static description = 'Open your sandbox environment in the browser to review and promote changes';
|
|
6
|
+
static examples = [
|
|
7
|
+
`$ xano sandbox review
|
|
8
|
+
Opening browser...
|
|
9
|
+
Review session started!
|
|
10
|
+
`,
|
|
11
|
+
`$ xano sandbox review -u`,
|
|
12
|
+
`$ xano sandbox review -o json`,
|
|
13
|
+
];
|
|
14
|
+
static flags = {
|
|
15
|
+
...BaseCommand.baseFlags,
|
|
16
|
+
output: Flags.string({
|
|
17
|
+
char: 'o',
|
|
18
|
+
default: 'summary',
|
|
19
|
+
description: 'Output format',
|
|
20
|
+
options: ['summary', 'json'],
|
|
21
|
+
required: false,
|
|
22
|
+
}),
|
|
23
|
+
'url-only': Flags.boolean({
|
|
24
|
+
char: 'u',
|
|
25
|
+
default: false,
|
|
26
|
+
description: 'Print the URL without opening the browser',
|
|
27
|
+
required: false,
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
async run() {
|
|
31
|
+
const { flags } = await this.parse(SandboxReview);
|
|
32
|
+
const { profile } = this.resolveProfile(flags);
|
|
33
|
+
const apiUrl = `${profile.instance_origin}/api:meta/sandbox/impersonate`;
|
|
34
|
+
try {
|
|
35
|
+
const response = await this.verboseFetch(apiUrl, {
|
|
36
|
+
headers: {
|
|
37
|
+
accept: 'application/json',
|
|
38
|
+
Authorization: `Bearer ${profile.access_token}`,
|
|
39
|
+
},
|
|
40
|
+
method: 'GET',
|
|
41
|
+
}, flags.verbose, profile.access_token);
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
const message = await this.parseApiError(response, 'API request failed');
|
|
44
|
+
this.error(message);
|
|
45
|
+
}
|
|
46
|
+
const result = (await response.json());
|
|
47
|
+
if (!result._ti) {
|
|
48
|
+
this.error('No one-time token returned from impersonate API');
|
|
49
|
+
}
|
|
50
|
+
if (flags.output === 'json') {
|
|
51
|
+
this.log(JSON.stringify(result, null, 2));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const frontendUrl = this.getFrontendUrl(profile.instance_origin);
|
|
55
|
+
const params = new URLSearchParams({
|
|
56
|
+
_ti: result._ti,
|
|
57
|
+
});
|
|
58
|
+
const impersonateUrl = `${frontendUrl}/impersonate?${params.toString()}`;
|
|
59
|
+
if (flags['url-only']) {
|
|
60
|
+
this.log(impersonateUrl);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
this.log('Opening browser...');
|
|
64
|
+
await open(impersonateUrl);
|
|
65
|
+
this.log('Review session started!');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (error instanceof Error && 'oclif' in error)
|
|
72
|
+
throw error;
|
|
73
|
+
if (error instanceof Error) {
|
|
74
|
+
this.error(`Failed to open sandbox review: ${error.message}`);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
this.error(`Failed to open sandbox review: ${String(error)}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
getFrontendUrl(instanceOrigin) {
|
|
82
|
+
try {
|
|
83
|
+
const url = new URL(instanceOrigin);
|
|
84
|
+
if (url.hostname === 'localhost' || url.hostname === '127.0.0.1') {
|
|
85
|
+
url.port = '4200';
|
|
86
|
+
return url.origin;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// fall through
|
|
91
|
+
}
|
|
92
|
+
return instanceOrigin;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import BaseCommand from '../../../../base-command.js';
|
|
2
|
+
export default class SandboxUnitTestList 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
|
+
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|