@xano/cli 1.0.3-beta.3 → 1.0.3-beta.5
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 +3 -6
- package/dist/base-command.d.ts +6 -0
- package/dist/base-command.js +24 -0
- package/dist/commands/static_host/build/create/index.d.ts +1 -0
- package/dist/commands/static_host/build/create/index.js +6 -1
- package/dist/commands/static_host/build/push/index.d.ts +2 -1
- package/dist/commands/static_host/build/push/index.js +56 -29
- package/oclif.manifest.json +2282 -2268
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -527,11 +527,6 @@ xano static_host create marketing --description "Marketing site"
|
|
|
527
527
|
xano static_host get marketing
|
|
528
528
|
xano static_host edit marketing --name marketing-v2 --description "Updated"
|
|
529
529
|
|
|
530
|
-
# Create a build (name optional — auto-generated from the timestamp if omitted).
|
|
531
|
-
# For package.json builds, the CLI waits for the build to finish (--no-wait to skip).
|
|
532
|
-
xano static_host build create default -f ./build.zip -n "v1.0.0"
|
|
533
|
-
xano static_host build create default -f ./build.zip # name: 20260531-143022
|
|
534
|
-
|
|
535
530
|
# List builds
|
|
536
531
|
xano static_host build list default
|
|
537
532
|
|
|
@@ -546,10 +541,12 @@ xano static_host build pull default --latest # Latest build
|
|
|
546
541
|
xano static_host build pull default --env dev # Build currently deployed to dev
|
|
547
542
|
xano static_host build pull default --env prod -d ./prod-release
|
|
548
543
|
|
|
549
|
-
# Push a
|
|
544
|
+
# Push a build (name optional — auto-generated from the timestamp if omitted).
|
|
545
|
+
# Accepts a directory (-d) or a zip file (-f). Defaults to the current directory.
|
|
550
546
|
# For package.json builds, the CLI waits for the build to finish (--no-wait to skip).
|
|
551
547
|
xano static_host build push default -d ./dist -n "v1.0.0"
|
|
552
548
|
xano static_host build push default # current dir, auto-name
|
|
549
|
+
xano static_host build push default -f ./build.zip -n "v1.0.0" # from zip file
|
|
553
550
|
xano static_host build push default -n "release" --description "Production build"
|
|
554
551
|
|
|
555
552
|
# Delete a build (prompts for confirmation; --force to skip)
|
package/dist/base-command.d.ts
CHANGED
|
@@ -114,6 +114,12 @@ export default abstract class BaseCommand extends Command {
|
|
|
114
114
|
*
|
|
115
115
|
* Returns the final status. Resolves to the last-seen status on timeout.
|
|
116
116
|
*/
|
|
117
|
+
protected logStaticHostUrls(opts: {
|
|
118
|
+
profile: ProfileConfig;
|
|
119
|
+
staticHost: string;
|
|
120
|
+
verbose: boolean;
|
|
121
|
+
workspaceId: string;
|
|
122
|
+
}): Promise<void>;
|
|
117
123
|
protected waitForBuild(opts: {
|
|
118
124
|
buildId: number | string;
|
|
119
125
|
intervalMs?: number;
|
package/dist/base-command.js
CHANGED
|
@@ -325,6 +325,30 @@ export default class BaseCommand extends Command {
|
|
|
325
325
|
*
|
|
326
326
|
* Returns the final status. Resolves to the last-seen status on timeout.
|
|
327
327
|
*/
|
|
328
|
+
async logStaticHostUrls(opts) {
|
|
329
|
+
const { profile, staticHost, verbose, workspaceId } = opts;
|
|
330
|
+
const url = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/static_host/${staticHost}`;
|
|
331
|
+
try {
|
|
332
|
+
const response = await this.verboseFetch(url, {
|
|
333
|
+
headers: { accept: 'application/json', Authorization: `Bearer ${profile.access_token}` },
|
|
334
|
+
method: 'GET',
|
|
335
|
+
}, verbose, profile.access_token);
|
|
336
|
+
if (!response.ok)
|
|
337
|
+
return;
|
|
338
|
+
const host = (await response.json());
|
|
339
|
+
if (host.dev?.default_url)
|
|
340
|
+
this.log(`Dev URL: ${host.dev.default_url}`);
|
|
341
|
+
if (host.dev?.custom_url)
|
|
342
|
+
this.log(`Dev Custom URL: ${host.dev.custom_url}`);
|
|
343
|
+
if (host.prod?.default_url)
|
|
344
|
+
this.log(`Prod URL: ${host.prod.default_url}`);
|
|
345
|
+
if (host.prod?.custom_url)
|
|
346
|
+
this.log(`Prod Custom URL: ${host.prod.custom_url}`);
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
// Non-fatal — the build succeeded, we just can't show the URL.
|
|
350
|
+
}
|
|
351
|
+
}
|
|
328
352
|
async waitForBuild(opts) {
|
|
329
353
|
const { buildId, profile, quiet, staticHost, verbose, workspaceId } = opts;
|
|
330
354
|
const intervalMs = opts.intervalMs ?? 2000;
|
|
@@ -6,6 +6,7 @@ import BaseCommand from '../../../../base-command.js';
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function generateBuildName(date?: Date): string;
|
|
8
8
|
export default class StaticHostBuildCreate extends BaseCommand {
|
|
9
|
+
static hidden: boolean;
|
|
9
10
|
static args: {
|
|
10
11
|
static_host: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
11
12
|
};
|
|
@@ -18,13 +18,14 @@ export function generateBuildName(date = new Date()) {
|
|
|
18
18
|
return `${y}${mo}${d}-${h}${mi}${s}`;
|
|
19
19
|
}
|
|
20
20
|
export default class StaticHostBuildCreate extends BaseCommand {
|
|
21
|
+
static hidden = true;
|
|
21
22
|
static args = {
|
|
22
23
|
static_host: Args.string({
|
|
23
24
|
description: 'Static Host name',
|
|
24
25
|
required: true,
|
|
25
26
|
}),
|
|
26
27
|
};
|
|
27
|
-
static description = 'Create a new build
|
|
28
|
+
static description = '[Deprecated: use "static_host build push -f <file>" instead] Create a new build from a zip file';
|
|
28
29
|
static examples = [
|
|
29
30
|
`$ xano static_host:build:create default -f ./build.zip -n "v1.0.0"
|
|
30
31
|
Build created successfully!
|
|
@@ -88,6 +89,7 @@ Description: Production build
|
|
|
88
89
|
}),
|
|
89
90
|
};
|
|
90
91
|
async run() {
|
|
92
|
+
this.warn('`static_host build create` is deprecated. Use `static_host build push -f <file>` instead.');
|
|
91
93
|
const { args, flags } = await this.parse(StaticHostBuildCreate);
|
|
92
94
|
const { profile, profileName } = this.resolveProfile(flags);
|
|
93
95
|
// Determine workspace_id from flag or profile
|
|
@@ -186,6 +188,9 @@ Description: Production build
|
|
|
186
188
|
this.error(`Build ${result.id} failed (status: error). Check the build log with: xano static_host build get ${args.static_host} --build_id ${result.id}`);
|
|
187
189
|
}
|
|
188
190
|
}
|
|
191
|
+
if (flags.output !== 'json') {
|
|
192
|
+
await this.logStaticHostUrls({ profile, staticHost: args.static_host, verbose: flags.verbose, workspaceId });
|
|
193
|
+
}
|
|
189
194
|
}
|
|
190
195
|
catch (error) {
|
|
191
196
|
if (error instanceof Error) {
|
|
@@ -7,7 +7,8 @@ export default class StaticHostBuildPush extends BaseCommand {
|
|
|
7
7
|
static examples: string[];
|
|
8
8
|
static flags: {
|
|
9
9
|
description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
directory: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
directory: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
12
|
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
13
|
'no-wait': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
14
|
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -11,23 +11,23 @@ export default class StaticHostBuildPush extends BaseCommand {
|
|
|
11
11
|
required: true,
|
|
12
12
|
}),
|
|
13
13
|
};
|
|
14
|
-
static description = 'Push a directory as a new static host build';
|
|
14
|
+
static description = 'Push a directory or zip file as a new static host build';
|
|
15
15
|
static examples = [
|
|
16
|
-
`$ xano static_host build push default -n "v1.0.0"
|
|
16
|
+
`$ xano static_host build push default -d ./dist -n "v1.0.0"
|
|
17
17
|
Pushed 15 files as build "v1.0.0"
|
|
18
18
|
ID: 123
|
|
19
|
-
`,
|
|
20
|
-
`$ xano static_host build push default -n "v1.0.0"
|
|
21
|
-
Pushed 8 files as build "v1.0.0" (from current directory)
|
|
22
19
|
`,
|
|
23
20
|
`$ xano static_host build push default
|
|
24
21
|
Pushed 8 files as build "20260531-143022"
|
|
22
|
+
`,
|
|
23
|
+
`$ xano static_host build push default -f ./build.zip -n "v1.0.0"
|
|
24
|
+
Pushed build.zip as build "v1.0.0"
|
|
25
|
+
ID: 124
|
|
25
26
|
`,
|
|
26
27
|
`$ xano static_host build push myhost -n "production" --description "Production build" -w 40
|
|
27
28
|
Pushed 22 files as build "production"
|
|
28
|
-
ID:
|
|
29
|
+
ID: 125
|
|
29
30
|
`,
|
|
30
|
-
`$ xano static_host build push default -n "release-1.2" -d ./build -o json`,
|
|
31
31
|
];
|
|
32
32
|
static flags = {
|
|
33
33
|
...BaseCommand.baseFlags,
|
|
@@ -37,8 +37,14 @@ ID: 124
|
|
|
37
37
|
}),
|
|
38
38
|
directory: Flags.string({
|
|
39
39
|
char: 'd',
|
|
40
|
-
default: '.',
|
|
41
40
|
description: 'Directory to push (defaults to current directory)',
|
|
41
|
+
exclusive: ['file'],
|
|
42
|
+
required: false,
|
|
43
|
+
}),
|
|
44
|
+
file: Flags.string({
|
|
45
|
+
char: 'f',
|
|
46
|
+
description: 'Path to a zip file to upload (alternative to -d)',
|
|
47
|
+
exclusive: ['directory'],
|
|
42
48
|
required: false,
|
|
43
49
|
}),
|
|
44
50
|
name: Flags.string({
|
|
@@ -79,32 +85,48 @@ ID: 124
|
|
|
79
85
|
` 1. Provide it as a flag: xano static_host build push <static_host> -n <name> -w <workspace_id>\n` +
|
|
80
86
|
` 2. Set it in your profile using: xano profile edit ${profileName} -w <workspace_id>`);
|
|
81
87
|
}
|
|
82
|
-
const sourceDir = path.resolve(flags.directory);
|
|
83
|
-
if (!fs.existsSync(sourceDir)) {
|
|
84
|
-
this.error(`Directory not found: ${sourceDir}`);
|
|
85
|
-
}
|
|
86
|
-
const stats = fs.statSync(sourceDir);
|
|
87
|
-
if (!stats.isDirectory()) {
|
|
88
|
-
this.error(`Path is not a directory: ${sourceDir}`);
|
|
89
|
-
}
|
|
90
88
|
const animate = Boolean(process.stdout.isTTY) && flags.output !== 'json' && !flags.verbose;
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
const buildName = flags.name ?? generateBuildName();
|
|
90
|
+
let zipBuffer;
|
|
91
|
+
let fileCount = 0;
|
|
92
|
+
let fileName;
|
|
93
|
+
if (flags.file) {
|
|
94
|
+
const filePath = path.resolve(flags.file);
|
|
95
|
+
if (!fs.existsSync(filePath)) {
|
|
96
|
+
this.error(`File not found: ${filePath}`);
|
|
97
|
+
}
|
|
98
|
+
const fileStats = fs.statSync(filePath);
|
|
99
|
+
if (!fileStats.isFile()) {
|
|
100
|
+
this.error(`Path is not a file: ${filePath}`);
|
|
101
|
+
}
|
|
102
|
+
fileName = path.basename(filePath);
|
|
103
|
+
if (animate)
|
|
104
|
+
ux.action.start('Uploading', fileName);
|
|
105
|
+
zipBuffer = fs.readFileSync(filePath);
|
|
94
106
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
107
|
+
else {
|
|
108
|
+
const sourceDir = path.resolve(flags.directory ?? '.');
|
|
109
|
+
if (!fs.existsSync(sourceDir)) {
|
|
110
|
+
this.error(`Directory not found: ${sourceDir}`);
|
|
111
|
+
}
|
|
112
|
+
const dirStats = fs.statSync(sourceDir);
|
|
113
|
+
if (!dirStats.isDirectory()) {
|
|
114
|
+
this.error(`Path is not a directory: ${sourceDir}`);
|
|
115
|
+
}
|
|
116
|
+
fileCount = this.countFiles(sourceDir);
|
|
117
|
+
if (animate)
|
|
118
|
+
ux.action.start('Packaging', `${fileCount} files`);
|
|
119
|
+
zipBuffer = await this.createZipBuffer(sourceDir);
|
|
120
|
+
if (animate) {
|
|
121
|
+
ux.action.stop(`${fileCount} files (${(zipBuffer.length / (1024 * 1024)).toFixed(1)} MB)`);
|
|
122
|
+
ux.action.start('Uploading');
|
|
123
|
+
}
|
|
100
124
|
}
|
|
125
|
+
const sizeMB = (zipBuffer.length / (1024 * 1024)).toFixed(1);
|
|
101
126
|
const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/static_host/${args.static_host}/build`;
|
|
102
|
-
// Name is optional — fall back to a timestamped name so builds can be
|
|
103
|
-
// pushed without thinking up a label each time.
|
|
104
|
-
const buildName = flags.name ?? generateBuildName();
|
|
105
127
|
const formData = new globalThis.FormData();
|
|
106
128
|
const blob = new Blob([new Uint8Array(zipBuffer)], { type: 'application/zip' });
|
|
107
|
-
formData.append('file', blob, 'build.zip');
|
|
129
|
+
formData.append('file', blob, fileName ?? 'build.zip');
|
|
108
130
|
formData.append('name', buildName);
|
|
109
131
|
if (flags.description) {
|
|
110
132
|
formData.append('description', flags.description);
|
|
@@ -133,7 +155,9 @@ ID: 124
|
|
|
133
155
|
this.log(JSON.stringify(result, null, 2));
|
|
134
156
|
}
|
|
135
157
|
else {
|
|
136
|
-
this.log(
|
|
158
|
+
this.log(fileName
|
|
159
|
+
? `Pushed ${fileName} as build "${buildName}" (${sizeMB} MB)`
|
|
160
|
+
: `Pushed ${fileCount} files as build "${buildName}" (${sizeMB} MB)`);
|
|
137
161
|
this.log(`ID: ${result.id}`);
|
|
138
162
|
if (result.status) {
|
|
139
163
|
this.log(`Status: ${result.status}`);
|
|
@@ -155,6 +179,9 @@ ID: 124
|
|
|
155
179
|
this.error(`Build ${result.id} failed (status: error). Check the build log with: xano static_host build get ${args.static_host} --build_id ${result.id}`);
|
|
156
180
|
}
|
|
157
181
|
}
|
|
182
|
+
if (flags.output !== 'json') {
|
|
183
|
+
await this.logStaticHostUrls({ profile, staticHost: args.static_host, verbose: flags.verbose, workspaceId });
|
|
184
|
+
}
|
|
158
185
|
}
|
|
159
186
|
catch (error) {
|
|
160
187
|
if (error instanceof Error) {
|