veryfront 0.1.92 → 0.1.93

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 (75) hide show
  1. package/esm/cli/commands/styles/command-help.d.ts +3 -0
  2. package/esm/cli/commands/styles/command-help.d.ts.map +1 -0
  3. package/esm/cli/commands/styles/command-help.js +19 -0
  4. package/esm/cli/commands/styles/command.d.ts +3 -0
  5. package/esm/cli/commands/styles/command.d.ts.map +1 -0
  6. package/esm/cli/commands/styles/command.js +198 -0
  7. package/esm/cli/commands/styles/handler.d.ts +24 -0
  8. package/esm/cli/commands/styles/handler.d.ts.map +1 -0
  9. package/esm/cli/commands/styles/handler.js +17 -0
  10. package/esm/cli/help/command-definitions.d.ts.map +1 -1
  11. package/esm/cli/help/command-definitions.js +2 -0
  12. package/esm/cli/router.d.ts.map +1 -1
  13. package/esm/cli/router.js +2 -0
  14. package/esm/deno.d.ts +1 -0
  15. package/esm/deno.js +2 -1
  16. package/esm/src/html/styles-builder/css-pregeneration.d.ts +9 -0
  17. package/esm/src/html/styles-builder/css-pregeneration.d.ts.map +1 -1
  18. package/esm/src/html/styles-builder/css-pregeneration.js +26 -15
  19. package/esm/src/jobs/schemas.d.ts +40 -40
  20. package/esm/src/platform/adapters/veryfront-api-client/client.d.ts +2 -1
  21. package/esm/src/platform/adapters/veryfront-api-client/client.d.ts.map +1 -1
  22. package/esm/src/platform/adapters/veryfront-api-client/client.js +3 -0
  23. package/esm/src/platform/adapters/veryfront-api-client/index.d.ts +1 -1
  24. package/esm/src/platform/adapters/veryfront-api-client/index.d.ts.map +1 -1
  25. package/esm/src/platform/adapters/veryfront-api-client/operations.d.ts +11 -2
  26. package/esm/src/platform/adapters/veryfront-api-client/operations.d.ts.map +1 -1
  27. package/esm/src/platform/adapters/veryfront-api-client/operations.js +30 -0
  28. package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.d.ts +14 -3
  29. package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.d.ts.map +1 -1
  30. package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.js +8 -1
  31. package/esm/src/rendering/styles.d.ts +9 -0
  32. package/esm/src/rendering/styles.d.ts.map +1 -0
  33. package/esm/src/rendering/styles.js +8 -0
  34. package/esm/src/sandbox/index.d.ts +1 -1
  35. package/esm/src/sandbox/index.d.ts.map +1 -1
  36. package/esm/src/sandbox/sandbox.d.ts +14 -3
  37. package/esm/src/sandbox/sandbox.d.ts.map +1 -1
  38. package/esm/src/sandbox/sandbox.js +20 -6
  39. package/esm/src/security/http/base-handler.d.ts.map +1 -1
  40. package/esm/src/security/http/base-handler.js +5 -2
  41. package/esm/src/server/context/request-context.d.ts.map +1 -1
  42. package/esm/src/server/context/request-context.js +4 -2
  43. package/esm/src/server/handlers/dev/styles-css.handler.d.ts +2 -0
  44. package/esm/src/server/handlers/dev/styles-css.handler.d.ts.map +1 -1
  45. package/esm/src/server/handlers/dev/styles-css.handler.js +23 -0
  46. package/esm/src/server/handlers/preview/markdown-preview.handler.d.ts.map +1 -1
  47. package/esm/src/server/handlers/preview/markdown-preview.handler.js +4 -2
  48. package/esm/src/server/handlers/request/css.handler.d.ts.map +1 -1
  49. package/esm/src/server/handlers/request/css.handler.js +4 -2
  50. package/esm/src/server/handlers/request/ssr/ssr.handler.d.ts.map +1 -1
  51. package/esm/src/server/handlers/request/ssr/ssr.handler.js +4 -2
  52. package/esm/src/utils/version.d.ts +1 -1
  53. package/esm/src/utils/version.js +1 -1
  54. package/package.json +1 -1
  55. package/src/cli/commands/styles/command-help.ts +21 -0
  56. package/src/cli/commands/styles/command.ts +296 -0
  57. package/src/cli/commands/styles/handler.ts +23 -0
  58. package/src/cli/help/command-definitions.ts +2 -0
  59. package/src/cli/router.ts +2 -0
  60. package/src/deno.js +2 -1
  61. package/src/src/html/styles-builder/css-pregeneration.ts +57 -29
  62. package/src/src/platform/adapters/veryfront-api-client/client.ts +8 -0
  63. package/src/src/platform/adapters/veryfront-api-client/index.ts +1 -0
  64. package/src/src/platform/adapters/veryfront-api-client/operations.ts +48 -2
  65. package/src/src/platform/adapters/veryfront-api-client/schemas/api.schema.ts +9 -1
  66. package/src/src/rendering/styles.ts +15 -0
  67. package/src/src/sandbox/index.ts +1 -0
  68. package/src/src/sandbox/sandbox.ts +33 -6
  69. package/src/src/security/http/base-handler.ts +5 -2
  70. package/src/src/server/context/request-context.ts +4 -2
  71. package/src/src/server/handlers/dev/styles-css.handler.ts +31 -0
  72. package/src/src/server/handlers/preview/markdown-preview.handler.ts +4 -2
  73. package/src/src/server/handlers/request/css.handler.ts +4 -2
  74. package/src/src/server/handlers/request/ssr/ssr.handler.ts +4 -2
  75. package/src/src/utils/version.ts +1 -1
@@ -148,11 +148,13 @@ export const LookupDomainResponseSchema = z.object({
148
148
  });
149
149
 
150
150
  export const StyleArtifactResolveResponseSchema = z.object({
151
- status: z.enum(["ready", "missing"]),
151
+ status: z.enum(["ready", "missing", "building", "failed"]),
152
152
  artifact_hash: z.string().optional(),
153
153
  asset_path: z.string().optional(),
154
154
  etag: z.string().optional(),
155
155
  content_type: z.string().optional(),
156
+ build_job_id: z.string().uuid().optional(),
157
+ failure_reason: z.string().optional(),
156
158
  updated_at: z.string().optional(),
157
159
  });
158
160
 
@@ -228,4 +230,10 @@ export const API_ENDPOINTS = {
228
230
  description:
229
231
  "Resolve metadata for the latest ready style artifact for a branch, environment, or release selector",
230
232
  },
233
+ ensureStyleArtifactBuild: {
234
+ method: "POST" as const,
235
+ path: "/projects/{projectRef}/style-artifacts/current/builds",
236
+ description:
237
+ "Ensure a background style artifact build exists for a branch, environment, or release selector",
238
+ },
231
239
  } as const;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Public style artifact helpers used by CLI and worker entrypoints.
3
+ *
4
+ * @module rendering/styles
5
+ */
6
+
7
+ export {
8
+ buildPreparedCSSArtifactFromFiles,
9
+ type PreparedCSSArtifactBuildResult,
10
+ } from "../html/styles-builder/css-pregeneration.js";
11
+ export {
12
+ createStyleScopeProfile,
13
+ type StyleScopeProfile,
14
+ } from "../html/styles-builder/style-scope-profile.js";
15
+ export { resolveStyleContentVersion } from "../html/styles-builder/content-version.js";
@@ -24,6 +24,7 @@ export {
24
24
  type CommandJobHeartbeatStatus,
25
25
  type CommandJobOutput,
26
26
  type CommandJobStatus,
27
+ type ExecOptions,
27
28
  type ExecResult,
28
29
  type ExecStreamEvent,
29
30
  Sandbox,
@@ -19,6 +19,16 @@ import {
19
19
  import { getVeryfrontCloudAuthToken } from "../platform/cloud/resolver.js";
20
20
  import { getHostEnv } from "../platform/compat/process.js";
21
21
 
22
+ /** Options for command execution: working directory, timeout, and environment variables. */
23
+ export interface ExecOptions {
24
+ /** Working directory for the command. */
25
+ cwd?: string;
26
+ /** Timeout in seconds for the command. */
27
+ timeout_seconds?: number;
28
+ /** Additional environment variables for the command. */
29
+ env?: Record<string, string>;
30
+ }
31
+
22
32
  /** Options for creating a sandbox session. */
23
33
  export interface SandboxOptions {
24
34
  /** Base URL of the Veryfront API. Defaults to VERYFRONT_API_URL env. */
@@ -242,12 +252,12 @@ export class Sandbox {
242
252
  }
243
253
 
244
254
  /** Execute a bash command in the sandbox and return buffered result. */
245
- async executeCommand(command: string): Promise<ExecResult> {
255
+ async executeCommand(command: string, options?: ExecOptions): Promise<ExecResult> {
246
256
  let stdout = "";
247
257
  let stderr = "";
248
258
  let exitCode = 1;
249
259
 
250
- for await (const event of this.executeStream(command)) {
260
+ for await (const event of this.executeStream(command, options)) {
251
261
  switch (event.type) {
252
262
  case "stdout":
253
263
  stdout += event.data ?? "";
@@ -265,14 +275,14 @@ export class Sandbox {
265
275
  }
266
276
 
267
277
  /** Execute a bash command with streaming output (NDJSON). */
268
- async *executeStream(command: string): AsyncGenerator<ExecStreamEvent> {
278
+ async *executeStream(command: string, options?: ExecOptions): AsyncGenerator<ExecStreamEvent> {
269
279
  const res = await dntShim.fetch(`${this.endpoint}/exec`, {
270
280
  method: "POST",
271
281
  headers: {
272
282
  Authorization: `Bearer ${this.authToken}`,
273
283
  "Content-Type": "application/json",
274
284
  },
275
- body: JSON.stringify({ command }),
285
+ body: JSON.stringify({ command, ...options }),
276
286
  });
277
287
 
278
288
  if (!res.ok) {
@@ -343,14 +353,14 @@ export class Sandbox {
343
353
  }
344
354
 
345
355
  /** Start an async command job in the sandbox. */
346
- async startCommandJob(command: string): Promise<CommandJob> {
356
+ async startCommandJob(command: string, options?: ExecOptions): Promise<CommandJob> {
347
357
  const res = await dntShim.fetch(`${this.endpoint}/exec/jobs`, {
348
358
  method: "POST",
349
359
  headers: {
350
360
  Authorization: `Bearer ${this.authToken}`,
351
361
  "Content-Type": "application/json",
352
362
  },
353
- body: JSON.stringify({ command }),
363
+ body: JSON.stringify({ command, ...options }),
354
364
  });
355
365
 
356
366
  if (!res.ok) {
@@ -399,6 +409,23 @@ export class Sandbox {
399
409
  };
400
410
  }
401
411
 
412
+ /** List all command jobs in the sandbox. */
413
+ async listCommandJobs(): Promise<CommandJob[]> {
414
+ const res = await dntShim.fetch(`${this.endpoint}/exec/jobs`, {
415
+ headers: { Authorization: `Bearer ${this.authToken}` },
416
+ });
417
+
418
+ if (!res.ok) {
419
+ throw REQUEST_ERROR.create({
420
+ detail: `List command jobs failed: ${res.status} ${await res.text()}`,
421
+ });
422
+ }
423
+
424
+ const json = await res.json();
425
+ const jobs = Array.isArray(json) ? json : (json.jobs ?? []);
426
+ return jobs.map((j: Record<string, unknown>) => Sandbox.mapCommandJob(j));
427
+ }
428
+
402
429
  /** Cancel an async command job. */
403
430
  async cancelCommandJob(jobId: string): Promise<CommandJob> {
404
431
  const res = await dntShim.fetch(`${this.endpoint}/exec/jobs/${jobId}/cancel`, {
@@ -7,6 +7,7 @@ import type {
7
7
  RoutePattern,
8
8
  } from "../../types/index.js";
9
9
  import { runWithCacheBatching } from "../../cache/request-cache-batcher.js";
10
+ import { getHostEnv } from "../../platform/compat/process.js";
10
11
  import { serverLogger } from "../../utils/index.js";
11
12
  import { ResponseBuilder } from "./response/index.js";
12
13
 
@@ -78,7 +79,7 @@ export abstract class BaseHandler implements Handler {
78
79
  }
79
80
 
80
81
  protected logDebug(message: string, extra?: Record<string, unknown>, ctx?: HandlerContext): void {
81
- if (!ctx?.debug && !ctx?.adapter.env.get("VERYFRONT_DEBUG")) return;
82
+ if (!ctx?.debug && !getHostEnv("VERYFRONT_DEBUG")) return;
82
83
  serverLogger.debug(`[${this.metadata.name}] ${message}`, extra ?? undefined);
83
84
  }
84
85
 
@@ -108,7 +109,9 @@ export abstract class BaseHandler implements Handler {
108
109
  fn: () => Promise<T>,
109
110
  options: { requireToken?: boolean } = {},
110
111
  ): Promise<T> {
111
- const effectiveToken = ctx.proxyToken || ctx.adapter.env.get("VERYFRONT_API_TOKEN") || "";
112
+ // Framework-owned token: bypass project env overlay so proxy mode works
113
+ // when a remote project overlay is active.
114
+ const effectiveToken = ctx.proxyToken || getHostEnv("VERYFRONT_API_TOKEN") || "";
112
115
  const fsWrapper = ctx.adapter.fs as {
113
116
  setRequestToken?: (t: string) => void;
114
117
  setRequestBranch?: (b: string | null) => void;
@@ -1,5 +1,5 @@
1
1
  import * as dntShim from "../../../_dnt.shims.js";
2
- import { getEnv } from "../../platform/compat/process.js";
2
+ import { getHostEnv } from "../../platform/compat/process.js";
3
3
  import { parseProjectDomain } from "../utils/domain-parser.js";
4
4
 
5
5
  export interface RequestContext {
@@ -28,7 +28,9 @@ export function createRequestContext(req: dntShim.Request): RequestContext {
28
28
  : "production";
29
29
 
30
30
  return {
31
- token: req.headers.get("x-token") ?? getEnv("VERYFRONT_API_TOKEN") ?? "",
31
+ // Framework-owned token: bypass project env overlay so proxy mode works
32
+ // when a remote project overlay is active.
33
+ token: req.headers.get("x-token") ?? getHostEnv("VERYFRONT_API_TOKEN") ?? "",
32
34
  slug: req.headers.get("x-project-slug") ?? parsed.slug ?? "",
33
35
  branch: parsed.branch,
34
36
  mode,
@@ -29,6 +29,7 @@ import { createStyleScopeProfile } from "../../../html/styles-builder/style-scop
29
29
  import { serverLogger } from "../../../utils/index.js";
30
30
  import type { ResolvedContentContext } from "../../../platform/adapters/fs/veryfront/types.js";
31
31
  import type {
32
+ EnsureStyleArtifactBuildInput,
32
33
  ResolveStyleArtifactInput,
33
34
  VeryfrontApiClient,
34
35
  } from "../../../platform/adapters/veryfront-api-client/index.js";
@@ -353,6 +354,9 @@ body::before {
353
354
  });
354
355
 
355
356
  if (resolved.status !== "ready" || !resolved.artifactHash) {
357
+ if (resolved.status !== "building") {
358
+ await this.ensureRemotePreparedCSSBuild(client, selector, styleProfileHash);
359
+ }
356
360
  return undefined;
357
361
  }
358
362
 
@@ -415,4 +419,31 @@ body::before {
415
419
  });
416
420
  }
417
421
  }
422
+
423
+ private shouldEnsureRemoteStyleArtifactBuild(selector: StyleArtifactSelectorContext): boolean {
424
+ return Boolean(selector.environmentName || selector.releaseId);
425
+ }
426
+
427
+ private async ensureRemotePreparedCSSBuild(
428
+ client: VeryfrontApiClient,
429
+ selector: StyleArtifactSelectorContext,
430
+ styleProfileHash: string,
431
+ ): Promise<void> {
432
+ if (!this.shouldEnsureRemoteStyleArtifactBuild(selector)) return;
433
+
434
+ try {
435
+ await client.ensureStyleArtifactBuild(
436
+ {
437
+ ...selector,
438
+ styleProfileHash,
439
+ } satisfies EnsureStyleArtifactBuildInput,
440
+ );
441
+ } catch (error) {
442
+ logger.debug("Failed to ensure remote prepared CSS build", {
443
+ selector,
444
+ styleProfileHash,
445
+ error: error instanceof Error ? error.message : String(error),
446
+ });
447
+ }
448
+ }
418
449
  }
@@ -16,7 +16,7 @@ import { HTTP_OK } from "../../../utils/constants/index.js";
16
16
  import { compileMarkdownRuntime } from "../../../transforms/md/compiler/md-compiler.js";
17
17
  import { extract } from "../../../platform/compat/std/front-matter-yaml.js";
18
18
  import { isExtendedFSAdapter } from "../../../platform/adapters/fs/wrapper.js";
19
- import { getEnv } from "../../../platform/compat/process.js";
19
+ import { getHostEnv } from "../../../platform/compat/process.js";
20
20
  import { tryNotFoundFallback } from "../request/ssr/not-found-fallback.js";
21
21
  import { generateMarkdownHtml } from "./markdown-html-generator.js";
22
22
  import { validatePathSync } from "../../../security/index.js";
@@ -70,7 +70,9 @@ export class MarkdownPreviewHandler extends BaseHandler {
70
70
  const hasMultiProjectSupport = isExtendedFSAdapter(fsAdapter) && fsAdapter.isMultiProjectMode();
71
71
 
72
72
  if (ctx.projectSlug && hasMultiProjectSupport) {
73
- const effectiveToken = ctx.proxyToken || getEnv("VERYFRONT_API_TOKEN") || "";
73
+ // Framework-owned token: bypass project env overlay so proxy mode works
74
+ // when a remote project overlay is active.
75
+ const effectiveToken = ctx.proxyToken || getHostEnv("VERYFRONT_API_TOKEN") || "";
74
76
  const branch = ctx.parsedDomain?.branch ?? null;
75
77
 
76
78
  return await fsAdapter.runWithContext(
@@ -10,7 +10,7 @@ import {
10
10
  extractCacheKeyContext,
11
11
  runWithCacheKeyContext,
12
12
  } from "../../../cache/cache-key-builder.js";
13
- import { getEnv } from "../../../platform/compat/process.js";
13
+ import { getHostEnv } from "../../../platform/compat/process.js";
14
14
  import { runWithRequestContext } from "../../../platform/adapters/fs/veryfront/multi-project-adapter.js";
15
15
 
16
16
  /** Pattern to match hashed CSS URLs: /_vf/css/[8-char-hash].css */
@@ -50,7 +50,9 @@ export class CSSHandler extends BaseHandler {
50
50
  // the distributed API cache backend can't authenticate and silently returns
51
51
  // null — causing cross-pod cache misses. Wrap the lookup in request context
52
52
  // so the API backend can resolve the token and project.
53
- const effectiveToken = ctx.proxyToken || getEnv("VERYFRONT_API_TOKEN") || "";
53
+ // Framework-owned token: bypass project env overlay so proxy mode works
54
+ // when a remote project overlay is active.
55
+ const effectiveToken = ctx.proxyToken || getHostEnv("VERYFRONT_API_TOKEN") || "";
54
56
  const lookup = () =>
55
57
  runWithCacheKeyContext(cacheCtx, () =>
56
58
  getCSSWithJITFallback(
@@ -19,7 +19,7 @@ import type {
19
19
  import { PRIORITY_LOW } from "../../../../utils/constants/index.js";
20
20
  import { generateNonce } from "../../../../security/http/response/security-handler.js";
21
21
  import { isExtendedFSAdapter } from "../../../../platform/adapters/fs/wrapper.js";
22
- import { getEnv } from "../../../../platform/compat/process.js";
22
+ import { getHostEnv } from "../../../../platform/compat/process.js";
23
23
  import { shouldUseNoCacheHeadersFromHandler } from "../../../context/enriched-context.js";
24
24
  import { withSpan } from "../../../../observability/tracing/otlp-setup.js";
25
25
  import { serverLogger } from "../../../../utils/index.js";
@@ -117,7 +117,9 @@ export class SSRHandler extends BaseHandler {
117
117
  if (ctx.projectSlug && isExtended && fsAdapter.isMultiProjectMode()) {
118
118
  const prodMode = isProductionMode(ctx, url);
119
119
  const branch = ctx.parsedDomain?.branch ?? null;
120
- const effectiveToken = ctx.proxyToken || getEnv("VERYFRONT_API_TOKEN") || "";
120
+ // Framework-owned token: bypass project env overlay so proxy mode works
121
+ // when a remote project overlay is active.
122
+ const effectiveToken = ctx.proxyToken || getHostEnv("VERYFRONT_API_TOKEN") || "";
121
123
 
122
124
  logger.debug("Using multi-project context", {
123
125
  projectSlug: ctx.projectSlug,
@@ -3,7 +3,7 @@ import { getEnv } from "../platform/compat/process.js";
3
3
 
4
4
  // Keep in sync with deno.json version.
5
5
  // scripts/release.ts updates this constant during releases.
6
- export const VERSION = "0.1.92";
6
+ export const VERSION = "0.1.93";
7
7
 
8
8
  export function normalizeVeryfrontVersion(version: string | undefined): string | undefined {
9
9
  if (!version) return undefined;