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.
- package/esm/deno.js +1 -1
- package/esm/src/jobs/schemas.d.ts +30 -30
- package/esm/src/platform/adapters/veryfront-api-client/client.d.ts +3 -1
- package/esm/src/platform/adapters/veryfront-api-client/client.d.ts.map +1 -1
- package/esm/src/platform/adapters/veryfront-api-client/client.js +6 -0
- package/esm/src/platform/adapters/veryfront-api-client/index.d.ts +2 -2
- package/esm/src/platform/adapters/veryfront-api-client/index.d.ts.map +1 -1
- package/esm/src/platform/adapters/veryfront-api-client/index.js +1 -1
- package/esm/src/platform/adapters/veryfront-api-client/operations.d.ts +24 -0
- package/esm/src/platform/adapters/veryfront-api-client/operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/veryfront-api-client/operations.js +65 -3
- package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.d.ts +28 -0
- package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.d.ts.map +1 -1
- package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.js +13 -0
- package/esm/src/platform/adapters/veryfront-api-client/schemas/index.d.ts +1 -1
- package/esm/src/platform/adapters/veryfront-api-client/schemas/index.d.ts.map +1 -1
- package/esm/src/platform/adapters/veryfront-api-client/schemas/index.js +1 -1
- package/esm/src/sandbox/index.d.ts +1 -1
- package/esm/src/sandbox/index.d.ts.map +1 -1
- package/esm/src/sandbox/index.js +1 -1
- package/esm/src/sandbox/sandbox.d.ts +58 -0
- package/esm/src/sandbox/sandbox.d.ts.map +1 -1
- package/esm/src/sandbox/sandbox.js +111 -0
- package/esm/src/server/handlers/dev/styles-css.handler.d.ts +5 -0
- package/esm/src/server/handlers/dev/styles-css.handler.d.ts.map +1 -1
- package/esm/src/server/handlers/dev/styles-css.handler.js +121 -1
- package/package.json +1 -1
- package/src/deno.js +1 -1
- package/src/src/platform/adapters/veryfront-api-client/client.ts +17 -0
- package/src/src/platform/adapters/veryfront-api-client/index.ts +6 -0
- package/src/src/platform/adapters/veryfront-api-client/operations.ts +110 -3
- package/src/src/platform/adapters/veryfront-api-client/schemas/api.schema.ts +16 -0
- package/src/src/platform/adapters/veryfront-api-client/schemas/index.ts +2 -0
- package/src/src/sandbox/index.ts +13 -1
- package/src/src/sandbox/sandbox.ts +183 -0
- 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;
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/src/sandbox/sandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -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;
|
|
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
package/src/deno.js
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
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;
|
package/src/src/sandbox/index.ts
CHANGED
|
@@ -19,4 +19,16 @@
|
|
|
19
19
|
import "../../_dnt.polyfills.js";
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
export {
|
|
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";
|