@xano/cli 0.0.79 → 0.0.80-beta.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 +4 -2
- 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 +1748 -1734
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -123,6 +123,7 @@ xano workspace push ./my-workspace --delete # Delete objects not in
|
|
|
123
123
|
xano workspace push ./my-workspace --records # Include table records
|
|
124
124
|
xano workspace push ./my-workspace --env # Include environment variables
|
|
125
125
|
xano workspace push ./my-workspace --truncate # Truncate tables before import
|
|
126
|
+
xano workspace push ./my-workspace --no-transaction # Disable database transaction wrapping
|
|
126
127
|
xano workspace push ./my-workspace --no-sync-guids # Skip writing GUIDs back to local files
|
|
127
128
|
xano workspace push ./my-workspace --force # Skip preview and confirmation (for CI/CD)
|
|
128
129
|
|
|
@@ -331,9 +332,10 @@ xano tenant pull ./my-tenant -t <tenant_name> --draft
|
|
|
331
332
|
|
|
332
333
|
# Push local files to tenant
|
|
333
334
|
xano tenant push ./my-tenant -t <tenant_name>
|
|
334
|
-
xano tenant push ./my-tenant -t <tenant_name> --records
|
|
335
|
-
xano tenant push ./my-tenant -t <tenant_name> --env
|
|
335
|
+
xano tenant push ./my-tenant -t <tenant_name> --records # Include table records
|
|
336
|
+
xano tenant push ./my-tenant -t <tenant_name> --env # Include environment variables
|
|
336
337
|
xano tenant push ./my-tenant -t <tenant_name> --truncate
|
|
338
|
+
xano tenant push ./my-tenant -t <tenant_name> --no-transaction # Disable transaction wrapping
|
|
337
339
|
```
|
|
338
340
|
|
|
339
341
|
#### Deployments
|
|
@@ -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';
|