@xano/cli 0.0.25 → 0.0.27
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/dist/commands/workspace/pull/index.js +70 -16
- package/dist/commands/workspace/push/index.js +1 -1
- package/oclif.manifest.json +1021 -1021
- package/package.json +3 -1
|
@@ -3,6 +3,7 @@ import * as yaml from 'js-yaml';
|
|
|
3
3
|
import * as fs from 'node:fs';
|
|
4
4
|
import * as os from 'node:os';
|
|
5
5
|
import * as path from 'node:path';
|
|
6
|
+
import snakeCase from 'lodash.snakecase';
|
|
6
7
|
import BaseCommand from '../../../base-command.js';
|
|
7
8
|
export default class Pull extends BaseCommand {
|
|
8
9
|
static args = {
|
|
@@ -130,19 +131,69 @@ Pulled 58 documents to ./backup
|
|
|
130
131
|
const filenameCounters = new Map();
|
|
131
132
|
let writtenCount = 0;
|
|
132
133
|
for (const doc of documents) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
134
|
+
let typeDir;
|
|
135
|
+
let baseName;
|
|
136
|
+
if (doc.type === 'workspace') {
|
|
137
|
+
// workspace → workspace/{name}.xs
|
|
138
|
+
typeDir = path.join(outputDir, 'workspace');
|
|
139
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
140
|
+
}
|
|
141
|
+
else if (doc.type === 'workspace_trigger') {
|
|
142
|
+
// workspace_trigger → workspace/trigger/{name}.xs
|
|
143
|
+
typeDir = path.join(outputDir, 'workspace', 'trigger');
|
|
144
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
145
|
+
}
|
|
146
|
+
else if (doc.type === 'agent_trigger') {
|
|
147
|
+
// agent_trigger → agent/trigger/{name}.xs
|
|
148
|
+
typeDir = path.join(outputDir, 'agent', 'trigger');
|
|
149
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
150
|
+
}
|
|
151
|
+
else if (doc.type === 'mcp_server_trigger') {
|
|
152
|
+
// mcp_server_trigger → mcp_server/trigger/{name}.xs
|
|
153
|
+
typeDir = path.join(outputDir, 'mcp_server', 'trigger');
|
|
154
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
155
|
+
}
|
|
156
|
+
else if (doc.type === 'table_trigger') {
|
|
157
|
+
// table_trigger → table/trigger/{name}.xs
|
|
158
|
+
typeDir = path.join(outputDir, 'table', 'trigger');
|
|
159
|
+
baseName = this.sanitizeFilename(doc.name);
|
|
160
|
+
}
|
|
161
|
+
else if (doc.type === 'api_group') {
|
|
162
|
+
// api_group "test" → api/test/api_group.xs
|
|
163
|
+
const groupFolder = snakeCase(doc.name);
|
|
164
|
+
typeDir = path.join(outputDir, 'api', groupFolder);
|
|
165
|
+
baseName = 'api_group';
|
|
140
166
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
167
|
+
else if (doc.type === 'query' && doc.apiGroup) {
|
|
168
|
+
// query in group "test" → api/test/{query_name}.xs
|
|
169
|
+
const groupFolder = snakeCase(doc.apiGroup);
|
|
170
|
+
const nameParts = doc.name.split('/');
|
|
171
|
+
const leafName = nameParts.pop();
|
|
172
|
+
const folderParts = nameParts.map((part) => snakeCase(part));
|
|
173
|
+
typeDir = path.join(outputDir, 'api', groupFolder, ...folderParts);
|
|
174
|
+
baseName = this.sanitizeFilename(leafName);
|
|
175
|
+
if (doc.verb) {
|
|
176
|
+
baseName = `${baseName}_${doc.verb}`;
|
|
177
|
+
}
|
|
144
178
|
}
|
|
145
|
-
|
|
179
|
+
else {
|
|
180
|
+
// Default: split folder path from name
|
|
181
|
+
const nameParts = doc.name.split('/');
|
|
182
|
+
const leafName = nameParts.pop();
|
|
183
|
+
const folderParts = nameParts.map((part) => snakeCase(part));
|
|
184
|
+
typeDir = path.join(outputDir, doc.type, ...folderParts);
|
|
185
|
+
baseName = this.sanitizeFilename(leafName);
|
|
186
|
+
if (doc.verb) {
|
|
187
|
+
baseName = `${baseName}_${doc.verb}`;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
fs.mkdirSync(typeDir, { recursive: true });
|
|
191
|
+
// Track duplicates per directory
|
|
192
|
+
const dirKey = path.relative(outputDir, typeDir);
|
|
193
|
+
if (!filenameCounters.has(dirKey)) {
|
|
194
|
+
filenameCounters.set(dirKey, new Map());
|
|
195
|
+
}
|
|
196
|
+
const typeCounters = filenameCounters.get(dirKey);
|
|
146
197
|
const count = typeCounters.get(baseName) || 0;
|
|
147
198
|
typeCounters.set(baseName, count + 1);
|
|
148
199
|
// Append numeric suffix for duplicates
|
|
@@ -217,7 +268,13 @@ Pulled 58 documents to ./backup
|
|
|
217
268
|
if (verbMatch) {
|
|
218
269
|
verb = verbMatch[1];
|
|
219
270
|
}
|
|
220
|
-
|
|
271
|
+
// Extract api_group if present (e.g., api_group = "test")
|
|
272
|
+
let apiGroup;
|
|
273
|
+
const apiGroupMatch = content.match(/api_group\s*=\s*"([^"]*)"/);
|
|
274
|
+
if (apiGroupMatch) {
|
|
275
|
+
apiGroup = apiGroupMatch[1];
|
|
276
|
+
}
|
|
277
|
+
return { apiGroup, content, name, type, verb };
|
|
221
278
|
}
|
|
222
279
|
/**
|
|
223
280
|
* Sanitize a document name for use as a filename.
|
|
@@ -225,9 +282,6 @@ Pulled 58 documents to ./backup
|
|
|
225
282
|
* characters that are unsafe in filenames.
|
|
226
283
|
*/
|
|
227
284
|
sanitizeFilename(name) {
|
|
228
|
-
return name
|
|
229
|
-
.replaceAll('"', '')
|
|
230
|
-
.replaceAll(/\s+/g, '_')
|
|
231
|
-
.replaceAll(/[<>:"/\\|?*]/g, '_');
|
|
285
|
+
return snakeCase(name.replaceAll('"', ''));
|
|
232
286
|
}
|
|
233
287
|
}
|