veryfront 0.1.90 → 0.1.91

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 (36) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/jobs/schemas.d.ts +30 -30
  3. package/esm/src/platform/adapters/veryfront-api-client/client.d.ts +3 -1
  4. package/esm/src/platform/adapters/veryfront-api-client/client.d.ts.map +1 -1
  5. package/esm/src/platform/adapters/veryfront-api-client/client.js +6 -0
  6. package/esm/src/platform/adapters/veryfront-api-client/index.d.ts +2 -2
  7. package/esm/src/platform/adapters/veryfront-api-client/index.d.ts.map +1 -1
  8. package/esm/src/platform/adapters/veryfront-api-client/index.js +1 -1
  9. package/esm/src/platform/adapters/veryfront-api-client/operations.d.ts +24 -0
  10. package/esm/src/platform/adapters/veryfront-api-client/operations.d.ts.map +1 -1
  11. package/esm/src/platform/adapters/veryfront-api-client/operations.js +65 -3
  12. package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.d.ts +28 -0
  13. package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.d.ts.map +1 -1
  14. package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.js +13 -0
  15. package/esm/src/platform/adapters/veryfront-api-client/schemas/index.d.ts +1 -1
  16. package/esm/src/platform/adapters/veryfront-api-client/schemas/index.d.ts.map +1 -1
  17. package/esm/src/platform/adapters/veryfront-api-client/schemas/index.js +1 -1
  18. package/esm/src/sandbox/index.d.ts +1 -1
  19. package/esm/src/sandbox/index.d.ts.map +1 -1
  20. package/esm/src/sandbox/index.js +1 -1
  21. package/esm/src/sandbox/sandbox.d.ts +58 -0
  22. package/esm/src/sandbox/sandbox.d.ts.map +1 -1
  23. package/esm/src/sandbox/sandbox.js +111 -0
  24. package/esm/src/server/handlers/dev/styles-css.handler.d.ts +5 -0
  25. package/esm/src/server/handlers/dev/styles-css.handler.d.ts.map +1 -1
  26. package/esm/src/server/handlers/dev/styles-css.handler.js +121 -1
  27. package/package.json +1 -1
  28. package/src/deno.js +1 -1
  29. package/src/src/platform/adapters/veryfront-api-client/client.ts +17 -0
  30. package/src/src/platform/adapters/veryfront-api-client/index.ts +6 -0
  31. package/src/src/platform/adapters/veryfront-api-client/operations.ts +110 -3
  32. package/src/src/platform/adapters/veryfront-api-client/schemas/api.schema.ts +16 -0
  33. package/src/src/platform/adapters/veryfront-api-client/schemas/index.ts +2 -0
  34. package/src/src/sandbox/index.ts +13 -1
  35. package/src/src/sandbox/sandbox.ts +183 -0
  36. package/src/src/server/handlers/dev/styles-css.handler.ts +179 -1
@@ -17,6 +17,53 @@ export interface ExecStreamEvent {
17
17
  data?: string;
18
18
  exitCode?: number;
19
19
  }
20
+ /** Status of an async command job. */
21
+ export type CommandJobStatus = "running" | "completed" | "failed" | "canceled";
22
+ /** Heartbeat health status for a command job. */
23
+ export type CommandJobHeartbeatStatus = "disabled" | "healthy" | "degraded";
24
+ /** An async command job running in a sandbox. */
25
+ export interface CommandJob {
26
+ id: string;
27
+ status: CommandJobStatus;
28
+ exitCode: number | null;
29
+ signal: string | null;
30
+ startedAt: string;
31
+ finishedAt: string | null;
32
+ heartbeatStatus: CommandJobHeartbeatStatus;
33
+ lastHeartbeatAt: string | null;
34
+ lastHeartbeatError: string | null;
35
+ heartbeatFailureCount: number;
36
+ }
37
+ /** A command job with its captured output. */
38
+ export interface CommandJobOutput extends CommandJob {
39
+ stdout: string;
40
+ stderr: string;
41
+ stdoutTruncated: boolean;
42
+ stderrTruncated: boolean;
43
+ }
44
+ /** A sandbox session summary returned by list. */
45
+ export interface SandboxSession {
46
+ id: string;
47
+ shortId: string;
48
+ endpoint: string;
49
+ status: string;
50
+ createdAt: string;
51
+ }
52
+ /** Options for listing sandbox sessions. */
53
+ export interface SandboxListOptions extends SandboxOptions {
54
+ cursor?: string;
55
+ limit?: number;
56
+ }
57
+ /** Paginated result of sandbox sessions. */
58
+ export interface SandboxListResult {
59
+ data: SandboxSession[];
60
+ pageInfo: {
61
+ self: string | null;
62
+ first: null;
63
+ next: string | null;
64
+ prev: string | null;
65
+ };
66
+ }
20
67
  /** Client for isolated ephemeral compute environments with command execution and file I/O. */
21
68
  export declare class Sandbox {
22
69
  private endpoint;
@@ -30,6 +77,8 @@ export declare class Sandbox {
30
77
  static create(options?: SandboxOptions): Promise<Sandbox>;
31
78
  /** Reconnect to an existing sandbox session. */
32
79
  static get(id: string, options?: SandboxOptions): Promise<Sandbox>;
80
+ /** List sandbox sessions with optional pagination. */
81
+ static list(options?: SandboxListOptions): Promise<SandboxListResult>;
33
82
  private static waitForReady;
34
83
  /** Execute a bash command in the sandbox and return buffered result. */
35
84
  executeCommand(command: string): Promise<ExecResult>;
@@ -42,6 +91,15 @@ export declare class Sandbox {
42
91
  path: string;
43
92
  content: string;
44
93
  }>): Promise<void>;
94
+ /** Start an async command job in the sandbox. */
95
+ startCommandJob(command: string): Promise<CommandJob>;
96
+ /** Get the status of an async command job. */
97
+ getCommandJob(jobId: string): Promise<CommandJob>;
98
+ /** Get the output of an async command job. */
99
+ getCommandJobOutput(jobId: string): Promise<CommandJobOutput>;
100
+ /** Cancel an async command job. */
101
+ cancelCommandJob(jobId: string): Promise<CommandJob>;
102
+ private static mapCommandJob;
45
103
  /** Send a heartbeat to prevent idle timeout. */
46
104
  heartbeat(): Promise<void>;
47
105
  /** Close the sandbox session and mark for deletion. */
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/src/sandbox/sandbox.ts"],"names":[],"mappings":"AAqBA,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,8FAA8F;AAC9F,qBAAa,OAAO;IAEhB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,MAAM;IAJhB,OAAO;IAOP,OAAO,CAAC,MAAM,CAAC,aAAa;IAM5B,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAa/B,4EAA4E;WAC/D,MAAM,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IA4BnE,gDAAgD;WACnC,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;mBAkBvD,YAAY;IA6BjC,wEAAwE;IAClE,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAsB1D,6DAA6D;IACtD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC,eAAe,CAAC;IAyCtE,8CAA8C;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAe7C,4CAA4C;IACtC,UAAU,CACd,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAC9C,OAAO,CAAC,IAAI,CAAC;IAiBhB,gDAAgD;IAC1C,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAOhC,uDAAuD;IACjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,0BAA0B;IAC1B,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,oCAAoC;IACpC,IAAI,GAAG,IAAI,MAAM,CAEhB;CACF"}
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/src/sandbox/sandbox.ts"],"names":[],"mappings":"AAqBA,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,sCAAsC;AACtC,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE/E,iDAAiD;AACjD,MAAM,MAAM,yBAAyB,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;AAE5E,iDAAiD;AACjD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,EAAE,yBAAyB,CAAC;IAC3C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,8CAA8C;AAC9C,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,4CAA4C;AAC5C,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,KAAK,EAAE,IAAI,CAAC;QACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;KACrB,CAAC;CACH;AAED,8FAA8F;AAC9F,qBAAa,OAAO;IAEhB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,MAAM;IAJhB,OAAO;IAOP,OAAO,CAAC,MAAM,CAAC,aAAa;IAM5B,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAa/B,4EAA4E;WAC/D,MAAM,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IA4BnE,gDAAgD;WACnC,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAkB5E,sDAAsD;WACzC,IAAI,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;mBAwC1D,YAAY;IA6BjC,wEAAwE;IAClE,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAsB1D,6DAA6D;IACtD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC,eAAe,CAAC;IAyCtE,8CAA8C;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAe7C,4CAA4C;IACtC,UAAU,CACd,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAC9C,OAAO,CAAC,IAAI,CAAC;IAiBhB,iDAAiD;IAC3C,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAmB3D,8CAA8C;IACxC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAcvD,8CAA8C;IACxC,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAqBnE,mCAAmC;IAC7B,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAe1D,OAAO,CAAC,MAAM,CAAC,aAAa;IAe5B,gDAAgD;IAC1C,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAOhC,uDAAuD;IACjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,0BAA0B;IAC1B,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,oCAAoC;IACpC,IAAI,GAAG,IAAI,MAAM,CAEhB;CACF"}
@@ -74,6 +74,42 @@ export class Sandbox {
74
74
  const { endpoint } = await res.json();
75
75
  return new Sandbox(endpoint, id, authToken, apiUrl);
76
76
  }
77
+ /** List sandbox sessions with optional pagination. */
78
+ static async list(options = {}) {
79
+ const apiUrl = Sandbox.resolveApiUrl(options);
80
+ const authToken = Sandbox.resolveAuthToken(options);
81
+ const params = new URLSearchParams();
82
+ if (options.cursor)
83
+ params.set("cursor", options.cursor);
84
+ if (options.limit !== undefined)
85
+ params.set("limit", String(options.limit));
86
+ const query = params.toString();
87
+ const url = `${apiUrl}/sandbox-sessions${query ? `?${query}` : ""}`;
88
+ const res = await dntShim.fetch(url, {
89
+ headers: { Authorization: `Bearer ${authToken}` },
90
+ });
91
+ if (!res.ok) {
92
+ throw REQUEST_ERROR.create({
93
+ detail: `Failed to list sandboxes: ${res.status} ${await res.text()}`,
94
+ });
95
+ }
96
+ const json = await res.json();
97
+ return {
98
+ data: json.data.map((s) => ({
99
+ id: s.id,
100
+ shortId: s.short_id,
101
+ endpoint: s.endpoint,
102
+ status: s.status,
103
+ createdAt: s.created_at,
104
+ })),
105
+ pageInfo: {
106
+ self: json.page_info?.self ?? null,
107
+ first: null,
108
+ next: json.page_info?.next ?? null,
109
+ prev: json.page_info?.prev ?? null,
110
+ },
111
+ };
112
+ }
77
113
  static async waitForReady(apiUrl, id, authToken, maxWaitMs = 60_000, pollIntervalMs = 2_000) {
78
114
  const start = Date.now();
79
115
  while (Date.now() - start < maxWaitMs) {
@@ -177,6 +213,81 @@ export class Sandbox {
177
213
  });
178
214
  }
179
215
  }
216
+ /** Start an async command job in the sandbox. */
217
+ async startCommandJob(command) {
218
+ const res = await dntShim.fetch(`${this.endpoint}/exec/jobs`, {
219
+ method: "POST",
220
+ headers: {
221
+ Authorization: `Bearer ${this.authToken}`,
222
+ "Content-Type": "application/json",
223
+ },
224
+ body: JSON.stringify({ command }),
225
+ });
226
+ if (!res.ok) {
227
+ throw REQUEST_ERROR.create({
228
+ detail: `Start command job failed: ${res.status} ${await res.text()}`,
229
+ });
230
+ }
231
+ return Sandbox.mapCommandJob(await res.json());
232
+ }
233
+ /** Get the status of an async command job. */
234
+ async getCommandJob(jobId) {
235
+ const res = await dntShim.fetch(`${this.endpoint}/exec/jobs/${jobId}`, {
236
+ headers: { Authorization: `Bearer ${this.authToken}` },
237
+ });
238
+ if (!res.ok) {
239
+ throw REQUEST_ERROR.create({
240
+ detail: `Get command job failed: ${res.status} ${await res.text()}`,
241
+ });
242
+ }
243
+ return Sandbox.mapCommandJob(await res.json());
244
+ }
245
+ /** Get the output of an async command job. */
246
+ async getCommandJobOutput(jobId) {
247
+ const res = await dntShim.fetch(`${this.endpoint}/exec/jobs/${jobId}/output`, {
248
+ headers: { Authorization: `Bearer ${this.authToken}` },
249
+ });
250
+ if (!res.ok) {
251
+ throw REQUEST_ERROR.create({
252
+ detail: `Get command job output failed: ${res.status} ${await res.text()}`,
253
+ });
254
+ }
255
+ const json = await res.json();
256
+ return {
257
+ ...Sandbox.mapCommandJob(json),
258
+ stdout: json.stdout,
259
+ stderr: json.stderr,
260
+ stdoutTruncated: json.stdout_truncated,
261
+ stderrTruncated: json.stderr_truncated,
262
+ };
263
+ }
264
+ /** Cancel an async command job. */
265
+ async cancelCommandJob(jobId) {
266
+ const res = await dntShim.fetch(`${this.endpoint}/exec/jobs/${jobId}/cancel`, {
267
+ method: "POST",
268
+ headers: { Authorization: `Bearer ${this.authToken}` },
269
+ });
270
+ if (!res.ok) {
271
+ throw REQUEST_ERROR.create({
272
+ detail: `Cancel command job failed: ${res.status} ${await res.text()}`,
273
+ });
274
+ }
275
+ return Sandbox.mapCommandJob(await res.json());
276
+ }
277
+ static mapCommandJob(json) {
278
+ return {
279
+ id: json.id,
280
+ status: json.status,
281
+ exitCode: json.exit_code,
282
+ signal: json.signal,
283
+ startedAt: json.started_at,
284
+ finishedAt: json.finished_at,
285
+ heartbeatStatus: json.heartbeat_status,
286
+ lastHeartbeatAt: json.last_heartbeat_at,
287
+ lastHeartbeatError: json.last_heartbeat_error,
288
+ heartbeatFailureCount: json.heartbeat_failure_count,
289
+ };
290
+ }
180
291
  /** Send a heartbeat to prevent idle timeout. */
181
292
  async heartbeat() {
182
293
  await dntShim.fetch(`${this.apiUrl}/sandbox-sessions/${this.sessionId}/heartbeat`, {
@@ -13,6 +13,11 @@ export declare class StylesCSSHandler extends BaseHandler {
13
13
  private loadStylesheet;
14
14
  private generateStylesheet;
15
15
  private getContentContext;
16
+ private getVeryfrontApiClient;
16
17
  private createPreparedCSSContext;
18
+ private resolveStyleArtifactSelector;
19
+ private tryResolveRemotePreparedCSS;
20
+ private getPreparedCSSByHash;
21
+ private registerPreparedCSSArtifact;
17
22
  }
18
23
  //# sourceMappingURL=styles-css.handler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"styles-css.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/dev/styles-css.handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAoBnG,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,EAAE,eAAe,CAKvB;IAEI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;YAqIjE,cAAc;IAkB5B,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,wBAAwB;CAyBjC"}
1
+ {"version":3,"file":"styles-css.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/dev/styles-css.handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AA+BnG,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,EAAE,eAAe,CAKvB;IAEI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;YAiKjE,cAAc;IAkB5B,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,wBAAwB;IA0BhC,OAAO,CAAC,4BAA4B;YA2CtB,2BAA2B;YAiD3B,oBAAoB;YASpB,2BAA2B;CA0B1C"}
@@ -1,7 +1,7 @@
1
1
  import { BaseHandler } from "../response/base.js";
2
2
  import { HTTP_OK, PRIORITY_HIGH_DEV } from "../../../utils/constants/index.js";
3
3
  import { joinPath } from "../../../utils/path-utils.js";
4
- import { formatCSSError, getProjectCSS } from "../../../html/styles-builder/tailwind-compiler.js";
4
+ import { formatCSSError, getCSSByHashAsync, getProjectCSS, regenerateCSSByHash, } from "../../../html/styles-builder/tailwind-compiler.js";
5
5
  import { DEFAULT_STYLESHEET } from "../../../html/styles-builder/css-hash-cache.js";
6
6
  import { resolveStyleContentVersion } from "../../../html/styles-builder/content-version.js";
7
7
  import { createPreparedProjectCSSContext, storePreparedProjectCSS, tryGetPreparedProjectCSS, } from "../../../html/styles-builder/prepared-project-css-cache.js";
@@ -48,6 +48,15 @@ export class StylesCSSHandler extends BaseHandler {
48
48
  return this.respond(responseBuilder.withContentType("text/css; charset=utf-8", prepared.css, HTTP_OK));
49
49
  }
50
50
  }
51
+ const remotePrepared = await this.tryResolveRemotePreparedCSS(ctx, projectScope, styleProfile.hash, contentContext, preparedContext);
52
+ if (remotePrepared) {
53
+ logger.debug("Prepared CSS resolved via style artifact metadata", {
54
+ projectScope,
55
+ styleProfileHash: styleProfile.hash,
56
+ cssHash: remotePrepared.hash,
57
+ });
58
+ return this.respond(responseBuilder.withContentType("text/css; charset=utf-8", remotePrepared.css, HTTP_OK));
59
+ }
51
60
  let candidates;
52
61
  try {
53
62
  candidates = await extractProjectCandidates(ctx);
@@ -112,6 +121,9 @@ body::before {
112
121
  hash: result.hash,
113
122
  });
114
123
  }
124
+ if ("hash" in result) {
125
+ await this.registerPreparedCSSArtifact(ctx, styleProfile.hash, contentContext, result.hash);
126
+ }
115
127
  return this.respond(responseBuilder.withContentType("text/css; charset=utf-8", result.css, HTTP_OK));
116
128
  });
117
129
  }
@@ -158,6 +170,13 @@ body::before {
158
170
  const fsAdapter = wrappedFs.getUnderlyingAdapter();
159
171
  return typeof fsAdapter.getContentContext === "function" ? fsAdapter.getContentContext() : null;
160
172
  }
173
+ getVeryfrontApiClient(ctx) {
174
+ const wrappedFs = ctx.adapter.fs;
175
+ if (typeof wrappedFs.getUnderlyingAdapter !== "function")
176
+ return null;
177
+ const fsAdapter = wrappedFs.getUnderlyingAdapter();
178
+ return typeof fsAdapter.getClient === "function" ? fsAdapter.getClient() : null;
179
+ }
161
180
  createPreparedCSSContext(projectScope, rawCss, styleProfileHash, contentContext, ctx) {
162
181
  if (!projectScope)
163
182
  return undefined;
@@ -171,4 +190,105 @@ body::before {
171
190
  buildMode: "production",
172
191
  });
173
192
  }
193
+ resolveStyleArtifactSelector(contentContext, ctx) {
194
+ if (contentContext?.sourceType === "branch" && contentContext.branch) {
195
+ return {
196
+ branch: contentContext.branch,
197
+ };
198
+ }
199
+ if (contentContext?.sourceType === "environment" && contentContext.environmentName) {
200
+ return {
201
+ environmentName: contentContext.environmentName,
202
+ };
203
+ }
204
+ if (contentContext?.sourceType === "release" && contentContext.releaseId) {
205
+ return {
206
+ releaseId: contentContext.releaseId,
207
+ };
208
+ }
209
+ if (ctx.parsedDomain?.branch) {
210
+ return {
211
+ branch: ctx.parsedDomain.branch,
212
+ };
213
+ }
214
+ if (ctx.environmentName) {
215
+ return {
216
+ environmentName: ctx.environmentName,
217
+ };
218
+ }
219
+ if (ctx.releaseId) {
220
+ return {
221
+ releaseId: ctx.releaseId,
222
+ };
223
+ }
224
+ return null;
225
+ }
226
+ async tryResolveRemotePreparedCSS(ctx, projectScope, styleProfileHash, contentContext, preparedContext) {
227
+ if (!projectScope)
228
+ return undefined;
229
+ const selector = this.resolveStyleArtifactSelector(contentContext, ctx);
230
+ if (!selector)
231
+ return undefined;
232
+ const client = this.getVeryfrontApiClient(ctx);
233
+ if (!client)
234
+ return undefined;
235
+ try {
236
+ const resolved = await client.resolveStyleArtifact({
237
+ ...selector,
238
+ styleProfileHash,
239
+ });
240
+ if (resolved.status !== "ready" || !resolved.artifactHash) {
241
+ return undefined;
242
+ }
243
+ const css = await this.getPreparedCSSByHash(resolved.artifactHash, projectScope);
244
+ if (!css)
245
+ return undefined;
246
+ if (preparedContext) {
247
+ await storePreparedProjectCSS(preparedContext, {
248
+ css,
249
+ hash: resolved.artifactHash,
250
+ });
251
+ }
252
+ return {
253
+ css,
254
+ hash: resolved.artifactHash,
255
+ };
256
+ }
257
+ catch (error) {
258
+ logger.debug("Failed to resolve prepared CSS via style artifact metadata", {
259
+ projectScope,
260
+ styleProfileHash,
261
+ error: error instanceof Error ? error.message : String(error),
262
+ });
263
+ return undefined;
264
+ }
265
+ }
266
+ async getPreparedCSSByHash(cssHash, projectScope) {
267
+ const cached = await getCSSByHashAsync(cssHash);
268
+ if (cached)
269
+ return cached;
270
+ return regenerateCSSByHash(cssHash, projectScope);
271
+ }
272
+ async registerPreparedCSSArtifact(ctx, styleProfileHash, contentContext, cssHash) {
273
+ const selector = this.resolveStyleArtifactSelector(contentContext, ctx);
274
+ if (!selector)
275
+ return;
276
+ const client = this.getVeryfrontApiClient(ctx);
277
+ if (!client)
278
+ return;
279
+ try {
280
+ await client.upsertStyleArtifact({
281
+ ...selector,
282
+ styleProfileHash,
283
+ artifactHash: cssHash,
284
+ });
285
+ }
286
+ catch (error) {
287
+ logger.debug("Failed to register prepared CSS artifact", {
288
+ cssHash,
289
+ styleProfileHash,
290
+ error: error instanceof Error ? error.message : String(error),
291
+ });
292
+ }
293
+ }
174
294
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.90",
3
+ "version": "0.1.91",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
package/src/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.90",
3
+ "version": "0.1.91",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -3,7 +3,10 @@ import {
3
3
  type FileDetail,
4
4
  type FileListResult,
5
5
  type ListFilesOptions,
6
+ type ProjectStyleArtifactResolution,
7
+ type ResolveStyleArtifactInput,
6
8
  type TokenProvider,
9
+ type UpsertStyleArtifactInput,
7
10
  VeryfrontAPIOperations,
8
11
  } from "./operations.js";
9
12
  import { API_CLIENT_ERROR, type VeryfrontAPIConfig } from "./types.js";
@@ -340,6 +343,20 @@ export class VeryfrontApiClient {
340
343
  return this.operations.lookupProjectByDomain(domain);
341
344
  }
342
345
 
346
+ resolveStyleArtifact(
347
+ input: ResolveStyleArtifactInput,
348
+ projectRef = this.getProjectSlug()!,
349
+ ): Promise<ProjectStyleArtifactResolution> {
350
+ return this.operations.resolveStyleArtifact(projectRef, input);
351
+ }
352
+
353
+ upsertStyleArtifact(
354
+ input: UpsertStyleArtifactInput,
355
+ projectRef = this.getProjectSlug()!,
356
+ ): Promise<ProjectStyleArtifactResolution> {
357
+ return this.operations.upsertStyleArtifact(projectRef, input);
358
+ }
359
+
343
360
  // =============================================================================
344
361
  // Adapter Convenience Methods
345
362
  // =============================================================================
@@ -9,6 +9,10 @@ export {
9
9
  type FileDetail,
10
10
  type FileListResult,
11
11
  type ListFilesOptions,
12
+ type ProjectStyleArtifactResolution,
13
+ type ResolveStyleArtifactInput,
14
+ type StyleArtifactSelector,
15
+ type UpsertStyleArtifactInput,
12
16
  VeryfrontAPIOperations,
13
17
  } from "./operations.js";
14
18
  export { type RequestOptions, requestWithRetry, type RetryConfig } from "./retry-handler.js";
@@ -39,4 +43,6 @@ export {
39
43
  ProjectSchema,
40
44
  ReleaseFileDetailSchema,
41
45
  ReleaseFileListItemSchema,
46
+ type StyleArtifactResolveResponse,
47
+ StyleArtifactResolveResponseSchema,
42
48
  } from "./schemas/index.js";
@@ -1,6 +1,6 @@
1
1
  import { logger as baseLogger } from "../../../utils/index.js";
2
2
  import { z } from "zod";
3
- import { requestWithRetry, type RetryConfig } from "./retry-handler.js";
3
+ import { type RequestOptions, requestWithRetry, type RetryConfig } from "./retry-handler.js";
4
4
  import { API_CLIENT_ERROR } from "./types.js";
5
5
  import {
6
6
  BranchFileDetailSchema,
@@ -15,6 +15,7 @@ import {
15
15
  type ProjectFile,
16
16
  ProjectSchema,
17
17
  ReleaseFileDetailSchema,
18
+ StyleArtifactResolveResponseSchema,
18
19
  } from "./schemas/index.js";
19
20
  import { withSpan } from "../../../observability/tracing/otlp-setup.js";
20
21
  import { SpanNames } from "../../../observability/tracing/span-names.js";
@@ -53,6 +54,32 @@ export interface FileDetail {
53
54
  release_version?: string | null;
54
55
  }
55
56
 
57
+ export interface StyleArtifactSelector {
58
+ branch?: string;
59
+ environmentName?: string;
60
+ releaseId?: string;
61
+ }
62
+
63
+ export interface ResolveStyleArtifactInput extends StyleArtifactSelector {
64
+ styleProfileHash: string;
65
+ }
66
+
67
+ export interface UpsertStyleArtifactInput extends ResolveStyleArtifactInput {
68
+ artifactHash: string;
69
+ assetPath?: string;
70
+ contentType?: string;
71
+ etag?: string;
72
+ }
73
+
74
+ export interface ProjectStyleArtifactResolution {
75
+ status: "ready" | "missing";
76
+ artifactHash?: string;
77
+ assetPath?: string;
78
+ etag?: string;
79
+ contentType?: string;
80
+ updatedAt?: string;
81
+ }
82
+
56
83
  function buildListParams(options: ListFilesOptions): URLSearchParams {
57
84
  const { cursor, limit = DEFAULT_PAGE_LIMIT, pattern, sortBy = "updated_at", sortOrder = "desc" } =
58
85
  options;
@@ -81,6 +108,30 @@ function mapProjectFile<T extends ProjectFile>(file: T): ProjectFile {
81
108
  };
82
109
  }
83
110
 
111
+ function buildStyleArtifactParams(input: ResolveStyleArtifactInput): URLSearchParams {
112
+ const params = new URLSearchParams({
113
+ style_profile_hash: input.styleProfileHash,
114
+ });
115
+
116
+ if (input.branch) params.set("branch", input.branch);
117
+ if (input.environmentName) params.set("environment_name", input.environmentName);
118
+ if (input.releaseId) params.set("release_id", input.releaseId);
119
+
120
+ return params;
121
+ }
122
+
123
+ function mapStyleArtifactResolution(raw: unknown): ProjectStyleArtifactResolution {
124
+ const response = StyleArtifactResolveResponseSchema.parse(raw);
125
+ return {
126
+ status: response.status,
127
+ artifactHash: response.artifact_hash,
128
+ assetPath: response.asset_path,
129
+ etag: response.etag,
130
+ contentType: response.content_type,
131
+ updatedAt: response.updated_at,
132
+ };
133
+ }
134
+
84
135
  async function listAllFiles(
85
136
  list: (cursor?: string) => Promise<FileListResult>,
86
137
  ): Promise<ProjectFile[]> {
@@ -423,11 +474,67 @@ export class VeryfrontAPIOperations {
423
474
  );
424
475
  }
425
476
 
426
- private request(endpoint: string): Promise<unknown> {
477
+ async resolveStyleArtifact(
478
+ projectRef: string,
479
+ input: ResolveStyleArtifactInput,
480
+ ): Promise<ProjectStyleArtifactResolution> {
481
+ const params = buildStyleArtifactParams(input);
482
+ const url = `/projects/${encodeURIComponent(projectRef)}/style-artifacts/current?${params}`;
483
+ logger.debug("resolveStyleArtifact", {
484
+ projectRef,
485
+ branch: input.branch,
486
+ environmentName: input.environmentName,
487
+ releaseId: input.releaseId,
488
+ styleProfileHash: input.styleProfileHash,
489
+ });
490
+
491
+ return mapStyleArtifactResolution(await this.request(url));
492
+ }
493
+
494
+ async upsertStyleArtifact(
495
+ projectRef: string,
496
+ input: UpsertStyleArtifactInput,
497
+ ): Promise<ProjectStyleArtifactResolution> {
498
+ const url = `/projects/${encodeURIComponent(projectRef)}/style-artifacts/current`;
499
+ logger.debug("upsertStyleArtifact", {
500
+ projectRef,
501
+ branch: input.branch,
502
+ environmentName: input.environmentName,
503
+ releaseId: input.releaseId,
504
+ styleProfileHash: input.styleProfileHash,
505
+ artifactHash: input.artifactHash,
506
+ });
507
+
508
+ return mapStyleArtifactResolution(
509
+ await this.request(url, {
510
+ method: "PUT",
511
+ headers: {
512
+ "Content-Type": "application/json",
513
+ },
514
+ body: JSON.stringify({
515
+ style_profile_hash: input.styleProfileHash,
516
+ branch: input.branch,
517
+ environment_name: input.environmentName,
518
+ release_id: input.releaseId,
519
+ artifact_hash: input.artifactHash,
520
+ asset_path: input.assetPath,
521
+ content_type: input.contentType,
522
+ etag: input.etag,
523
+ }),
524
+ }),
525
+ );
526
+ }
527
+
528
+ private request(endpoint: string, options: RequestOptions = {}): Promise<unknown> {
427
529
  return withSpan(
428
530
  SpanNames.API_REQUEST,
429
531
  () =>
430
- requestWithRetry(`${this.apiBaseUrl}${endpoint}`, this.tokenProvider(), this.retryConfig),
532
+ requestWithRetry(
533
+ `${this.apiBaseUrl}${endpoint}`,
534
+ this.tokenProvider(),
535
+ this.retryConfig,
536
+ options,
537
+ ),
431
538
  { "api.endpoint": endpoint, "api.base_url": this.apiBaseUrl },
432
539
  );
433
540
  }
@@ -147,6 +147,15 @@ export const LookupDomainResponseSchema = z.object({
147
147
  release_id: z.string().uuid().nullable(),
148
148
  });
149
149
 
150
+ export const StyleArtifactResolveResponseSchema = z.object({
151
+ status: z.enum(["ready", "missing"]),
152
+ artifact_hash: z.string().optional(),
153
+ asset_path: z.string().optional(),
154
+ etag: z.string().optional(),
155
+ content_type: z.string().optional(),
156
+ updated_at: z.string().optional(),
157
+ });
158
+
150
159
  export type Project = z.infer<typeof ProjectSchema>;
151
160
  export type ProjectFile = z.infer<typeof ProjectFileSchema>;
152
161
  export type PageInfo = z.infer<typeof PageInfoSchema>;
@@ -165,6 +174,7 @@ export type ListReleaseFilesResponse = z.infer<typeof ListReleaseFilesResponseSc
165
174
  export type ReleaseFileDetail = z.infer<typeof ReleaseFileDetailSchema>;
166
175
 
167
176
  export type LookupDomainResponse = z.infer<typeof LookupDomainResponseSchema>;
177
+ export type StyleArtifactResolveResponse = z.infer<typeof StyleArtifactResolveResponseSchema>;
168
178
 
169
179
  export const API_ENDPOINTS = {
170
180
  listProjects: {
@@ -212,4 +222,10 @@ export const API_ENDPOINTS = {
212
222
  path: "/projects/{domain}",
213
223
  description: "Look up project by custom domain (resolved via project_reference)",
214
224
  },
225
+ resolveStyleArtifact: {
226
+ method: "GET" as const,
227
+ path: "/projects/{projectRef}/style-artifacts/current",
228
+ description:
229
+ "Resolve metadata for the latest ready style artifact for a branch, environment, or release selector",
230
+ },
215
231
  } as const;
@@ -35,4 +35,6 @@ export {
35
35
  ReleaseFileDetailSchema,
36
36
  type ReleaseFileListItem,
37
37
  ReleaseFileListItemSchema,
38
+ type StyleArtifactResolveResponse,
39
+ StyleArtifactResolveResponseSchema,
38
40
  } from "./api.schema.js";
@@ -19,4 +19,16 @@
19
19
  import "../../_dnt.polyfills.js";
20
20
 
21
21
 
22
- export { type ExecResult, type ExecStreamEvent, Sandbox, type SandboxOptions } from "./sandbox.js";
22
+ export {
23
+ type CommandJob,
24
+ type CommandJobHeartbeatStatus,
25
+ type CommandJobOutput,
26
+ type CommandJobStatus,
27
+ type ExecResult,
28
+ type ExecStreamEvent,
29
+ Sandbox,
30
+ type SandboxListOptions,
31
+ type SandboxListResult,
32
+ type SandboxOptions,
33
+ type SandboxSession,
34
+ } from "./sandbox.js";