veryfront 0.1.90 → 0.1.92
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/config/environment-config.js +1 -1
- package/esm/src/jobs/schemas.d.ts +44 -44
- package/esm/src/jobs/schemas.js +3 -3
- package/esm/src/observability/metrics/manager.js +2 -2
- package/esm/src/observability/tracing/otlp-setup.js +2 -2
- package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts +1 -0
- package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/adapter.js +11 -5
- 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/proxy/logger.d.ts.map +1 -1
- package/esm/src/proxy/logger.js +2 -6
- package/esm/src/proxy/tracing.d.ts.map +1 -1
- package/esm/src/proxy/tracing.js +2 -5
- package/esm/src/proxy/version.d.ts +2 -0
- package/esm/src/proxy/version.d.ts.map +1 -0
- package/esm/src/proxy/version.js +18 -0
- 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/esm/src/server/handlers/monitoring/health.handler.js +2 -2
- package/esm/src/utils/logger/logger.js +2 -2
- package/esm/src/utils/version.d.ts +9 -1
- package/esm/src/utils/version.d.ts.map +1 -1
- package/esm/src/utils/version.js +29 -2
- package/package.json +1 -1
- package/src/deno.js +1 -1
- package/src/src/config/environment-config.ts +1 -1
- package/src/src/jobs/schemas.ts +3 -3
- package/src/src/observability/metrics/manager.ts +2 -2
- package/src/src/observability/tracing/otlp-setup.ts +2 -2
- package/src/src/platform/adapters/fs/veryfront/adapter.ts +12 -5
- 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/proxy/logger.ts +2 -8
- package/src/src/proxy/tracing.ts +2 -6
- package/src/src/proxy/version.ts +21 -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
- package/src/src/server/handlers/monitoring/health.handler.ts +2 -2
- package/src/src/utils/logger/logger.ts +2 -2
- package/src/src/utils/version.ts +37 -2
|
@@ -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
|
}
|
|
@@ -2,7 +2,7 @@ import { BaseHandler } from "../response/base.js";
|
|
|
2
2
|
import { joinPath } from "../../../utils/path-utils.js";
|
|
3
3
|
import { HTTP_OK, HTTP_UNAVAILABLE, PRIORITY_HIGH } from "../../../utils/constants/index.js";
|
|
4
4
|
import { isTracingDegraded, isTracingEnabled } from "../../../observability/tracing/index.js";
|
|
5
|
-
import {
|
|
5
|
+
import { RUNTIME_VERSION } from "../../../utils/version.js";
|
|
6
6
|
let serverInitialized = false;
|
|
7
7
|
export function setServerInitialized(ready) {
|
|
8
8
|
serverInitialized = ready;
|
|
@@ -57,7 +57,7 @@ export class HealthHandler extends BaseHandler {
|
|
|
57
57
|
status: tracingDegraded ? "degraded" : "ok",
|
|
58
58
|
timestamp: new Date().toISOString(),
|
|
59
59
|
mode: hasStaticBuild ? "static+ssr" : "ssr",
|
|
60
|
-
version:
|
|
60
|
+
version: RUNTIME_VERSION,
|
|
61
61
|
tracing: {
|
|
62
62
|
enabled: isTracingEnabled(),
|
|
63
63
|
degraded: tracingDegraded,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as dntShim from "../../../_dnt.shims.js";
|
|
2
2
|
import { getEnv } from "../../platform/compat/process.js";
|
|
3
3
|
import { hasDenoRuntime, hasNodeProcess } from "../runtime-guards.js";
|
|
4
|
-
import {
|
|
4
|
+
import { RUNTIME_VERSION } from "../version.js";
|
|
5
5
|
import { ANSI, colorize, formatContextText, formatTimestamp, LEVEL_COLORS, LEVEL_GLYPHS, padTag, serializeError, } from "./core.js";
|
|
6
6
|
export var LogLevel;
|
|
7
7
|
(function (LogLevel) {
|
|
@@ -165,7 +165,7 @@ class ConsoleLogger {
|
|
|
165
165
|
timestamp: new Date().toISOString(),
|
|
166
166
|
level,
|
|
167
167
|
service: this.prefix.toLowerCase(),
|
|
168
|
-
veryfrontVersion:
|
|
168
|
+
veryfrontVersion: RUNTIME_VERSION,
|
|
169
169
|
message,
|
|
170
170
|
};
|
|
171
171
|
if (this.componentName)
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.92";
|
|
2
|
+
export declare function normalizeVeryfrontVersion(version: string | undefined): string | undefined;
|
|
3
|
+
export declare function resolveRuntimeVersion(options?: {
|
|
4
|
+
veryfrontVersion?: string;
|
|
5
|
+
releaseVersion?: string;
|
|
6
|
+
denoVersion?: string;
|
|
7
|
+
fallbackVersion?: string;
|
|
8
|
+
}): string;
|
|
9
|
+
export declare const RUNTIME_VERSION: string;
|
|
2
10
|
export declare const SERVER_START_TIME: number;
|
|
3
11
|
export interface BuildVersion {
|
|
4
12
|
framework: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/src/utils/version.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/src/utils/version.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,OAAO,WAAW,CAAC;AAEhC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGzF;AAUD,wBAAgB,qBAAqB,CAAC,OAAO,GAAE;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAKd;AAED,eAAO,MAAM,eAAe,QAK1B,CAAC;AAEH,eAAO,MAAM,iBAAiB,EAAE,MAAmB,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,kBAAkB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,YAAY,CAM1E"}
|
package/esm/src/utils/version.js
CHANGED
|
@@ -1,10 +1,37 @@
|
|
|
1
|
+
import denoConfig from "../../deno.js";
|
|
2
|
+
import { getEnv } from "../platform/compat/process.js";
|
|
1
3
|
// Keep in sync with deno.json version.
|
|
2
4
|
// scripts/release.ts updates this constant during releases.
|
|
3
|
-
export const VERSION = "0.1.
|
|
5
|
+
export const VERSION = "0.1.92";
|
|
6
|
+
export function normalizeVeryfrontVersion(version) {
|
|
7
|
+
if (!version)
|
|
8
|
+
return undefined;
|
|
9
|
+
return version.replace(/^v(?=\d)/, "");
|
|
10
|
+
}
|
|
11
|
+
function getVersionEnv(name) {
|
|
12
|
+
try {
|
|
13
|
+
return getEnv(name);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function resolveRuntimeVersion(options = {}) {
|
|
20
|
+
return normalizeVeryfrontVersion(options.veryfrontVersion ?? options.releaseVersion) ??
|
|
21
|
+
normalizeVeryfrontVersion(options.denoVersion) ??
|
|
22
|
+
options.fallbackVersion ??
|
|
23
|
+
VERSION;
|
|
24
|
+
}
|
|
25
|
+
export const RUNTIME_VERSION = resolveRuntimeVersion({
|
|
26
|
+
veryfrontVersion: getVersionEnv("VERYFRONT_VERSION"),
|
|
27
|
+
releaseVersion: getVersionEnv("RELEASE_VERSION"),
|
|
28
|
+
denoVersion: typeof denoConfig.version === "string" ? denoConfig.version : undefined,
|
|
29
|
+
fallbackVersion: VERSION,
|
|
30
|
+
});
|
|
4
31
|
export const SERVER_START_TIME = Date.now();
|
|
5
32
|
export function createBuildVersion(projectUpdatedAt) {
|
|
6
33
|
return {
|
|
7
|
-
framework:
|
|
34
|
+
framework: RUNTIME_VERSION,
|
|
8
35
|
serverStart: SERVER_START_TIME,
|
|
9
36
|
projectUpdated: projectUpdatedAt,
|
|
10
37
|
};
|
package/package.json
CHANGED
package/src/deno.js
CHANGED
|
@@ -188,7 +188,7 @@ function readEnvSnapshot(): EnvironmentConfig {
|
|
|
188
188
|
? parseNumber(v8MaxOldSpaceSizeRaw, 0) || undefined
|
|
189
189
|
: undefined,
|
|
190
190
|
|
|
191
|
-
veryfrontVersion: getEnv("VERYFRONT_VERSION") || undefined,
|
|
191
|
+
veryfrontVersion: getEnv("VERYFRONT_VERSION") || getEnv("RELEASE_VERSION") || undefined,
|
|
192
192
|
};
|
|
193
193
|
}
|
|
194
194
|
|
package/src/src/jobs/schemas.ts
CHANGED
|
@@ -115,7 +115,7 @@ const BaseJobSchema = z.object({
|
|
|
115
115
|
id: z.string().uuid(),
|
|
116
116
|
project_id: z.string().uuid(),
|
|
117
117
|
environment_id: z.string().uuid().nullable(),
|
|
118
|
-
branch_id: z.string().nullable().optional()
|
|
118
|
+
branch_id: z.string().nullable().optional(),
|
|
119
119
|
cron_job_id: z.string().uuid().nullable(),
|
|
120
120
|
batch_id: z.string().uuid().nullable(),
|
|
121
121
|
name: z.string(),
|
|
@@ -134,7 +134,7 @@ const BaseJobSchema = z.object({
|
|
|
134
134
|
});
|
|
135
135
|
|
|
136
136
|
export const JobSchema = BaseJobSchema.extend({
|
|
137
|
-
failed_reason: z.string().nullable().optional()
|
|
137
|
+
failed_reason: z.string().nullable().optional(),
|
|
138
138
|
kind: JobKindSchema.optional().default(null),
|
|
139
139
|
failure_detail: z.string().nullable().optional().default(null),
|
|
140
140
|
result_summary: JobResultSummarySchema.optional().default(null),
|
|
@@ -242,7 +242,7 @@ export const CronJobSchema = z.object({
|
|
|
242
242
|
id: z.string().uuid(),
|
|
243
243
|
project_id: z.string().uuid(),
|
|
244
244
|
environment_id: z.string().uuid().nullable(),
|
|
245
|
-
branch_id: z.string().nullable().optional()
|
|
245
|
+
branch_id: z.string().nullable().optional(),
|
|
246
246
|
name: z.string(),
|
|
247
247
|
status: CronJobStatusSchema,
|
|
248
248
|
target: z.string(),
|
|
@@ -10,7 +10,7 @@ import { loadConfig } from "./config.js";
|
|
|
10
10
|
import { initializeInstruments } from "../instruments/index.js";
|
|
11
11
|
import { MetricsRecorder } from "./recorder.js";
|
|
12
12
|
import type { MetricsConfig, MetricsInstruments, OpenTelemetryAPI, RuntimeState } from "./types.js";
|
|
13
|
-
import {
|
|
13
|
+
import { RUNTIME_VERSION } from "../../utils/version.js";
|
|
14
14
|
|
|
15
15
|
const logger = serverLogger.component("metrics");
|
|
16
16
|
|
|
@@ -80,7 +80,7 @@ export class MetricsManager {
|
|
|
80
80
|
|
|
81
81
|
try {
|
|
82
82
|
this.api = await import("@opentelemetry/api");
|
|
83
|
-
this.meter = this.api.metrics.getMeter(finalConfig.prefix,
|
|
83
|
+
this.meter = this.api.metrics.getMeter(finalConfig.prefix, RUNTIME_VERSION);
|
|
84
84
|
|
|
85
85
|
this.instruments = initializeInstruments(this.meter, finalConfig, this.runtimeState);
|
|
86
86
|
this.recorder.instruments = this.instruments;
|
|
@@ -13,7 +13,7 @@ import * as dntShim from "../../../_dnt.shims.js";
|
|
|
13
13
|
|
|
14
14
|
import { getOtelTracingConfig } from "../../config/env.js";
|
|
15
15
|
import { serverLogger } from "../../utils/index.js";
|
|
16
|
-
import {
|
|
16
|
+
import { RUNTIME_VERSION } from "../../utils/version.js";
|
|
17
17
|
|
|
18
18
|
const logger = serverLogger.component("otel");
|
|
19
19
|
|
|
@@ -118,7 +118,7 @@ export async function initializeOTLP(): Promise<void> {
|
|
|
118
118
|
|
|
119
119
|
const resource = new Resource({
|
|
120
120
|
[ATTR_SERVICE_NAME]: config.serviceName,
|
|
121
|
-
[ATTR_SERVICE_VERSION]:
|
|
121
|
+
[ATTR_SERVICE_VERSION]: RUNTIME_VERSION,
|
|
122
122
|
});
|
|
123
123
|
|
|
124
124
|
const endpointBase = config.endpoint.replace(/\/$/, "");
|
|
@@ -350,10 +350,10 @@ export class VeryfrontFSAdapter implements FSAdapter {
|
|
|
350
350
|
sourceFilesWithContent: fileSummary.sourceFilesWithContent,
|
|
351
351
|
});
|
|
352
352
|
|
|
353
|
-
// Trigger CSS pre-generation after the initial file snapshot is ready
|
|
354
|
-
//
|
|
355
|
-
//
|
|
356
|
-
if (fileSummary.sourceFilesWithContent > 0) {
|
|
353
|
+
// Trigger CSS pre-generation after the initial file snapshot is ready for
|
|
354
|
+
// published contexts. Branch previews should first try remote metadata
|
|
355
|
+
// recovery on cold starts instead of repopulating the prepared cache here.
|
|
356
|
+
if (fileSummary.sourceFilesWithContent > 0 && this.shouldBackgroundPregenerateStyles()) {
|
|
357
357
|
this.triggerCSSPregeneration(files).catch(() => {
|
|
358
358
|
// Error already logged in triggerCSSPregeneration
|
|
359
359
|
});
|
|
@@ -403,6 +403,13 @@ export class VeryfrontFSAdapter implements FSAdapter {
|
|
|
403
403
|
return isPrefixBeingInvalidated(prefix);
|
|
404
404
|
}
|
|
405
405
|
|
|
406
|
+
private shouldBackgroundPregenerateStyles(): boolean {
|
|
407
|
+
// Branch previews should recover the last registered stylesheet artifact on
|
|
408
|
+
// cold starts before rebuilding CSS locally. Live edit pokes still
|
|
409
|
+
// pregenerate through the WebSocket path after branch content changes.
|
|
410
|
+
return this.contentContext?.sourceType !== "branch";
|
|
411
|
+
}
|
|
412
|
+
|
|
406
413
|
private scheduleFileListWarmup(reason: string, cacheKey?: string): void {
|
|
407
414
|
if (!this.initialized || !this.contentContext) return;
|
|
408
415
|
|
|
@@ -446,7 +453,7 @@ export class VeryfrontFSAdapter implements FSAdapter {
|
|
|
446
453
|
await this.cache.setAsync(effectiveCacheKey, files);
|
|
447
454
|
const fileSummary = summarizeFileList(files);
|
|
448
455
|
|
|
449
|
-
if (fileSummary.sourceFilesWithContent > 0) {
|
|
456
|
+
if (fileSummary.sourceFilesWithContent > 0 && this.shouldBackgroundPregenerateStyles()) {
|
|
450
457
|
this.triggerCSSPregeneration(files).catch(() => {
|
|
451
458
|
// Error already logged in triggerCSSPregeneration
|
|
452
459
|
});
|
|
@@ -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/proxy/logger.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
// Import version from root deno.json (the source of truth)
|
|
2
1
|
import * as dntShim from "../../_dnt.shims.js";
|
|
3
|
-
|
|
4
|
-
import denoConfig from "../../deno.js";
|
|
5
2
|
import { getEnv } from "./env.js";
|
|
6
3
|
import { getTraceContext } from "./tracing.js";
|
|
7
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
|
+
import { PROXY_RUNTIME_VERSION } from "./version.js";
|
|
8
6
|
|
|
9
7
|
// NOTE: Formatting utilities are INLINED below instead of imported from ../utils/logger/core.ts
|
|
10
8
|
// because the proxy Docker build only copies src/proxy/ and has no access to src/utils/.
|
|
@@ -45,10 +43,6 @@ function getProxyRequestContext(): ProxyRequestContext | undefined {
|
|
|
45
43
|
return requestContextStore.getStore();
|
|
46
44
|
}
|
|
47
45
|
|
|
48
|
-
// Get version from environment variable or root deno.json
|
|
49
|
-
const VERYFRONT_VERSION: string = getEnv("VERYFRONT_VERSION") ??
|
|
50
|
-
(typeof denoConfig.version === "string" ? denoConfig.version : "0.0.0");
|
|
51
|
-
|
|
52
46
|
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
53
47
|
|
|
54
48
|
const LOG_LEVEL_ORDER: Record<LogLevel, number> = {
|
|
@@ -295,7 +289,7 @@ class ProxyLogger {
|
|
|
295
289
|
timestamp: new Date().toISOString(),
|
|
296
290
|
level,
|
|
297
291
|
service: "proxy",
|
|
298
|
-
veryfrontVersion:
|
|
292
|
+
veryfrontVersion: PROXY_RUNTIME_VERSION,
|
|
299
293
|
message,
|
|
300
294
|
...(traceCtx.traceId && { traceId: traceCtx.traceId, spanId: traceCtx.spanId }),
|
|
301
295
|
// Include request context fields at top level (like renderer logs)
|