veryfront 0.1.71 → 0.1.72

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.
Files changed (79) hide show
  1. package/esm/cli/commands/files/command-help.d.ts +3 -0
  2. package/esm/cli/commands/files/command-help.d.ts.map +1 -0
  3. package/esm/cli/commands/files/command-help.js +38 -0
  4. package/esm/cli/commands/files/command.d.ts +105 -0
  5. package/esm/cli/commands/files/command.d.ts.map +1 -0
  6. package/esm/cli/commands/files/command.js +250 -0
  7. package/esm/cli/commands/files/handler.d.ts +3 -0
  8. package/esm/cli/commands/files/handler.d.ts.map +1 -0
  9. package/esm/cli/commands/files/handler.js +4 -0
  10. package/esm/cli/commands/files/index.d.ts +4 -0
  11. package/esm/cli/commands/files/index.d.ts.map +1 -0
  12. package/esm/cli/commands/files/index.js +2 -0
  13. package/esm/cli/commands/knowledge/command-help.d.ts +3 -0
  14. package/esm/cli/commands/knowledge/command-help.d.ts.map +1 -0
  15. package/esm/cli/commands/knowledge/command-help.js +38 -0
  16. package/esm/cli/commands/knowledge/command.d.ts +122 -0
  17. package/esm/cli/commands/knowledge/command.d.ts.map +1 -0
  18. package/esm/cli/commands/knowledge/command.js +382 -0
  19. package/esm/cli/commands/knowledge/handler.d.ts +3 -0
  20. package/esm/cli/commands/knowledge/handler.d.ts.map +1 -0
  21. package/esm/cli/commands/knowledge/handler.js +4 -0
  22. package/esm/cli/commands/knowledge/index.d.ts +3 -0
  23. package/esm/cli/commands/knowledge/index.d.ts.map +1 -0
  24. package/esm/cli/commands/knowledge/index.js +2 -0
  25. package/esm/cli/commands/knowledge/parser-source.d.ts +2 -0
  26. package/esm/cli/commands/knowledge/parser-source.d.ts.map +1 -0
  27. package/esm/cli/commands/knowledge/parser-source.js +415 -0
  28. package/esm/cli/commands/uploads/command-help.d.ts +3 -0
  29. package/esm/cli/commands/uploads/command-help.d.ts.map +1 -0
  30. package/esm/cli/commands/uploads/command-help.js +43 -0
  31. package/esm/cli/commands/uploads/command.d.ts +140 -0
  32. package/esm/cli/commands/uploads/command.d.ts.map +1 -0
  33. package/esm/cli/commands/uploads/command.js +323 -0
  34. package/esm/cli/commands/uploads/handler.d.ts +3 -0
  35. package/esm/cli/commands/uploads/handler.d.ts.map +1 -0
  36. package/esm/cli/commands/uploads/handler.js +4 -0
  37. package/esm/cli/commands/uploads/index.d.ts +4 -0
  38. package/esm/cli/commands/uploads/index.d.ts.map +1 -0
  39. package/esm/cli/commands/uploads/index.js +2 -0
  40. package/esm/cli/help/command-definitions.d.ts.map +1 -1
  41. package/esm/cli/help/command-definitions.js +6 -0
  42. package/esm/cli/router.d.ts.map +1 -1
  43. package/esm/cli/router.js +6 -0
  44. package/esm/deno.js +1 -1
  45. package/esm/src/errors/error-registry.d.ts +2 -0
  46. package/esm/src/errors/error-registry.d.ts.map +1 -1
  47. package/esm/src/errors/error-registry.js +8 -0
  48. package/esm/src/errors/index.d.ts +1 -1
  49. package/esm/src/errors/index.d.ts.map +1 -1
  50. package/esm/src/errors/index.js +1 -1
  51. package/esm/src/platform/compat/media-types.d.ts +5 -0
  52. package/esm/src/platform/compat/media-types.d.ts.map +1 -0
  53. package/esm/src/platform/compat/media-types.js +19 -0
  54. package/esm/src/platform/index.d.ts +1 -0
  55. package/esm/src/platform/index.d.ts.map +1 -1
  56. package/esm/src/platform/index.js +2 -0
  57. package/esm/src/server/bootstrap.js +5 -1
  58. package/package.json +2 -1
  59. package/src/cli/commands/files/command-help.ts +40 -0
  60. package/src/cli/commands/files/command.ts +328 -0
  61. package/src/cli/commands/files/handler.ts +6 -0
  62. package/src/cli/commands/files/index.ts +19 -0
  63. package/src/cli/commands/knowledge/command-help.ts +40 -0
  64. package/src/cli/commands/knowledge/command.ts +513 -0
  65. package/src/cli/commands/knowledge/handler.ts +6 -0
  66. package/src/cli/commands/knowledge/index.ts +2 -0
  67. package/src/cli/commands/knowledge/parser-source.ts +415 -0
  68. package/src/cli/commands/uploads/command-help.ts +45 -0
  69. package/src/cli/commands/uploads/command.ts +465 -0
  70. package/src/cli/commands/uploads/handler.ts +6 -0
  71. package/src/cli/commands/uploads/index.ts +23 -0
  72. package/src/cli/help/command-definitions.ts +6 -0
  73. package/src/cli/router.ts +6 -0
  74. package/src/deno.js +1 -1
  75. package/src/src/errors/error-registry.ts +9 -0
  76. package/src/src/errors/index.ts +1 -0
  77. package/src/src/platform/compat/media-types.ts +23 -0
  78. package/src/src/platform/index.ts +3 -0
  79. package/src/src/server/bootstrap.ts +6 -1
@@ -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,6 @@
1
+ import type { ParsedArgs } from "../../shared/types.js";
2
+ import { uploadsCommand } from "./command.js";
3
+
4
+ export async function handleUploadsCommand(args: ParsedArgs): Promise<void> {
5
+ await uploadsCommand(args);
6
+ }
@@ -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
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.71",
3
+ "version": "0.1.72",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -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,
@@ -46,6 +46,7 @@ export {
46
46
  CONFIG_VALIDATION_ERROR,
47
47
  CONFIG_VALIDATION_FAILED,
48
48
  CORS_CONFIG_INVALID,
49
+ COST_LIMIT_EXCEEDED,
49
50
  DEPENDENCY_MISSING,
50
51
  // DEPLOY
51
52
  DEPLOYMENT_ERROR,
@@ -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
+ }
@@ -55,6 +55,9 @@ export {
55
55
  type StdinReader,
56
56
  } from "./compat/stdin.js";
57
57
 
58
+ // Compat: media types
59
+ export { lookup as lookupMimeType } from "./compat/media-types.js";
60
+
58
61
  // Compat: KV store
59
62
  export { createKVStore, MemoryKv } from "./compat/kv/index.js";
60
63
 
@@ -278,7 +278,12 @@ function validateProductionEnvironment(_adapter: RuntimeAdapter): void {
278
278
  );
279
279
  }
280
280
 
281
- if (!controlPlanePublicKey) {
281
+ if (!controlPlanePublicKey && nodeEnv === "development") {
282
+ logger.warn(
283
+ "[Bootstrap:Prod] CHANNEL_DISPATCH_SIGNING_PUBLIC_KEY is not set. " +
284
+ "Channel dispatch verification will be unavailable (local dev mode).",
285
+ );
286
+ } else if (!controlPlanePublicKey) {
282
287
  logger.error(
283
288
  "[Bootstrap:Prod] CRITICAL: CHANNEL_DISPATCH_SIGNING_PUBLIC_KEY is not set in proxy mode. " +
284
289
  "Hosted runtimes cannot verify control-plane requests without it.",