@xano/cli 1.3.3 → 1.3.5-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 +137 -3
- package/dist/base-command.d.ts +12 -1
- package/dist/base-command.js +36 -22
- package/dist/commands/branch/set_live/index.d.ts +14 -0
- package/dist/commands/branch/set_live/index.js +38 -0
- package/dist/commands/ephemeral/push/index.js +6 -1
- package/dist/commands/function/create/index.d.ts +15 -0
- package/dist/commands/function/create/index.js +39 -0
- package/dist/commands/function/edit/index.d.ts +15 -0
- package/dist/commands/function/edit/index.js +39 -0
- package/dist/commands/function/run/index.js +5 -11
- package/dist/commands/policy/catalogue/index.d.ts +16 -0
- package/dist/commands/policy/catalogue/index.js +60 -0
- package/dist/commands/policy/coverage/index.d.ts +17 -0
- package/dist/commands/policy/coverage/index.js +33 -0
- package/dist/commands/policy/create/index.d.ts +18 -0
- package/dist/commands/policy/create/index.js +44 -0
- package/dist/commands/policy/delete/index.d.ts +19 -0
- package/dist/commands/policy/delete/index.js +61 -0
- package/dist/commands/policy/evaluate/index.d.ts +32 -0
- package/dist/commands/policy/evaluate/index.js +71 -0
- package/dist/commands/policy/list/index.d.ts +14 -0
- package/dist/commands/policy/list/index.js +21 -0
- package/dist/commands/policy/parse/index.d.ts +19 -0
- package/dist/commands/policy/parse/index.js +18 -0
- package/dist/commands/policy/publish/index.d.ts +20 -0
- package/dist/commands/policy/publish/index.js +38 -0
- package/dist/commands/policy/runs/index.d.ts +54 -0
- package/dist/commands/policy/runs/index.js +273 -0
- package/dist/commands/policy/status/index.d.ts +21 -0
- package/dist/commands/policy/status/index.js +54 -0
- package/dist/commands/release/create/index.js +4 -0
- package/dist/commands/release/deploy/index.d.ts +19 -0
- package/dist/commands/release/deploy/index.js +68 -6
- package/dist/commands/release/import/index.js +5 -1
- package/dist/commands/release/list/index.d.ts +7 -0
- package/dist/commands/release/list/index.js +46 -9
- package/dist/commands/release/push/index.js +19 -1
- package/dist/commands/sandbox/delete/index.js +8 -0
- package/dist/commands/sandbox/pull/index.d.ts +7 -0
- package/dist/commands/sandbox/pull/index.js +49 -0
- package/dist/commands/sandbox/push/index.d.ts +4 -0
- package/dist/commands/sandbox/push/index.js +59 -2
- package/dist/commands/sandbox/reset/index.js +8 -0
- package/dist/commands/skills/pull/index.d.ts +30 -0
- package/dist/commands/skills/pull/index.js +118 -0
- package/dist/commands/tenant/create/index.d.ts +3 -0
- package/dist/commands/tenant/create/index.js +21 -0
- package/dist/commands/tenant/deploy_release/index.d.ts +40 -0
- package/dist/commands/tenant/deploy_release/index.js +182 -4
- package/dist/commands/tenant/edit/index.d.ts +2 -0
- package/dist/commands/tenant/edit/index.js +39 -4
- package/dist/commands/tenant_deploy_request/bypass/index.d.ts +31 -0
- package/dist/commands/tenant_deploy_request/bypass/index.js +109 -0
- package/dist/commands/tenant_deploy_request/create/index.d.ts +21 -0
- package/dist/commands/tenant_deploy_request/create/index.js +108 -0
- package/dist/commands/tenant_deploy_request/edit/index.d.ts +22 -0
- package/dist/commands/tenant_deploy_request/edit/index.js +103 -0
- package/dist/commands/tenant_deploy_request/get/index.d.ts +25 -0
- package/dist/commands/tenant_deploy_request/get/index.js +113 -0
- package/dist/commands/tenant_deploy_request/list/index.d.ts +20 -0
- package/dist/commands/tenant_deploy_request/list/index.js +122 -0
- package/dist/commands/tenant_deploy_request/revision/index.d.ts +21 -0
- package/dist/commands/tenant_deploy_request/revision/index.js +83 -0
- package/dist/commands/tenant_deploy_request/set_status/index.d.ts +38 -0
- package/dist/commands/tenant_deploy_request/set_status/index.js +159 -0
- package/dist/commands/workspace/pull/index.d.ts +17 -0
- package/dist/commands/workspace/pull/index.js +124 -7
- package/dist/commands/workspace/push/index.d.ts +23 -0
- package/dist/commands/workspace/push/index.js +188 -6
- package/dist/policy-command.d.ts +91 -0
- package/dist/policy-command.js +95 -0
- package/dist/utils/document-parser.d.ts +10 -0
- package/dist/utils/document-parser.js +21 -0
- package/dist/utils/export-compare.d.ts +52 -0
- package/dist/utils/export-compare.js +134 -0
- package/dist/utils/local-config.d.ts +23 -0
- package/dist/utils/local-config.js +62 -2
- package/dist/utils/multidoc-push.d.ts +124 -4
- package/dist/utils/multidoc-push.js +670 -49
- package/dist/utils/object-fetch.d.ts +86 -0
- package/dist/utils/object-fetch.js +265 -0
- package/dist/utils/policy/catalogue.d.ts +85 -0
- package/dist/utils/policy/catalogue.js +196 -0
- package/dist/utils/policy/coverage.d.ts +19 -0
- package/dist/utils/policy/coverage.js +93 -0
- package/dist/utils/policy/errors.d.ts +20 -0
- package/dist/utils/policy/errors.js +93 -0
- package/dist/utils/policy/feedback.d.ts +90 -0
- package/dist/utils/policy/feedback.js +210 -0
- package/dist/utils/policy/findings.d.ts +29 -0
- package/dist/utils/policy/findings.js +82 -0
- package/dist/utils/policy/gate.d.ts +138 -0
- package/dist/utils/policy/gate.js +193 -0
- package/dist/utils/policy/permission.d.ts +7 -0
- package/dist/utils/policy/permission.js +55 -0
- package/dist/utils/policy/push-gate.d.ts +5 -0
- package/dist/utils/policy/push-gate.js +43 -0
- package/dist/utils/policy/release.d.ts +85 -0
- package/dist/utils/policy/release.js +117 -0
- package/dist/utils/policy/request.d.ts +55 -0
- package/dist/utils/policy/request.js +119 -0
- package/dist/utils/policy/runs.d.ts +30 -0
- package/dist/utils/policy/runs.js +101 -0
- package/dist/utils/policy/status.d.ts +55 -0
- package/dist/utils/policy/status.js +127 -0
- package/dist/utils/policy/template.d.ts +66 -0
- package/dist/utils/policy/template.js +152 -0
- package/dist/utils/policy/types.d.ts +295 -0
- package/dist/utils/policy/types.js +1 -0
- package/dist/utils/reference-checker.d.ts +3 -0
- package/dist/utils/reference-checker.js +3 -2
- package/dist/utils/sandbox-marker.d.ts +9 -0
- package/dist/utils/sandbox-marker.js +119 -0
- package/dist/utils/sync-state.d.ts +71 -0
- package/dist/utils/sync-state.js +353 -0
- package/oclif.manifest.json +6472 -3181
- package/package.json +9 -1
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { buildDocumentKey, parseDocument } from './document-parser.js';
|
|
2
|
+
export const ITEMS_BLOCK_REGEX = /^([ \t]*)items\s*=\s*\[[\s\S]*?\n\1\]/m;
|
|
3
|
+
/**
|
|
4
|
+
* Split a GET /multidoc response into parsed documents, skipping empty or invalid segments.
|
|
5
|
+
*/
|
|
6
|
+
export function parseExportDocuments(multidoc) {
|
|
7
|
+
const documents = [];
|
|
8
|
+
for (const raw of multidoc.split('\n---\n')) {
|
|
9
|
+
const trimmed = raw.trim();
|
|
10
|
+
if (!trimmed)
|
|
11
|
+
continue;
|
|
12
|
+
const parsed = parseDocument(trimmed);
|
|
13
|
+
if (parsed)
|
|
14
|
+
documents.push(parsed);
|
|
15
|
+
}
|
|
16
|
+
return documents;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Reinsert a local table `items = [...]` block when the server export omitted records.
|
|
20
|
+
* If the export already has an items block, the server copy wins.
|
|
21
|
+
*/
|
|
22
|
+
export function preserveLocalTableRecords(localContent, serverContent) {
|
|
23
|
+
if (ITEMS_BLOCK_REGEX.test(serverContent)) {
|
|
24
|
+
return serverContent;
|
|
25
|
+
}
|
|
26
|
+
const localMatch = localContent.match(ITEMS_BLOCK_REGEX);
|
|
27
|
+
if (!localMatch) {
|
|
28
|
+
return serverContent;
|
|
29
|
+
}
|
|
30
|
+
const lines = serverContent.split('\n');
|
|
31
|
+
let insertIndex = -1;
|
|
32
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
33
|
+
if (lines[i].trim() === '}') {
|
|
34
|
+
insertIndex = i;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (insertIndex === -1) {
|
|
39
|
+
return serverContent;
|
|
40
|
+
}
|
|
41
|
+
lines.splice(insertIndex, 0, ...localMatch[0].split('\n'));
|
|
42
|
+
return lines.join('\n');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Index local files by document key (and GUID) so an export document can be paired
|
|
46
|
+
* with the file it belongs to. Ambiguous case-insensitive keys are marked empty
|
|
47
|
+
* rather than guessed.
|
|
48
|
+
*/
|
|
49
|
+
export function indexLocalDocuments(files, localContents) {
|
|
50
|
+
const byKey = new Map(files);
|
|
51
|
+
const byKeyLower = new Map();
|
|
52
|
+
for (const [key, filePath] of files) {
|
|
53
|
+
const lower = key.toLowerCase();
|
|
54
|
+
if (byKeyLower.has(lower) && byKeyLower.get(lower) !== filePath) {
|
|
55
|
+
byKeyLower.set(lower, '');
|
|
56
|
+
}
|
|
57
|
+
else if (!byKeyLower.has(lower)) {
|
|
58
|
+
byKeyLower.set(lower, filePath);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const byGuid = new Map();
|
|
62
|
+
for (const [filePath, local] of localContents) {
|
|
63
|
+
const parsed = parseDocument(local);
|
|
64
|
+
if (parsed?.guid)
|
|
65
|
+
byGuid.set(parsed.guid, filePath);
|
|
66
|
+
}
|
|
67
|
+
return { byGuid, byKey, byKeyLower };
|
|
68
|
+
}
|
|
69
|
+
export function resolveMatchedPath(doc, index) {
|
|
70
|
+
const key = buildDocumentKey(doc.type, doc.name, doc.verb, doc.apiGroup);
|
|
71
|
+
return index.byKey.get(key) || index.byKeyLower.get(key.toLowerCase()) || (doc.guid ? index.byGuid.get(doc.guid) : undefined);
|
|
72
|
+
}
|
|
73
|
+
export function selectWritebacks(exported, pushedFiles, localContents, options) {
|
|
74
|
+
const result = [];
|
|
75
|
+
const index = indexLocalDocuments(pushedFiles, localContents);
|
|
76
|
+
for (const doc of exported) {
|
|
77
|
+
const filePath = resolveMatchedPath(doc, index);
|
|
78
|
+
if (!filePath)
|
|
79
|
+
continue;
|
|
80
|
+
const local = localContents.get(filePath) ?? '';
|
|
81
|
+
let { content } = doc;
|
|
82
|
+
if (!options.includeRecords && doc.type === 'table') {
|
|
83
|
+
content = preserveLocalTableRecords(local, content);
|
|
84
|
+
}
|
|
85
|
+
if (local.trim() === content.trim())
|
|
86
|
+
continue;
|
|
87
|
+
result.push({ content, filePath });
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
export function compareLocalToExport(localEntries, exported) {
|
|
92
|
+
const pushedFiles = new Map();
|
|
93
|
+
const localContents = new Map();
|
|
94
|
+
const byPath = new Map();
|
|
95
|
+
for (const entry of localEntries) {
|
|
96
|
+
const parsed = parseDocument(entry.content);
|
|
97
|
+
if (!parsed)
|
|
98
|
+
continue;
|
|
99
|
+
const key = buildDocumentKey(parsed.type, parsed.name, parsed.verb, parsed.apiGroup);
|
|
100
|
+
pushedFiles.set(key, entry.filePath);
|
|
101
|
+
localContents.set(entry.filePath, entry.content);
|
|
102
|
+
byPath.set(entry.filePath, entry);
|
|
103
|
+
}
|
|
104
|
+
const index = indexLocalDocuments(pushedFiles, localContents);
|
|
105
|
+
const matchedLocal = new Set();
|
|
106
|
+
const candidates = [];
|
|
107
|
+
const identical = [];
|
|
108
|
+
const serverOnly = [];
|
|
109
|
+
for (const doc of exported) {
|
|
110
|
+
const filePath = resolveMatchedPath(doc, index);
|
|
111
|
+
if (!filePath) {
|
|
112
|
+
serverOnly.push(doc);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
matchedLocal.add(filePath);
|
|
116
|
+
const local = byPath.get(filePath);
|
|
117
|
+
if (!local)
|
|
118
|
+
continue;
|
|
119
|
+
if (local.content.trim() === doc.content.trim()) {
|
|
120
|
+
identical.push(local);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
candidates.push(local);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const unmatchedLocal = [];
|
|
127
|
+
for (const entry of localEntries) {
|
|
128
|
+
if (matchedLocal.has(entry.filePath))
|
|
129
|
+
continue;
|
|
130
|
+
unmatchedLocal.push(entry);
|
|
131
|
+
candidates.push(entry);
|
|
132
|
+
}
|
|
133
|
+
return { candidates, identical, serverOnly, unmatchedLocal };
|
|
134
|
+
}
|
|
@@ -4,9 +4,12 @@ export declare const LOCAL_PROFILE_FILENAME = "profile.yaml";
|
|
|
4
4
|
export interface LocalProfileConfig {
|
|
5
5
|
account_origin?: string;
|
|
6
6
|
branch?: string;
|
|
7
|
+
fast?: boolean;
|
|
7
8
|
instance_origin?: string;
|
|
8
9
|
profile?: string;
|
|
9
10
|
workspace?: string;
|
|
11
|
+
writeback?: boolean;
|
|
12
|
+
writeback_object_limit?: number;
|
|
10
13
|
}
|
|
11
14
|
/**
|
|
12
15
|
* Parse the raw contents of a profile.yaml.
|
|
@@ -34,8 +37,28 @@ export declare function resolveProfileSelection(params: {
|
|
|
34
37
|
applyLocal: boolean;
|
|
35
38
|
profileName: string;
|
|
36
39
|
};
|
|
40
|
+
export type WorkspacePushDefaultKey = 'fast' | 'writeback';
|
|
41
|
+
/**
|
|
42
|
+
* Resolve push --fast/--writeback from the explicit flag, then
|
|
43
|
+
* profile.yaml, then false. `--sync` ignores a profile.yaml `fast: true`
|
|
44
|
+
* instead of erroring; an explicit `--fast --sync` is left as-is for executePush.
|
|
45
|
+
* Used by both workspace push and sandbox push.
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolvePushDefaults(args: {
|
|
48
|
+
flagFast?: boolean;
|
|
49
|
+
flagWriteback?: boolean;
|
|
50
|
+
localFast?: boolean;
|
|
51
|
+
localWriteback?: boolean;
|
|
52
|
+
sync: boolean;
|
|
53
|
+
}): {
|
|
54
|
+
fast: boolean;
|
|
55
|
+
fromLocal: WorkspacePushDefaultKey[];
|
|
56
|
+
writeback: boolean;
|
|
57
|
+
};
|
|
37
58
|
/** Format the one-line banner shown when a local profile.yaml is in effect. */
|
|
38
59
|
export declare function formatLocalProfileBanner(profileName: string, workspace: string | undefined, relativePath: string): string;
|
|
60
|
+
/** Format the one-line banner when profile.yaml turns on workspace push flags. */
|
|
61
|
+
export declare function formatWorkspacePushDefaultsBanner(fromLocal: WorkspacePushDefaultKey[], relativePath: string): string;
|
|
39
62
|
/**
|
|
40
63
|
* Walk up from `startDir` to the filesystem root, returning the path of the
|
|
41
64
|
* first profile.yaml found, or null if none exists.
|
|
@@ -2,7 +2,9 @@ import * as yaml from 'js-yaml';
|
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
3
|
import { dirname, join, resolve } from 'node:path';
|
|
4
4
|
export const LOCAL_PROFILE_FILENAME = 'profile.yaml';
|
|
5
|
-
const
|
|
5
|
+
const RECOGNIZED_STRING_KEYS = ['profile', 'workspace', 'instance_origin', 'account_origin', 'branch'];
|
|
6
|
+
const RECOGNIZED_BOOLEAN_KEYS = ['fast', 'writeback'];
|
|
7
|
+
const RECOGNIZED_NON_NEGATIVE_INTEGER_KEYS = ['writeback_object_limit'];
|
|
6
8
|
/**
|
|
7
9
|
* Fields that may be layered onto a resolved profile (everything except the profile pointer).
|
|
8
10
|
* NOTE: `insecure` is intentionally NOT listed here — a project file must never silently
|
|
@@ -26,11 +28,28 @@ export function parseLocalProfile(raw) {
|
|
|
26
28
|
`Tokens belong in credentials.yaml — reference a profile by name instead.`);
|
|
27
29
|
}
|
|
28
30
|
const config = {};
|
|
29
|
-
for (const key of
|
|
31
|
+
for (const key of RECOGNIZED_STRING_KEYS) {
|
|
30
32
|
if (obj[key] !== undefined && obj[key] !== null) {
|
|
31
33
|
config[key] = String(obj[key]);
|
|
32
34
|
}
|
|
33
35
|
}
|
|
36
|
+
for (const key of RECOGNIZED_BOOLEAN_KEYS) {
|
|
37
|
+
if (obj[key] === undefined || obj[key] === null)
|
|
38
|
+
continue;
|
|
39
|
+
if (typeof obj[key] !== 'boolean') {
|
|
40
|
+
throw new TypeError(`profile.yaml: ${key} must be a boolean`);
|
|
41
|
+
}
|
|
42
|
+
config[key] = obj[key];
|
|
43
|
+
}
|
|
44
|
+
for (const key of RECOGNIZED_NON_NEGATIVE_INTEGER_KEYS) {
|
|
45
|
+
if (obj[key] === undefined || obj[key] === null)
|
|
46
|
+
continue;
|
|
47
|
+
const value = obj[key];
|
|
48
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {
|
|
49
|
+
throw new TypeError(`profile.yaml: ${key} must be a non-negative integer`);
|
|
50
|
+
}
|
|
51
|
+
config[key] = value;
|
|
52
|
+
}
|
|
34
53
|
if (Object.keys(config).length === 0) {
|
|
35
54
|
return null;
|
|
36
55
|
}
|
|
@@ -63,11 +82,52 @@ export function resolveProfileSelection(params) {
|
|
|
63
82
|
}
|
|
64
83
|
return { applyLocal: false, profileName: params.defaultProfile };
|
|
65
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve push --fast/--writeback from the explicit flag, then
|
|
87
|
+
* profile.yaml, then false. `--sync` ignores a profile.yaml `fast: true`
|
|
88
|
+
* instead of erroring; an explicit `--fast --sync` is left as-is for executePush.
|
|
89
|
+
* Used by both workspace push and sandbox push.
|
|
90
|
+
*/
|
|
91
|
+
export function resolvePushDefaults(args) {
|
|
92
|
+
const fromLocal = [];
|
|
93
|
+
let fast;
|
|
94
|
+
if (args.flagFast !== undefined) {
|
|
95
|
+
fast = args.flagFast;
|
|
96
|
+
}
|
|
97
|
+
else if (args.sync) {
|
|
98
|
+
fast = false;
|
|
99
|
+
}
|
|
100
|
+
else if (args.localFast === undefined) {
|
|
101
|
+
fast = false;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
fast = args.localFast;
|
|
105
|
+
if (args.localFast)
|
|
106
|
+
fromLocal.push('fast');
|
|
107
|
+
}
|
|
108
|
+
let writeback;
|
|
109
|
+
if (args.flagWriteback !== undefined) {
|
|
110
|
+
writeback = args.flagWriteback;
|
|
111
|
+
}
|
|
112
|
+
else if (args.localWriteback === undefined) {
|
|
113
|
+
writeback = false;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
writeback = args.localWriteback;
|
|
117
|
+
if (args.localWriteback)
|
|
118
|
+
fromLocal.push('writeback');
|
|
119
|
+
}
|
|
120
|
+
return { fast, fromLocal, writeback };
|
|
121
|
+
}
|
|
66
122
|
/** Format the one-line banner shown when a local profile.yaml is in effect. */
|
|
67
123
|
export function formatLocalProfileBanner(profileName, workspace, relativePath) {
|
|
68
124
|
const workspaceClause = workspace ? ` (workspace ${workspace})` : '';
|
|
69
125
|
return `Using profile '${profileName}'${workspaceClause} · ${relativePath}`;
|
|
70
126
|
}
|
|
127
|
+
/** Format the one-line banner when profile.yaml turns on workspace push flags. */
|
|
128
|
+
export function formatWorkspacePushDefaultsBanner(fromLocal, relativePath) {
|
|
129
|
+
return `Using ${fromLocal.map((key) => `--${key}`).join(' ')} · ${relativePath}`;
|
|
130
|
+
}
|
|
71
131
|
/**
|
|
72
132
|
* Walk up from `startDir` to the filesystem root, returning the path of the
|
|
73
133
|
* first profile.yaml found, or null if none exists.
|
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import { Command } from '@oclif/core';
|
|
1
|
+
import { Command, Errors } from '@oclif/core';
|
|
2
2
|
import { type BadIndex, type BadReference } from './reference-checker.js';
|
|
3
|
+
import { type SyncFileEntry, type SyncTargetIdentity, type SyncTargetState } from './sync-state.js';
|
|
3
4
|
export interface PushFlags {
|
|
4
5
|
delete: boolean;
|
|
5
6
|
'dry-run': boolean;
|
|
6
7
|
env: boolean;
|
|
7
8
|
exclude?: string[];
|
|
9
|
+
fast?: boolean;
|
|
8
10
|
force: boolean;
|
|
9
11
|
guids: boolean;
|
|
10
12
|
include?: string[];
|
|
11
13
|
records: boolean;
|
|
14
|
+
refresh?: boolean;
|
|
12
15
|
sync: boolean;
|
|
13
16
|
transaction: boolean;
|
|
14
17
|
truncate: boolean;
|
|
15
18
|
verbose: boolean;
|
|
19
|
+
writeback?: boolean;
|
|
20
|
+
writebackDiff?: string;
|
|
21
|
+
writebackObjectLimit?: number;
|
|
16
22
|
}
|
|
17
23
|
export interface PushTarget {
|
|
18
24
|
/** Build the dry-run URL. Return null if dry-run is not supported for this target. */
|
|
@@ -21,6 +27,11 @@ export interface PushTarget {
|
|
|
21
27
|
buildPushUrl: (queryParams: URLSearchParams) => string;
|
|
22
28
|
/** CLI version string */
|
|
23
29
|
cliVersion: string;
|
|
30
|
+
/**
|
|
31
|
+
* Guidance for a refusal this target recognises, given the HTTP status and the server's payload.
|
|
32
|
+
* A preview or import refused that way stops with the message and this guidance appended.
|
|
33
|
+
*/
|
|
34
|
+
explainRefusal?: (status: number, payload: unknown) => string | undefined;
|
|
24
35
|
/** Instance origin URL (e.g., "https://x123-abcd-1234.xano.io") */
|
|
25
36
|
instanceOrigin: string;
|
|
26
37
|
/** Human-readable label for log messages (e.g., "sandbox environment", "workspace 40") */
|
|
@@ -47,6 +58,15 @@ export interface KnowledgeConfig {
|
|
|
47
58
|
/** Root directory containing the `knowledge/` folder. */
|
|
48
59
|
rootDir: string;
|
|
49
60
|
}
|
|
61
|
+
export type PushSyncTarget = {
|
|
62
|
+
instanceOrigin: string;
|
|
63
|
+
kind: 'sandbox';
|
|
64
|
+
markerDir: string;
|
|
65
|
+
} | {
|
|
66
|
+
instanceOrigin: string;
|
|
67
|
+
kind: 'workspace';
|
|
68
|
+
workspace: string;
|
|
69
|
+
};
|
|
50
70
|
export interface PushContext {
|
|
51
71
|
accessToken: string;
|
|
52
72
|
branch: string;
|
|
@@ -54,8 +74,64 @@ export interface PushContext {
|
|
|
54
74
|
inputDir: string;
|
|
55
75
|
/** Optional knowledge sync config. Only workspace push sets this. */
|
|
56
76
|
knowledge?: KnowledgeConfig;
|
|
77
|
+
/** Where progress and diagnostics go; defaults to the command's stdout. */
|
|
78
|
+
log?: (message: string) => void;
|
|
79
|
+
/** Optional sync-record target. Workspace and sandbox push set this when they want a record. */
|
|
80
|
+
syncTarget?: PushSyncTarget;
|
|
57
81
|
verboseFetch: (url: string, options: RequestInit, verbose: boolean, authToken?: string) => Promise<Response>;
|
|
58
82
|
}
|
|
83
|
+
/** The fetch fields writeback reads. */
|
|
84
|
+
export interface WritebackHttpResponse {
|
|
85
|
+
ok: boolean;
|
|
86
|
+
status: number;
|
|
87
|
+
text: () => Promise<string>;
|
|
88
|
+
}
|
|
89
|
+
export interface DryRunSummary {
|
|
90
|
+
created: number;
|
|
91
|
+
deleted: number;
|
|
92
|
+
truncated: number;
|
|
93
|
+
unchanged: number;
|
|
94
|
+
updated: number;
|
|
95
|
+
}
|
|
96
|
+
export interface DryRunOperation {
|
|
97
|
+
action: string;
|
|
98
|
+
details: string;
|
|
99
|
+
name: string;
|
|
100
|
+
reason?: string;
|
|
101
|
+
type: string;
|
|
102
|
+
}
|
|
103
|
+
export interface DryRunResult {
|
|
104
|
+
operations: DryRunOperation[];
|
|
105
|
+
/** True when the sandbox currently holds a different source workspace than the one being pushed. */
|
|
106
|
+
source_workspace_mismatch?: boolean;
|
|
107
|
+
summary: Record<string, DryRunSummary>;
|
|
108
|
+
workspace_name?: string;
|
|
109
|
+
}
|
|
110
|
+
/** What a push did, for the calling command to report. */
|
|
111
|
+
export interface PushResult {
|
|
112
|
+
knowledge: {
|
|
113
|
+
deleted: number;
|
|
114
|
+
imported: number;
|
|
115
|
+
};
|
|
116
|
+
preview: DryRunResult | null;
|
|
117
|
+
/** The multidoc import's response body; absent when no multidoc was imported. */
|
|
118
|
+
response?: Record<string, unknown>;
|
|
119
|
+
/** The documents the multidoc import carried. */
|
|
120
|
+
sent: Array<{
|
|
121
|
+
content: string;
|
|
122
|
+
filePath: string;
|
|
123
|
+
}>;
|
|
124
|
+
/** Why the push stopped before writing anything, when it did. */
|
|
125
|
+
stopped?: 'blocked' | 'cancelled' | 'dry-run' | 'no-changes';
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* A push that failed after its multidoc import landed. The import is not rolled back, so the error
|
|
129
|
+
* carries what it did for the calling command to report beside the failure.
|
|
130
|
+
*/
|
|
131
|
+
export declare class FailedAfterImportError extends Errors.CLIError {
|
|
132
|
+
readonly imported: PushResult;
|
|
133
|
+
constructor(message: string, imported: PushResult);
|
|
134
|
+
}
|
|
59
135
|
/**
|
|
60
136
|
* Filter document entries down to the ones the dry-run preview reports as changed,
|
|
61
137
|
* used to send only the changed documents during a partial (non-`--sync`) push.
|
|
@@ -144,10 +220,12 @@ export declare function deletesHittingFilteredOut(operations: Array<{
|
|
|
144
220
|
relPath: string;
|
|
145
221
|
type: string;
|
|
146
222
|
}>;
|
|
223
|
+
export declare function pathMatchesFilters(relPath: string, inputDir: string, include: string[] | undefined, exclude: string[] | undefined): boolean;
|
|
147
224
|
/**
|
|
148
|
-
* Read .xs files into document entries, skipping empty files.
|
|
225
|
+
* Read .xs files into document entries, skipping empty files. When `raw` is given, the
|
|
226
|
+
* untrimmed bytes of each returned file are stored in it, keyed by file path.
|
|
149
227
|
*/
|
|
150
|
-
export declare function readDocuments(files: string[]): Array<{
|
|
228
|
+
export declare function readDocuments(files: string[], raw?: Map<string, string>): Array<{
|
|
151
229
|
content: string;
|
|
152
230
|
filePath: string;
|
|
153
231
|
}>;
|
|
@@ -192,7 +270,48 @@ export declare function confirm(message: string): Promise<boolean>;
|
|
|
192
270
|
* Execute a multidoc push with preview, validation, partial mode, and GUID sync.
|
|
193
271
|
* Shared by both sandbox:push and workspace:push commands.
|
|
194
272
|
*/
|
|
195
|
-
export declare function executePush(ctx: PushContext, target: PushTarget, flags: PushFlags): Promise<
|
|
273
|
+
export declare function executePush(ctx: PushContext, target: PushTarget, flags: PushFlags): Promise<PushResult>;
|
|
274
|
+
export interface WritebackResult {
|
|
275
|
+
elapsedMs: number;
|
|
276
|
+
/** Object ids resolved by per-object writeback, keyed by relative path. */
|
|
277
|
+
ids: Record<string, SyncFileEntry>;
|
|
278
|
+
/** The exact bytes written to each rewritten file. */
|
|
279
|
+
written: Array<{
|
|
280
|
+
content: string;
|
|
281
|
+
filePath: string;
|
|
282
|
+
}>;
|
|
283
|
+
}
|
|
284
|
+
export declare function writeBackFormattedDocuments(args: {
|
|
285
|
+
accessToken: string;
|
|
286
|
+
branch: string;
|
|
287
|
+
command: Command;
|
|
288
|
+
includeEnv: boolean;
|
|
289
|
+
includeRecords: boolean;
|
|
290
|
+
inputDir?: string;
|
|
291
|
+
isLiveBranch?: boolean;
|
|
292
|
+
/** Where progress goes; defaults to the command's stdout. */
|
|
293
|
+
log?: (message: string) => void;
|
|
294
|
+
/**
|
|
295
|
+
* The bytes each file held when it was pushed (after GUID sync). A file whose disk content
|
|
296
|
+
* no longer matches was edited during the push, so writeback leaves it alone.
|
|
297
|
+
*/
|
|
298
|
+
pushedBytes?: Map<string, string>;
|
|
299
|
+
pushedEntries: Array<{
|
|
300
|
+
content: string;
|
|
301
|
+
filePath: string;
|
|
302
|
+
}>;
|
|
303
|
+
resolvedTarget?: null | SyncTargetIdentity;
|
|
304
|
+
syncState?: null | SyncTargetState;
|
|
305
|
+
target: PushTarget;
|
|
306
|
+
verbose: boolean;
|
|
307
|
+
verboseFetch: (url: string, options: {
|
|
308
|
+
headers?: Record<string, string>;
|
|
309
|
+
method?: string;
|
|
310
|
+
}, verbose: boolean, authToken?: string) => Promise<WritebackHttpResponse>;
|
|
311
|
+
workspaceId?: string;
|
|
312
|
+
writebackDiff?: string;
|
|
313
|
+
writebackObjectLimit?: number;
|
|
314
|
+
}): Promise<WritebackResult>;
|
|
196
315
|
/**
|
|
197
316
|
* Turn a thrown fetch/network error into an actionable message.
|
|
198
317
|
*
|
|
@@ -207,3 +326,4 @@ export declare function executePush(ctx: PushContext, target: PushTarget, flags:
|
|
|
207
326
|
* signal of a server-side or proxy timeout rather than a local network blip.
|
|
208
327
|
*/
|
|
209
328
|
export declare function describeNetworkError(error: unknown, url: string, elapsedMs?: number): string;
|
|
329
|
+
export { parseExportDocuments, preserveLocalTableRecords, selectWritebacks } from './export-compare.js';
|