@xano/cli 0.0.78 → 0.0.80-beta.0
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 +1 -0
- package/dist/commands/tenant/push/index.d.ts +1 -0
- package/dist/commands/tenant/push/index.js +7 -0
- package/dist/commands/update/index.js +2 -0
- package/dist/commands/workspace/push/index.d.ts +1 -0
- package/dist/commands/workspace/push/index.js +28 -1
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.js +23 -1
- package/oclif.manifest.json +1140 -1126
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -117,6 +117,7 @@ xano workspace pull ./my-workspace --draft # Include draft changes
|
|
|
117
117
|
# Push local files to workspace
|
|
118
118
|
xano workspace push ./my-workspace
|
|
119
119
|
xano workspace push ./my-workspace -b dev
|
|
120
|
+
xano workspace push ./my-workspace --dry-run # Preview changes without pushing
|
|
120
121
|
xano workspace push ./my-workspace --partial # No workspace block required
|
|
121
122
|
xano workspace push ./my-workspace --delete # Delete objects not in the push
|
|
122
123
|
xano workspace push ./my-workspace --records # Include table records
|
|
@@ -9,6 +9,7 @@ export default class Push extends BaseCommand {
|
|
|
9
9
|
env: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
records: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
tenant: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
transaction: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
13
|
truncate: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
14
|
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
15
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -50,6 +50,12 @@ Truncate all table records before importing
|
|
|
50
50
|
description: 'Tenant name to push to',
|
|
51
51
|
required: true,
|
|
52
52
|
}),
|
|
53
|
+
transaction: Flags.boolean({
|
|
54
|
+
allowNo: true,
|
|
55
|
+
default: true,
|
|
56
|
+
description: 'Wrap import in a database transaction (use --no-transaction for debugging purposes)',
|
|
57
|
+
required: false,
|
|
58
|
+
}),
|
|
53
59
|
truncate: Flags.boolean({
|
|
54
60
|
default: false,
|
|
55
61
|
description: 'Truncate all table records before importing',
|
|
@@ -157,6 +163,7 @@ Truncate all table records before importing
|
|
|
157
163
|
const queryParams = new URLSearchParams({
|
|
158
164
|
env: flags.env.toString(),
|
|
159
165
|
records: flags.records.toString(),
|
|
166
|
+
transaction: flags.transaction.toString(),
|
|
160
167
|
truncate: flags.truncate.toString(),
|
|
161
168
|
});
|
|
162
169
|
const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/tenant/${tenantName}/multidoc?${queryParams.toString()}`;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
2
|
import { execSync } from 'node:child_process';
|
|
3
3
|
import BaseCommand from '../../base-command.js';
|
|
4
|
+
import { clearUpdateCache } from '../../update-check.js';
|
|
4
5
|
export default class Update extends BaseCommand {
|
|
5
6
|
static description = 'Update the Xano CLI to the latest version';
|
|
6
7
|
static examples = [`$ xano update`, `$ xano update --check`, `$ xano update --beta`];
|
|
@@ -31,6 +32,7 @@ export default class Update extends BaseCommand {
|
|
|
31
32
|
}
|
|
32
33
|
this.log(`Updating @xano/cli ${currentVersion} → ${latest}...`);
|
|
33
34
|
execSync(`npm install -g @xano/cli@${tag} --no-fund`, { stdio: 'inherit' });
|
|
35
|
+
clearUpdateCache();
|
|
34
36
|
this.log(`Updated to ${latest}`);
|
|
35
37
|
}
|
|
36
38
|
catch (error) {
|
|
@@ -13,6 +13,7 @@ export default class Push extends BaseCommand {
|
|
|
13
13
|
partial: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
14
|
records: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
15
|
'sync-guids': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
+
transaction: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
17
|
truncate: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
18
|
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
19
|
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
@@ -86,6 +86,12 @@ Truncate all table records before importing
|
|
|
86
86
|
description: 'Write server-assigned GUIDs back to local files (use --no-sync-guids to skip)',
|
|
87
87
|
required: false,
|
|
88
88
|
}),
|
|
89
|
+
transaction: Flags.boolean({
|
|
90
|
+
allowNo: true,
|
|
91
|
+
default: true,
|
|
92
|
+
description: 'Wrap import in a database transaction (use --no-transaction for debugging purposes)',
|
|
93
|
+
required: false,
|
|
94
|
+
}),
|
|
89
95
|
truncate: Flags.boolean({
|
|
90
96
|
default: false,
|
|
91
97
|
description: 'Truncate all table records before importing',
|
|
@@ -179,6 +185,7 @@ Truncate all table records before importing
|
|
|
179
185
|
env: flags.env.toString(),
|
|
180
186
|
partial: flags.partial.toString(),
|
|
181
187
|
records: flags.records.toString(),
|
|
188
|
+
transaction: flags.transaction.toString(),
|
|
182
189
|
truncate: flags.truncate.toString(),
|
|
183
190
|
});
|
|
184
191
|
// POST the multidoc to the API
|
|
@@ -245,7 +252,27 @@ Truncate all table records before importing
|
|
|
245
252
|
this.renderPreview(preview, shouldDelete, workspaceId, flags.verbose);
|
|
246
253
|
// Check if there are any actual changes (exclude deletes when --delete is off)
|
|
247
254
|
const hasChanges = Object.values(preview.summary).some((c) => c.created > 0 || c.updated > 0 || (shouldDelete && c.deleted > 0) || c.truncated > 0);
|
|
248
|
-
if
|
|
255
|
+
// Detect if local files contain records that would be imported
|
|
256
|
+
const tablesWithRecords = flags.records
|
|
257
|
+
? documentEntries
|
|
258
|
+
.filter((d) => /^table\s+/m.test(d.content) && /\bitems\s*=\s*\[/m.test(d.content))
|
|
259
|
+
.map((d) => {
|
|
260
|
+
const nameMatch = d.content.match(/^table\s+(\S+)/m);
|
|
261
|
+
const itemCount = (d.content.match(/^\s*\{$/gm) || []).length;
|
|
262
|
+
return { name: nameMatch ? nameMatch[1] : 'unknown', records: itemCount };
|
|
263
|
+
})
|
|
264
|
+
: [];
|
|
265
|
+
const hasLocalRecords = tablesWithRecords.length > 0;
|
|
266
|
+
if (hasLocalRecords) {
|
|
267
|
+
this.log('');
|
|
268
|
+
this.log(ux.colorize('bold', '--- Records ---'));
|
|
269
|
+
this.log('');
|
|
270
|
+
for (const t of tablesWithRecords) {
|
|
271
|
+
this.log(` ${ux.colorize('yellow', 'UPSERT'.padEnd(16))} ${'table'.padEnd(18)} ${t.name} (${t.records} records)`);
|
|
272
|
+
}
|
|
273
|
+
this.log('');
|
|
274
|
+
}
|
|
275
|
+
if (!hasChanges && !hasLocalRecords) {
|
|
249
276
|
this.log('');
|
|
250
277
|
this.log('No changes to push.');
|
|
251
278
|
return;
|
package/dist/update-check.d.ts
CHANGED
package/dist/update-check.js
CHANGED
|
@@ -7,6 +7,18 @@ const CHECK_INTERVAL_MS = 8 * 60 * 60 * 1000; // 8 hours
|
|
|
7
7
|
function isBeta(version) {
|
|
8
8
|
return version.includes('beta') || version.includes('alpha') || version.includes('rc');
|
|
9
9
|
}
|
|
10
|
+
/** Returns true if `latest` is a higher semver than `current`. */
|
|
11
|
+
function isNewer(latest, current) {
|
|
12
|
+
const a = latest.split('.').map(Number);
|
|
13
|
+
const b = current.split('.').map(Number);
|
|
14
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
15
|
+
if ((a[i] ?? 0) > (b[i] ?? 0))
|
|
16
|
+
return true;
|
|
17
|
+
if ((a[i] ?? 0) < (b[i] ?? 0))
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
10
22
|
function readCache() {
|
|
11
23
|
try {
|
|
12
24
|
if (!fs.existsSync(UPDATE_CHECK_FILE))
|
|
@@ -21,6 +33,16 @@ function readCache() {
|
|
|
21
33
|
return null;
|
|
22
34
|
}
|
|
23
35
|
}
|
|
36
|
+
export function clearUpdateCache() {
|
|
37
|
+
try {
|
|
38
|
+
if (fs.existsSync(UPDATE_CHECK_FILE)) {
|
|
39
|
+
fs.unlinkSync(UPDATE_CHECK_FILE);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Silently fail
|
|
44
|
+
}
|
|
45
|
+
}
|
|
24
46
|
function writeCache(latestVersion) {
|
|
25
47
|
try {
|
|
26
48
|
const dir = path.dirname(UPDATE_CHECK_FILE);
|
|
@@ -62,7 +84,7 @@ export function checkForUpdate(currentVersion, forceCheck = false) {
|
|
|
62
84
|
writeCache(latestVersion);
|
|
63
85
|
}
|
|
64
86
|
}
|
|
65
|
-
if (!latestVersion || latestVersion
|
|
87
|
+
if (!latestVersion || !isNewer(latestVersion, currentVersion))
|
|
66
88
|
return null;
|
|
67
89
|
const yellow = '\u001B[33m';
|
|
68
90
|
const cyan = '\u001B[36m';
|