veryfront 0.1.71 → 0.1.73
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/esm/cli/commands/files/command-help.d.ts +3 -0
- package/esm/cli/commands/files/command-help.d.ts.map +1 -0
- package/esm/cli/commands/files/command-help.js +38 -0
- package/esm/cli/commands/files/command.d.ts +105 -0
- package/esm/cli/commands/files/command.d.ts.map +1 -0
- package/esm/cli/commands/files/command.js +250 -0
- package/esm/cli/commands/files/handler.d.ts +3 -0
- package/esm/cli/commands/files/handler.d.ts.map +1 -0
- package/esm/cli/commands/files/handler.js +4 -0
- package/esm/cli/commands/files/index.d.ts +4 -0
- package/esm/cli/commands/files/index.d.ts.map +1 -0
- package/esm/cli/commands/files/index.js +2 -0
- package/esm/cli/commands/knowledge/command-help.d.ts +3 -0
- package/esm/cli/commands/knowledge/command-help.d.ts.map +1 -0
- package/esm/cli/commands/knowledge/command-help.js +38 -0
- package/esm/cli/commands/knowledge/command.d.ts +122 -0
- package/esm/cli/commands/knowledge/command.d.ts.map +1 -0
- package/esm/cli/commands/knowledge/command.js +382 -0
- package/esm/cli/commands/knowledge/handler.d.ts +3 -0
- package/esm/cli/commands/knowledge/handler.d.ts.map +1 -0
- package/esm/cli/commands/knowledge/handler.js +4 -0
- package/esm/cli/commands/knowledge/index.d.ts +3 -0
- package/esm/cli/commands/knowledge/index.d.ts.map +1 -0
- package/esm/cli/commands/knowledge/index.js +2 -0
- package/esm/cli/commands/knowledge/parser-source.d.ts +2 -0
- package/esm/cli/commands/knowledge/parser-source.d.ts.map +1 -0
- package/esm/cli/commands/knowledge/parser-source.js +415 -0
- package/esm/cli/commands/uploads/command-help.d.ts +3 -0
- package/esm/cli/commands/uploads/command-help.d.ts.map +1 -0
- package/esm/cli/commands/uploads/command-help.js +43 -0
- package/esm/cli/commands/uploads/command.d.ts +140 -0
- package/esm/cli/commands/uploads/command.d.ts.map +1 -0
- package/esm/cli/commands/uploads/command.js +323 -0
- package/esm/cli/commands/uploads/handler.d.ts +3 -0
- package/esm/cli/commands/uploads/handler.d.ts.map +1 -0
- package/esm/cli/commands/uploads/handler.js +4 -0
- package/esm/cli/commands/uploads/index.d.ts +4 -0
- package/esm/cli/commands/uploads/index.d.ts.map +1 -0
- package/esm/cli/commands/uploads/index.js +2 -0
- package/esm/cli/help/command-definitions.d.ts.map +1 -1
- package/esm/cli/help/command-definitions.js +6 -0
- package/esm/cli/router.d.ts.map +1 -1
- package/esm/cli/router.js +6 -0
- package/esm/deno.js +1 -1
- package/esm/src/errors/error-registry.d.ts +2 -0
- package/esm/src/errors/error-registry.d.ts.map +1 -1
- package/esm/src/errors/error-registry.js +8 -0
- package/esm/src/errors/index.d.ts +1 -1
- package/esm/src/errors/index.d.ts.map +1 -1
- package/esm/src/errors/index.js +1 -1
- package/esm/src/html/html-shell-generator.d.ts.map +1 -1
- package/esm/src/html/html-shell-generator.js +6 -0
- package/esm/src/platform/compat/media-types.d.ts +5 -0
- package/esm/src/platform/compat/media-types.d.ts.map +1 -0
- package/esm/src/platform/compat/media-types.js +19 -0
- package/esm/src/platform/index.d.ts +1 -0
- package/esm/src/platform/index.d.ts.map +1 -1
- package/esm/src/platform/index.js +2 -0
- package/esm/src/rendering/orchestrator/pipeline.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/pipeline.js +116 -105
- package/esm/src/server/bootstrap.js +5 -1
- package/esm/src/server/dev-server/error-overlay/error-formatter.d.ts +4 -0
- package/esm/src/server/dev-server/error-overlay/error-formatter.d.ts.map +1 -1
- package/esm/src/server/dev-server/error-overlay/error-formatter.js +15 -0
- package/esm/src/server/dev-server/error-overlay/html-template.d.ts +1 -1
- package/esm/src/server/dev-server/error-overlay/html-template.d.ts.map +1 -1
- package/esm/src/server/dev-server/error-overlay/html-template.js +131 -8
- package/esm/src/server/dev-server/error-overlay/index.d.ts +1 -1
- package/esm/src/server/dev-server/error-overlay/index.d.ts.map +1 -1
- package/esm/src/server/dev-server/error-overlay/index.js +1 -1
- package/esm/src/server/dev-server/error-overlay/overlay-renderer.d.ts +1 -1
- package/esm/src/server/dev-server/error-overlay/overlay-renderer.d.ts.map +1 -1
- package/esm/src/server/dev-server/error-overlay/overlay-renderer.js +2 -2
- package/esm/src/server/dev-server/request-handler.d.ts.map +1 -1
- package/esm/src/server/dev-server/request-handler.js +6 -2
- package/esm/src/server/services/rendering/ssr.service.d.ts.map +1 -1
- package/esm/src/server/services/rendering/ssr.service.js +9 -2
- package/esm/src/server/utils/error-html.d.ts.map +1 -1
- package/esm/src/server/utils/error-html.js +26 -6
- package/package.json +2 -1
- package/src/cli/commands/files/command-help.ts +40 -0
- package/src/cli/commands/files/command.ts +328 -0
- package/src/cli/commands/files/handler.ts +6 -0
- package/src/cli/commands/files/index.ts +19 -0
- package/src/cli/commands/knowledge/command-help.ts +40 -0
- package/src/cli/commands/knowledge/command.ts +513 -0
- package/src/cli/commands/knowledge/handler.ts +6 -0
- package/src/cli/commands/knowledge/index.ts +2 -0
- package/src/cli/commands/knowledge/parser-source.ts +415 -0
- package/src/cli/commands/uploads/command-help.ts +45 -0
- package/src/cli/commands/uploads/command.ts +465 -0
- package/src/cli/commands/uploads/handler.ts +6 -0
- package/src/cli/commands/uploads/index.ts +23 -0
- package/src/cli/help/command-definitions.ts +6 -0
- package/src/cli/router.ts +6 -0
- package/src/deno.js +1 -1
- package/src/src/errors/error-registry.ts +9 -0
- package/src/src/errors/index.ts +1 -0
- package/src/src/html/html-shell-generator.ts +9 -0
- package/src/src/platform/compat/media-types.ts +23 -0
- package/src/src/platform/index.ts +3 -0
- package/src/src/rendering/orchestrator/pipeline.ts +186 -172
- package/src/src/server/bootstrap.ts +6 -1
- package/src/src/server/dev-server/error-overlay/error-formatter.ts +21 -0
- package/src/src/server/dev-server/error-overlay/html-template.ts +139 -8
- package/src/src/server/dev-server/error-overlay/index.ts +1 -0
- package/src/src/server/dev-server/error-overlay/overlay-renderer.ts +2 -1
- package/src/src/server/dev-server/request-handler.ts +6 -2
- package/src/src/server/services/rendering/ssr.service.ts +9 -2
- package/src/src/server/utils/error-html.ts +29 -6
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
import * as dntShim from "../../../_dnt.shims.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { createFileSystem, cwd, lookupMimeType } from "../../../src/platform/index.js";
|
|
4
|
+
import { dirname, join, normalize, resolve } from "../../../src/platform/compat/path/index.js";
|
|
5
|
+
import { withSpan } from "../../../src/observability/tracing/otlp-setup.js";
|
|
6
|
+
import { cliLogger } from "../../utils/index.js";
|
|
7
|
+
import { type ApiClient, createApiClient, resolveConfigWithAuth } from "../../shared/config.js";
|
|
8
|
+
import type { ParsedArgs } from "../../shared/types.js";
|
|
9
|
+
|
|
10
|
+
export interface UploadItem {
|
|
11
|
+
type: "file" | "folder";
|
|
12
|
+
path: string;
|
|
13
|
+
file_name?: string;
|
|
14
|
+
size?: number;
|
|
15
|
+
content_type?: string | null;
|
|
16
|
+
status?: string;
|
|
17
|
+
visibility?: string;
|
|
18
|
+
created_at?: string;
|
|
19
|
+
updated_at?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface UploadsListResponse {
|
|
23
|
+
data: UploadItem[];
|
|
24
|
+
page_info?: {
|
|
25
|
+
next?: string | null;
|
|
26
|
+
prev?: string | null;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface SignedUrlResponse {
|
|
31
|
+
signed_url: string;
|
|
32
|
+
expires_at: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface CreateUploadResponse {
|
|
36
|
+
file_upload_url: string;
|
|
37
|
+
file_path: string;
|
|
38
|
+
upload_id: string;
|
|
39
|
+
required_headers: Record<string, string>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const UploadListArgsSchema = z.object({
|
|
43
|
+
projectSlug: z.string().optional(),
|
|
44
|
+
projectDir: z.string().optional(),
|
|
45
|
+
path: z.string().optional(),
|
|
46
|
+
limit: z.coerce.number().min(1).max(100).optional(),
|
|
47
|
+
recursive: z.boolean().default(true),
|
|
48
|
+
json: z.boolean().default(false),
|
|
49
|
+
quiet: z.boolean().default(false),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export type UploadListOptions = z.infer<typeof UploadListArgsSchema>;
|
|
53
|
+
|
|
54
|
+
const UploadPullArgsSchema = z.object({
|
|
55
|
+
projectSlug: z.string().optional(),
|
|
56
|
+
projectDir: z.string().optional(),
|
|
57
|
+
uploads: z.array(z.string()).default([]),
|
|
58
|
+
path: z.string().optional(),
|
|
59
|
+
all: z.boolean().default(false),
|
|
60
|
+
outputDir: z.string().default(join(cwd(), "uploads")),
|
|
61
|
+
json: z.boolean().default(false),
|
|
62
|
+
quiet: z.boolean().default(false),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export type UploadPullOptions = z.infer<typeof UploadPullArgsSchema>;
|
|
66
|
+
|
|
67
|
+
const UploadPutArgsSchema = z.object({
|
|
68
|
+
projectSlug: z.string().optional(),
|
|
69
|
+
projectDir: z.string().optional(),
|
|
70
|
+
uploadPath: z.string().min(1),
|
|
71
|
+
from: z.string().min(1),
|
|
72
|
+
contentType: z.string().optional(),
|
|
73
|
+
json: z.boolean().default(false),
|
|
74
|
+
quiet: z.boolean().default(false),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export type UploadPutOptions = z.infer<typeof UploadPutArgsSchema>;
|
|
78
|
+
|
|
79
|
+
const UploadDeleteArgsSchema = z.object({
|
|
80
|
+
projectSlug: z.string().optional(),
|
|
81
|
+
projectDir: z.string().optional(),
|
|
82
|
+
uploadPath: z.string().min(1),
|
|
83
|
+
json: z.boolean().default(false),
|
|
84
|
+
quiet: z.boolean().default(false),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
export type UploadDeleteOptions = z.infer<typeof UploadDeleteArgsSchema>;
|
|
88
|
+
|
|
89
|
+
function getStringArg(args: ParsedArgs, ...keys: string[]): string | undefined {
|
|
90
|
+
for (const key of keys) {
|
|
91
|
+
const value = args[key];
|
|
92
|
+
if (typeof value === "string" && value) return value;
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function getBooleanArg(args: ParsedArgs, ...keys: string[]): boolean {
|
|
98
|
+
return keys.some((key) => Boolean(args[key]));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function printJson(value: unknown): void {
|
|
102
|
+
console.log(JSON.stringify(value, null, 2));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function formatUploadItem(item: UploadItem): string {
|
|
106
|
+
if (item.type === "folder") return `[folder] ${item.path}`;
|
|
107
|
+
const size = typeof item.size === "number" ? ` (${item.size} bytes)` : "";
|
|
108
|
+
return `[file] ${item.path}${size}`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function showUploadsUsage(): void {
|
|
112
|
+
console.log(`
|
|
113
|
+
Veryfront Uploads
|
|
114
|
+
|
|
115
|
+
Usage:
|
|
116
|
+
veryfront uploads list [options]
|
|
117
|
+
veryfront uploads pull <upload-path...> [options]
|
|
118
|
+
veryfront uploads pull --path <prefix> --all [options]
|
|
119
|
+
veryfront uploads put <upload-path> --from <local-file> [options]
|
|
120
|
+
veryfront uploads delete <upload-path> [options]
|
|
121
|
+
|
|
122
|
+
Subcommands:
|
|
123
|
+
list List uploads in the project uploads store
|
|
124
|
+
pull Download one or many uploads into a local directory
|
|
125
|
+
put Upload or replace a file in the project uploads store
|
|
126
|
+
delete Delete an upload by path
|
|
127
|
+
`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function normalizeUploadPath(uploadPath: string): string {
|
|
131
|
+
const normalizedPath = normalize(uploadPath).replace(/^\/+/, "");
|
|
132
|
+
if (!normalizedPath || normalizedPath.startsWith("..") || normalizedPath.startsWith("/")) {
|
|
133
|
+
throw new Error(`Invalid upload path: ${uploadPath}`);
|
|
134
|
+
}
|
|
135
|
+
return normalizedPath;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function parseUploadsListArgs(
|
|
139
|
+
args: ParsedArgs,
|
|
140
|
+
): z.SafeParseReturnType<unknown, UploadListOptions> {
|
|
141
|
+
return UploadListArgsSchema.safeParse({
|
|
142
|
+
projectSlug: getStringArg(args, "project", "p", "project-slug"),
|
|
143
|
+
projectDir: getStringArg(args, "project-dir", "dir", "d"),
|
|
144
|
+
path: getStringArg(args, "path"),
|
|
145
|
+
limit: args.limit,
|
|
146
|
+
recursive: args.recursive === undefined ? true : Boolean(args.recursive),
|
|
147
|
+
json: getBooleanArg(args, "json", "j"),
|
|
148
|
+
quiet: getBooleanArg(args, "quiet", "q"),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function parseUploadsPullArgs(
|
|
153
|
+
args: ParsedArgs,
|
|
154
|
+
): z.SafeParseReturnType<unknown, UploadPullOptions> {
|
|
155
|
+
return UploadPullArgsSchema.safeParse({
|
|
156
|
+
projectSlug: getStringArg(args, "project", "p", "project-slug"),
|
|
157
|
+
projectDir: getStringArg(args, "project-dir", "dir", "d"),
|
|
158
|
+
uploads: args._.slice(2).filter((value): value is string => typeof value === "string"),
|
|
159
|
+
path: getStringArg(args, "path"),
|
|
160
|
+
all: getBooleanArg(args, "all"),
|
|
161
|
+
outputDir: getStringArg(args, "output-dir") ?? join(cwd(), "uploads"),
|
|
162
|
+
json: getBooleanArg(args, "json", "j"),
|
|
163
|
+
quiet: getBooleanArg(args, "quiet", "q"),
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function parseUploadsPutArgs(
|
|
168
|
+
args: ParsedArgs,
|
|
169
|
+
): z.SafeParseReturnType<unknown, UploadPutOptions> {
|
|
170
|
+
return UploadPutArgsSchema.safeParse({
|
|
171
|
+
projectSlug: getStringArg(args, "project", "p", "project-slug"),
|
|
172
|
+
projectDir: getStringArg(args, "project-dir", "dir", "d"),
|
|
173
|
+
uploadPath: typeof args._[2] === "string" ? args._[2] : "",
|
|
174
|
+
from: getStringArg(args, "from") ?? "",
|
|
175
|
+
contentType: getStringArg(args, "content-type"),
|
|
176
|
+
json: getBooleanArg(args, "json", "j"),
|
|
177
|
+
quiet: getBooleanArg(args, "quiet", "q"),
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function parseUploadsDeleteArgs(
|
|
182
|
+
args: ParsedArgs,
|
|
183
|
+
): z.SafeParseReturnType<unknown, UploadDeleteOptions> {
|
|
184
|
+
return UploadDeleteArgsSchema.safeParse({
|
|
185
|
+
projectSlug: getStringArg(args, "project", "p", "project-slug"),
|
|
186
|
+
projectDir: getStringArg(args, "project-dir", "dir", "d"),
|
|
187
|
+
uploadPath: typeof args._[2] === "string" ? args._[2] : "",
|
|
188
|
+
json: getBooleanArg(args, "json", "j"),
|
|
189
|
+
quiet: getBooleanArg(args, "quiet", "q"),
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function buildUploadsListUrl(projectSlug: string): string {
|
|
194
|
+
return `/projects/${projectSlug}/uploads`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export function buildUploadCreateUrl(projectSlug: string): string {
|
|
198
|
+
return `/projects/${projectSlug}/uploads`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function buildUploadSignedUrlPath(projectSlug: string, uploadPath: string): string {
|
|
202
|
+
return `/projects/${projectSlug}/uploads/${
|
|
203
|
+
encodeURIComponent(normalizeUploadPath(uploadPath))
|
|
204
|
+
}/url`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function buildUploadDeleteUrl(projectSlug: string, uploadPath: string): string {
|
|
208
|
+
return `/projects/${projectSlug}/uploads/${encodeURIComponent(normalizeUploadPath(uploadPath))}`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export async function listAllUploads(
|
|
212
|
+
client: ApiClient,
|
|
213
|
+
projectSlug: string,
|
|
214
|
+
options: Partial<Pick<UploadListOptions, "path" | "recursive" | "limit">> = {},
|
|
215
|
+
): Promise<UploadItem[]> {
|
|
216
|
+
const allItems: UploadItem[] = [];
|
|
217
|
+
let cursor: string | undefined;
|
|
218
|
+
|
|
219
|
+
do {
|
|
220
|
+
const params: Record<string, string> = {
|
|
221
|
+
limit: String(options.limit ?? 100),
|
|
222
|
+
recursive: String(options.recursive ?? true),
|
|
223
|
+
};
|
|
224
|
+
if (options.path) params.path = options.path;
|
|
225
|
+
if (cursor) params.cursor = cursor;
|
|
226
|
+
|
|
227
|
+
const response = await client.get<UploadsListResponse>(
|
|
228
|
+
buildUploadsListUrl(projectSlug),
|
|
229
|
+
params,
|
|
230
|
+
);
|
|
231
|
+
allItems.push(...response.data);
|
|
232
|
+
cursor = response.page_info?.next ?? undefined;
|
|
233
|
+
} while (cursor);
|
|
234
|
+
|
|
235
|
+
return allItems;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export function resolveUploadOutputPath(uploadPath: string, outputDir: string): string {
|
|
239
|
+
const normalizedPath = normalizeUploadPath(uploadPath);
|
|
240
|
+
const fullPath = resolve(outputDir, normalizedPath);
|
|
241
|
+
const resolvedOutputDir = resolve(outputDir);
|
|
242
|
+
|
|
243
|
+
if (!fullPath.startsWith(`${resolvedOutputDir}/`) && fullPath !== resolvedOutputDir) {
|
|
244
|
+
throw new Error(`Invalid upload path: ${uploadPath}`);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return fullPath;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export async function downloadUploadToFile(
|
|
251
|
+
client: ApiClient,
|
|
252
|
+
projectSlug: string,
|
|
253
|
+
uploadPath: string,
|
|
254
|
+
outputDir: string,
|
|
255
|
+
): Promise<{ uploadPath: string; localPath: string; bytes: number }> {
|
|
256
|
+
const fs = createFileSystem();
|
|
257
|
+
const signedUrl = await client.get<SignedUrlResponse>(
|
|
258
|
+
buildUploadSignedUrlPath(projectSlug, uploadPath),
|
|
259
|
+
);
|
|
260
|
+
const response = await dntShim.fetch(signedUrl.signed_url);
|
|
261
|
+
|
|
262
|
+
if (!response.ok) {
|
|
263
|
+
throw new Error(`Failed to download upload: ${uploadPath}`);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
267
|
+
const localPath = resolveUploadOutputPath(uploadPath, outputDir);
|
|
268
|
+
await fs.mkdir(dirname(localPath), { recursive: true });
|
|
269
|
+
await fs.writeFile(localPath, bytes);
|
|
270
|
+
|
|
271
|
+
return { uploadPath: normalizeUploadPath(uploadPath), localPath, bytes: bytes.byteLength };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export async function uploadLocalFileToUploads(
|
|
275
|
+
client: ApiClient,
|
|
276
|
+
projectSlug: string,
|
|
277
|
+
uploadPath: string,
|
|
278
|
+
localPath: string,
|
|
279
|
+
contentType?: string,
|
|
280
|
+
): Promise<CreateUploadResponse> {
|
|
281
|
+
const fs = createFileSystem();
|
|
282
|
+
const normalizedPath = normalizeUploadPath(uploadPath);
|
|
283
|
+
const bytes = await fs.readFile(localPath);
|
|
284
|
+
const inferredContentType = contentType ?? lookupMimeType(localPath) ??
|
|
285
|
+
"application/octet-stream";
|
|
286
|
+
const createResponse = await client.post<CreateUploadResponse>(
|
|
287
|
+
buildUploadCreateUrl(projectSlug),
|
|
288
|
+
{
|
|
289
|
+
file_path: normalizedPath,
|
|
290
|
+
content_type: inferredContentType,
|
|
291
|
+
size: bytes.byteLength,
|
|
292
|
+
},
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
const uploadResponse = await dntShim.fetch(createResponse.file_upload_url, {
|
|
296
|
+
method: "PUT",
|
|
297
|
+
headers: createResponse.required_headers,
|
|
298
|
+
body: bytes as dntShim.BodyInit,
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
if (!uploadResponse.ok) {
|
|
302
|
+
throw new Error(`Failed to upload file to storage: ${normalizedPath}`);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return createResponse;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export async function deleteUpload(
|
|
309
|
+
client: ApiClient,
|
|
310
|
+
projectSlug: string,
|
|
311
|
+
uploadPath: string,
|
|
312
|
+
): Promise<void> {
|
|
313
|
+
await client.delete(buildUploadDeleteUrl(projectSlug, uploadPath));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export async function uploadsCommand(args: ParsedArgs): Promise<void> {
|
|
317
|
+
const subcommand = typeof args._[1] === "string" ? args._[1] : undefined;
|
|
318
|
+
|
|
319
|
+
if (!subcommand || subcommand === "help") {
|
|
320
|
+
showUploadsUsage();
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
await withSpan("cli.command.uploads", async () => {
|
|
325
|
+
switch (subcommand) {
|
|
326
|
+
case "list": {
|
|
327
|
+
const parsed = parseUploadsListArgs(args);
|
|
328
|
+
if (!parsed.success) {
|
|
329
|
+
throw new Error(`Invalid uploads list arguments: ${parsed.error.message}`);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const options = parsed.data;
|
|
333
|
+
let config = await resolveConfigWithAuth(options.projectDir);
|
|
334
|
+
if (options.projectSlug) config = { ...config, projectSlug: options.projectSlug };
|
|
335
|
+
|
|
336
|
+
const client = createApiClient(config);
|
|
337
|
+
const uploads = await listAllUploads(client, config.projectSlug, options);
|
|
338
|
+
|
|
339
|
+
if (options.json) {
|
|
340
|
+
printJson(uploads);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (!uploads.length) {
|
|
345
|
+
cliLogger.info("No uploads found.");
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
for (const upload of uploads) {
|
|
350
|
+
console.log(formatUploadItem(upload));
|
|
351
|
+
}
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
case "pull": {
|
|
356
|
+
const parsed = parseUploadsPullArgs(args);
|
|
357
|
+
if (!parsed.success) {
|
|
358
|
+
throw new Error(`Invalid uploads pull arguments: ${parsed.error.message}`);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const options = parsed.data;
|
|
362
|
+
let config = await resolveConfigWithAuth(options.projectDir);
|
|
363
|
+
if (options.projectSlug) config = { ...config, projectSlug: options.projectSlug };
|
|
364
|
+
|
|
365
|
+
const client = createApiClient(config);
|
|
366
|
+
let targets = options.uploads;
|
|
367
|
+
|
|
368
|
+
if (options.all) {
|
|
369
|
+
const uploads = await listAllUploads(client, config.projectSlug, {
|
|
370
|
+
path: options.path,
|
|
371
|
+
recursive: true,
|
|
372
|
+
limit: 100,
|
|
373
|
+
});
|
|
374
|
+
targets = uploads.filter((item) => item.type === "file").map((item) => item.path);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (!targets.length) {
|
|
378
|
+
throw new Error("No uploads selected. Pass upload paths or use --path with --all.");
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const results = [] as Array<{ uploadPath: string; localPath: string; bytes: number }>;
|
|
382
|
+
for (const uploadPath of targets) {
|
|
383
|
+
const result = await downloadUploadToFile(
|
|
384
|
+
client,
|
|
385
|
+
config.projectSlug,
|
|
386
|
+
uploadPath,
|
|
387
|
+
options.outputDir,
|
|
388
|
+
);
|
|
389
|
+
results.push(result);
|
|
390
|
+
if (!options.quiet && !options.json) {
|
|
391
|
+
cliLogger.info(`Downloaded ${uploadPath} -> ${result.localPath}`);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (options.json) {
|
|
396
|
+
printJson(results);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (!options.quiet) {
|
|
401
|
+
cliLogger.info(`Pulled ${results.length} upload(s) into ${options.outputDir}.`);
|
|
402
|
+
}
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
case "put": {
|
|
407
|
+
const parsed = parseUploadsPutArgs(args);
|
|
408
|
+
if (!parsed.success) {
|
|
409
|
+
throw new Error(`Invalid uploads put arguments: ${parsed.error.message}`);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const options = parsed.data;
|
|
413
|
+
let config = await resolveConfigWithAuth(options.projectDir);
|
|
414
|
+
if (options.projectSlug) config = { ...config, projectSlug: options.projectSlug };
|
|
415
|
+
|
|
416
|
+
const client = createApiClient(config);
|
|
417
|
+
const result = await uploadLocalFileToUploads(
|
|
418
|
+
client,
|
|
419
|
+
config.projectSlug,
|
|
420
|
+
options.uploadPath,
|
|
421
|
+
options.from,
|
|
422
|
+
options.contentType,
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
if (options.json) {
|
|
426
|
+
printJson(result);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (!options.quiet) {
|
|
431
|
+
cliLogger.info(`Uploaded ${options.from} -> ${normalizeUploadPath(options.uploadPath)}`);
|
|
432
|
+
}
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
case "delete":
|
|
437
|
+
case "rm": {
|
|
438
|
+
const parsed = parseUploadsDeleteArgs(args);
|
|
439
|
+
if (!parsed.success) {
|
|
440
|
+
throw new Error(`Invalid uploads delete arguments: ${parsed.error.message}`);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const options = parsed.data;
|
|
444
|
+
let config = await resolveConfigWithAuth(options.projectDir);
|
|
445
|
+
if (options.projectSlug) config = { ...config, projectSlug: options.projectSlug };
|
|
446
|
+
|
|
447
|
+
const client = createApiClient(config);
|
|
448
|
+
await deleteUpload(client, config.projectSlug, options.uploadPath);
|
|
449
|
+
|
|
450
|
+
if (options.json) {
|
|
451
|
+
printJson({ success: true, path: normalizeUploadPath(options.uploadPath) });
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (!options.quiet) {
|
|
456
|
+
cliLogger.info(`Deleted upload ${normalizeUploadPath(options.uploadPath)}`);
|
|
457
|
+
}
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
default:
|
|
462
|
+
showUploadsUsage();
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export {
|
|
2
|
+
buildUploadCreateUrl,
|
|
3
|
+
buildUploadSignedUrlPath,
|
|
4
|
+
buildUploadsListUrl,
|
|
5
|
+
deleteUpload,
|
|
6
|
+
downloadUploadToFile,
|
|
7
|
+
listAllUploads,
|
|
8
|
+
parseUploadsDeleteArgs,
|
|
9
|
+
parseUploadsListArgs,
|
|
10
|
+
parseUploadsPullArgs,
|
|
11
|
+
parseUploadsPutArgs,
|
|
12
|
+
resolveUploadOutputPath,
|
|
13
|
+
uploadLocalFileToUploads,
|
|
14
|
+
uploadsCommand,
|
|
15
|
+
} from "./command.js";
|
|
16
|
+
export type {
|
|
17
|
+
UploadDeleteOptions,
|
|
18
|
+
UploadItem,
|
|
19
|
+
UploadListOptions,
|
|
20
|
+
UploadPullOptions,
|
|
21
|
+
UploadPutOptions,
|
|
22
|
+
} from "./command.js";
|
|
23
|
+
export { handleUploadsCommand } from "./handler.js";
|
|
@@ -21,6 +21,9 @@ import { analyzeChunksHelp } from "../commands/analyze-chunks/command-help.js";
|
|
|
21
21
|
import { generateHelp } from "../commands/generate/command-help.js";
|
|
22
22
|
import { pullHelp } from "../commands/pull/command-help.js";
|
|
23
23
|
import { pushHelp } from "../commands/push/command-help.js";
|
|
24
|
+
import { uploadsHelp } from "../commands/uploads/command-help.js";
|
|
25
|
+
import { filesHelp } from "../commands/files/command-help.js";
|
|
26
|
+
import { knowledgeHelp } from "../commands/knowledge/command-help.js";
|
|
24
27
|
import { mergeHelp } from "../commands/merge/command-help.js";
|
|
25
28
|
import { deployHelp } from "../commands/deploy/command-help.js";
|
|
26
29
|
import { upHelp } from "../commands/up/command-help.js";
|
|
@@ -52,6 +55,9 @@ export const COMMANDS: CommandRegistry = {
|
|
|
52
55
|
generate: generateHelp,
|
|
53
56
|
pull: pullHelp,
|
|
54
57
|
push: pushHelp,
|
|
58
|
+
uploads: uploadsHelp,
|
|
59
|
+
files: filesHelp,
|
|
60
|
+
knowledge: knowledgeHelp,
|
|
55
61
|
merge: mergeHelp,
|
|
56
62
|
deploy: deployHelp,
|
|
57
63
|
up: upHelp,
|
package/src/cli/router.ts
CHANGED
|
@@ -22,6 +22,9 @@ import { handleMCPCommand } from "./commands/mcp/handler.js";
|
|
|
22
22
|
import { handleMergeCommand } from "./commands/merge/handler.js";
|
|
23
23
|
import { handlePullCommand } from "./commands/pull/index.js";
|
|
24
24
|
import { handlePushCommand } from "./commands/push/index.js";
|
|
25
|
+
import { handleUploadsCommand } from "./commands/uploads/index.js";
|
|
26
|
+
import { handleFilesCommand } from "./commands/files/index.js";
|
|
27
|
+
import { handleKnowledgeCommand } from "./commands/knowledge/index.js";
|
|
25
28
|
import { handleRoutesCommand } from "./commands/routes/handler.js";
|
|
26
29
|
import { handleServeCommand } from "./commands/serve/handler.js";
|
|
27
30
|
import { handleStartCommand } from "./commands/start/handler.js";
|
|
@@ -56,6 +59,9 @@ const commands: Record<string, (args: ParsedArgs) => Promise<void>> = {
|
|
|
56
59
|
"g": handleGenerateCommand,
|
|
57
60
|
"pull": handlePullCommand,
|
|
58
61
|
"push": handlePushCommand,
|
|
62
|
+
"uploads": handleUploadsCommand,
|
|
63
|
+
"files": handleFilesCommand,
|
|
64
|
+
"knowledge": handleKnowledgeCommand,
|
|
59
65
|
"merge": handleMergeCommand,
|
|
60
66
|
"deploy": handleDeployCommand,
|
|
61
67
|
"up": handleUpCommand,
|
package/src/deno.js
CHANGED
|
@@ -591,6 +591,14 @@ export const ORCHESTRATION_ERROR = defineError({
|
|
|
591
591
|
suggestion: "Check agent coordination logic",
|
|
592
592
|
});
|
|
593
593
|
|
|
594
|
+
export const COST_LIMIT_EXCEEDED = defineError({
|
|
595
|
+
slug: "cost-limit-exceeded",
|
|
596
|
+
category: "AGENT",
|
|
597
|
+
status: 429,
|
|
598
|
+
title: "Cost limit exceeded",
|
|
599
|
+
suggestion: "Wait for the budget period to reset or increase the limit",
|
|
600
|
+
});
|
|
601
|
+
|
|
594
602
|
// =============================================================================
|
|
595
603
|
// GENERAL - Cross-cutting errors
|
|
596
604
|
// =============================================================================
|
|
@@ -772,6 +780,7 @@ export const ERROR_REGISTRY = {
|
|
|
772
780
|
"agent-timeout": AGENT_TIMEOUT,
|
|
773
781
|
"agent-intent-error": AGENT_INTENT_ERROR,
|
|
774
782
|
"orchestration-error": ORCHESTRATION_ERROR,
|
|
783
|
+
"cost-limit-exceeded": COST_LIMIT_EXCEEDED,
|
|
775
784
|
|
|
776
785
|
// GENERAL
|
|
777
786
|
"unknown-error": UNKNOWN_ERROR,
|
package/src/src/errors/index.ts
CHANGED
|
@@ -208,6 +208,14 @@ async function generateHTMLShellPartsImpl(
|
|
|
208
208
|
|
|
209
209
|
const nonceAttr = nonce ? ` nonce="${nonce}"` : "";
|
|
210
210
|
|
|
211
|
+
// Expose project slug for runtime error overlay "Fix in Veryfront" button
|
|
212
|
+
const overlaySlug = options.projectId || meta.slug;
|
|
213
|
+
const slugForOverlay = useDevScripts && overlaySlug
|
|
214
|
+
? `<script${nonceAttr}>window.__VF_PROJECT_SLUG__=${
|
|
215
|
+
JSON.stringify(overlaySlug).replace(/</g, "\\u003c")
|
|
216
|
+
};</script>`
|
|
217
|
+
: "";
|
|
218
|
+
|
|
211
219
|
const hydrationErrorSuppression = useDevScripts ? "" : `<script${nonceAttr}>
|
|
212
220
|
(function(){
|
|
213
221
|
var origError = console.error;
|
|
@@ -303,6 +311,7 @@ async function generateHTMLShellPartsImpl(
|
|
|
303
311
|
${linkTags}
|
|
304
312
|
${styleTags}
|
|
305
313
|
${modeStyles}
|
|
314
|
+
${slugForOverlay}
|
|
306
315
|
</head>
|
|
307
316
|
<body${bodyClass ? ` class="${bodyClass}"` : ""} suppressHydrationWarning>
|
|
308
317
|
<div ${rootAttributes}>`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import mime from "mime-types";
|
|
2
|
+
|
|
3
|
+
export function contentType(path: string): string | undefined {
|
|
4
|
+
const type = mime.lookup(path);
|
|
5
|
+
if (!type) return undefined;
|
|
6
|
+
|
|
7
|
+
const cs = mime.charset(type);
|
|
8
|
+
if (!cs) return type;
|
|
9
|
+
|
|
10
|
+
return `${type}; charset=${cs}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function extension(type: string): string | undefined {
|
|
14
|
+
return mime.extension(type) ?? undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function lookup(path: string): string | undefined {
|
|
18
|
+
return mime.lookup(path) ?? undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function charset(type: string): string | undefined {
|
|
22
|
+
return mime.charset(type) ?? undefined;
|
|
23
|
+
}
|