@xano/cli 0.0.41 → 0.0.42

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 CHANGED
@@ -106,9 +106,12 @@ xano workspace pull ./my-workspace --draft # Include draft changes
106
106
  # Push local files to workspace
107
107
  xano workspace push ./my-workspace
108
108
  xano workspace push ./my-workspace -b dev
109
- xano workspace push ./my-workspace --no-records # Schema only
110
- xano workspace push ./my-workspace --no-env # Skip env vars
111
- xano workspace push ./my-workspace --truncate # Truncate tables before import
109
+ xano workspace push ./my-workspace --partial # No workspace block required
110
+ xano workspace push ./my-workspace --delete # Delete objects not in the push
111
+ xano workspace push ./my-workspace --no-records # Schema only
112
+ xano workspace push ./my-workspace --no-env # Skip env vars
113
+ xano workspace push ./my-workspace --truncate # Truncate tables before import
114
+ xano workspace push ./my-workspace --no-sync-guids # Skip writing GUIDs back to local files
112
115
  ```
113
116
 
114
117
  ### Branches
@@ -7,7 +7,9 @@ export default class Push extends BaseCommand {
7
7
  static examples: string[];
8
8
  static flags: {
9
9
  branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ delete: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
11
  env: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ partial: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
13
  records: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
14
  'sync-guids': import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
15
  truncate: import("@oclif/core/interfaces").BooleanFlag<boolean>;
@@ -25,6 +25,12 @@ Pushed 58 documents from ./backup
25
25
  `,
26
26
  `$ xano workspace push ./my-workspace -b dev
27
27
  Pushed 42 documents from ./my-workspace
28
+ `,
29
+ `$ xano workspace push ./my-functions --partial
30
+ Push some files without a workspace block (implies --no-delete)
31
+ `,
32
+ `$ xano workspace push ./my-workspace --no-delete
33
+ Patch files without deleting existing workspace objects
28
34
  `,
29
35
  `$ xano workspace push ./my-workspace --no-records
30
36
  Push schema only, skip importing table records
@@ -49,12 +55,23 @@ Push schema only, skip records and environment variables
49
55
  description: 'Branch name (optional if set in profile, defaults to live)',
50
56
  required: false,
51
57
  }),
58
+ delete: Flags.boolean({
59
+ allowNo: true,
60
+ default: false,
61
+ description: 'Delete workspace objects not included in the push (default: false)',
62
+ required: false,
63
+ }),
52
64
  env: Flags.boolean({
53
65
  allowNo: true,
54
66
  default: true,
55
67
  description: 'Include environment variables in import (default: true, use --no-env to exclude)',
56
68
  required: false,
57
69
  }),
70
+ partial: Flags.boolean({
71
+ default: false,
72
+ description: 'Partial push — workspace block is not required, existing objects are kept (implies --no-delete)',
73
+ required: false,
74
+ }),
58
75
  records: Flags.boolean({
59
76
  allowNo: true,
60
77
  default: true,
@@ -146,10 +163,14 @@ Push schema only, skip records and environment variables
146
163
  }
147
164
  // Determine branch from flag or profile
148
165
  const branch = flags.branch || profile.branch || '';
166
+ // --partial implies --no-delete
167
+ const shouldDelete = flags.partial ? false : flags.delete;
149
168
  // Construct the API URL
150
169
  const queryParams = new URLSearchParams({
151
170
  branch,
171
+ delete: shouldDelete.toString(),
152
172
  env: flags.env.toString(),
173
+ partial: flags.partial.toString(),
153
174
  records: flags.records.toString(),
154
175
  truncate: flags.truncate.toString(),
155
176
  });
@@ -200,12 +221,33 @@ Push schema only, skip records and environment variables
200
221
  }
201
222
  // Write GUIDs back to local files
202
223
  if (flags['sync-guids'] && guidMap.length > 0) {
224
+ // Build a secondary lookup by type:name only (without verb/api_group)
225
+ // for cases where the server omits those fields
226
+ const baseKeyMap = new Map();
227
+ for (const [key, fp] of documentFileMap) {
228
+ const baseKey = key.split(':').slice(0, 2).join(':');
229
+ // Only use base key if there's no ambiguity (single entry per base key)
230
+ if (baseKeyMap.has(baseKey)) {
231
+ baseKeyMap.set(baseKey, ''); // Mark as ambiguous
232
+ }
233
+ else {
234
+ baseKeyMap.set(baseKey, fp);
235
+ }
236
+ }
203
237
  let updatedCount = 0;
204
238
  for (const entry of guidMap) {
205
239
  if (!entry.guid)
206
240
  continue;
207
241
  const key = buildDocumentKey(entry.type, entry.name, entry.verb, entry.api_group);
208
- const filePath = documentFileMap.get(key);
242
+ let filePath = documentFileMap.get(key);
243
+ // Fallback: try type:name only if full key didn't match
244
+ if (!filePath) {
245
+ const baseKey = `${entry.type}:${entry.name}`;
246
+ const basePath = baseKeyMap.get(baseKey);
247
+ if (basePath) {
248
+ filePath = basePath;
249
+ }
250
+ }
209
251
  if (!filePath) {
210
252
  if (flags.verbose) {
211
253
  this.log(` No local file found for ${entry.type} "${entry.name}", skipping GUID sync`);