veryfront 0.1.89 → 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 (87) hide show
  1. package/esm/cli/commands/knowledge/command.d.ts +3 -0
  2. package/esm/cli/commands/knowledge/command.d.ts.map +1 -1
  3. package/esm/cli/commands/knowledge/command.js +27 -2
  4. package/esm/deno.js +1 -1
  5. package/esm/src/html/styles-builder/candidate-extractor.d.ts +5 -1
  6. package/esm/src/html/styles-builder/candidate-extractor.d.ts.map +1 -1
  7. package/esm/src/html/styles-builder/candidate-extractor.js +6 -1
  8. package/esm/src/html/styles-builder/content-version.d.ts +9 -0
  9. package/esm/src/html/styles-builder/content-version.d.ts.map +1 -0
  10. package/esm/src/html/styles-builder/content-version.js +15 -0
  11. package/esm/src/html/styles-builder/css-pregeneration.d.ts +11 -0
  12. package/esm/src/html/styles-builder/css-pregeneration.d.ts.map +1 -1
  13. package/esm/src/html/styles-builder/css-pregeneration.js +15 -10
  14. package/esm/src/html/styles-builder/prepared-project-css-cache.d.ts +31 -0
  15. package/esm/src/html/styles-builder/prepared-project-css-cache.d.ts.map +1 -0
  16. package/esm/src/html/styles-builder/prepared-project-css-cache.js +165 -0
  17. package/esm/src/html/styles-builder/style-scope-profile.d.ts +14 -0
  18. package/esm/src/html/styles-builder/style-scope-profile.d.ts.map +1 -0
  19. package/esm/src/html/styles-builder/style-scope-profile.js +121 -0
  20. package/esm/src/jobs/schemas.d.ts +30 -30
  21. package/esm/src/platform/adapters/fs/factory.d.ts.map +1 -1
  22. package/esm/src/platform/adapters/fs/factory.js +2 -21
  23. package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts.map +1 -1
  24. package/esm/src/platform/adapters/fs/veryfront/adapter.js +44 -19
  25. package/esm/src/platform/adapters/fs/veryfront/default-invalidation-callbacks.d.ts +3 -0
  26. package/esm/src/platform/adapters/fs/veryfront/default-invalidation-callbacks.d.ts.map +1 -0
  27. package/esm/src/platform/adapters/fs/veryfront/default-invalidation-callbacks.js +25 -0
  28. package/esm/src/platform/adapters/fs/veryfront/proxy-manager.d.ts.map +1 -1
  29. package/esm/src/platform/adapters/fs/veryfront/proxy-manager.js +2 -15
  30. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts +4 -0
  31. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts.map +1 -1
  32. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.js +2 -0
  33. package/esm/src/platform/adapters/veryfront-api-client/client.d.ts +3 -1
  34. package/esm/src/platform/adapters/veryfront-api-client/client.d.ts.map +1 -1
  35. package/esm/src/platform/adapters/veryfront-api-client/client.js +6 -0
  36. package/esm/src/platform/adapters/veryfront-api-client/index.d.ts +2 -2
  37. package/esm/src/platform/adapters/veryfront-api-client/index.d.ts.map +1 -1
  38. package/esm/src/platform/adapters/veryfront-api-client/index.js +1 -1
  39. package/esm/src/platform/adapters/veryfront-api-client/operations.d.ts +24 -0
  40. package/esm/src/platform/adapters/veryfront-api-client/operations.d.ts.map +1 -1
  41. package/esm/src/platform/adapters/veryfront-api-client/operations.js +65 -3
  42. package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.d.ts +28 -0
  43. package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.d.ts.map +1 -1
  44. package/esm/src/platform/adapters/veryfront-api-client/schemas/api.schema.js +13 -0
  45. package/esm/src/platform/adapters/veryfront-api-client/schemas/index.d.ts +1 -1
  46. package/esm/src/platform/adapters/veryfront-api-client/schemas/index.d.ts.map +1 -1
  47. package/esm/src/platform/adapters/veryfront-api-client/schemas/index.js +1 -1
  48. package/esm/src/rendering/orchestrator/css-candidate-manifest.d.ts +3 -0
  49. package/esm/src/rendering/orchestrator/css-candidate-manifest.d.ts.map +1 -1
  50. package/esm/src/rendering/orchestrator/css-candidate-manifest.js +10 -5
  51. package/esm/src/rendering/orchestrator/html.d.ts.map +1 -1
  52. package/esm/src/rendering/orchestrator/html.js +8 -0
  53. package/esm/src/sandbox/index.d.ts +1 -1
  54. package/esm/src/sandbox/index.d.ts.map +1 -1
  55. package/esm/src/sandbox/index.js +1 -1
  56. package/esm/src/sandbox/sandbox.d.ts +58 -0
  57. package/esm/src/sandbox/sandbox.d.ts.map +1 -1
  58. package/esm/src/sandbox/sandbox.js +111 -0
  59. package/esm/src/server/handlers/dev/styles-candidate-scanner.d.ts.map +1 -1
  60. package/esm/src/server/handlers/dev/styles-candidate-scanner.js +14 -16
  61. package/esm/src/server/handlers/dev/styles-css.handler.d.ts +7 -0
  62. package/esm/src/server/handlers/dev/styles-css.handler.d.ts.map +1 -1
  63. package/esm/src/server/handlers/dev/styles-css.handler.js +175 -8
  64. package/package.json +1 -1
  65. package/src/cli/commands/knowledge/command.ts +30 -2
  66. package/src/deno.js +1 -1
  67. package/src/src/html/styles-builder/candidate-extractor.ts +13 -0
  68. package/src/src/html/styles-builder/content-version.ts +20 -0
  69. package/src/src/html/styles-builder/css-pregeneration.ts +49 -12
  70. package/src/src/html/styles-builder/prepared-project-css-cache.ts +228 -0
  71. package/src/src/html/styles-builder/style-scope-profile.ts +164 -0
  72. package/src/src/platform/adapters/fs/factory.ts +2 -27
  73. package/src/src/platform/adapters/fs/veryfront/adapter.ts +49 -20
  74. package/src/src/platform/adapters/fs/veryfront/default-invalidation-callbacks.ts +35 -0
  75. package/src/src/platform/adapters/fs/veryfront/proxy-manager.ts +4 -21
  76. package/src/src/platform/adapters/fs/veryfront/websocket-manager.ts +3 -0
  77. package/src/src/platform/adapters/veryfront-api-client/client.ts +17 -0
  78. package/src/src/platform/adapters/veryfront-api-client/index.ts +6 -0
  79. package/src/src/platform/adapters/veryfront-api-client/operations.ts +110 -3
  80. package/src/src/platform/adapters/veryfront-api-client/schemas/api.schema.ts +16 -0
  81. package/src/src/platform/adapters/veryfront-api-client/schemas/index.ts +2 -0
  82. package/src/src/rendering/orchestrator/css-candidate-manifest.ts +28 -6
  83. package/src/src/rendering/orchestrator/html.ts +11 -0
  84. package/src/src/sandbox/index.ts +13 -1
  85. package/src/src/sandbox/sandbox.ts +183 -0
  86. package/src/src/server/handlers/dev/styles-candidate-scanner.ts +18 -15
  87. package/src/src/server/handlers/dev/styles-css.handler.ts +262 -12
@@ -13,18 +13,31 @@ import { HTTP_OK, PRIORITY_HIGH_DEV } from "../../../utils/constants/index.js";
13
13
  import { joinPath } from "../../../utils/path-utils.js";
14
14
  import {
15
15
  formatCSSError,
16
- generateTailwindCSS,
16
+ getCSSByHashAsync,
17
17
  getProjectCSS,
18
+ regenerateCSSByHash,
18
19
  } from "../../../html/styles-builder/tailwind-compiler.js";
19
20
  import { DEFAULT_STYLESHEET } from "../../../html/styles-builder/css-hash-cache.js";
21
+ import { resolveStyleContentVersion } from "../../../html/styles-builder/content-version.js";
22
+ import {
23
+ createPreparedProjectCSSContext,
24
+ type PreparedProjectCSSRequestContext,
25
+ storePreparedProjectCSS,
26
+ tryGetPreparedProjectCSS,
27
+ } from "../../../html/styles-builder/prepared-project-css-cache.js";
28
+ import { createStyleScopeProfile } from "../../../html/styles-builder/style-scope-profile.js";
20
29
  import { serverLogger } from "../../../utils/index.js";
30
+ import type { ResolvedContentContext } from "../../../platform/adapters/fs/veryfront/types.js";
31
+ import type {
32
+ ResolveStyleArtifactInput,
33
+ VeryfrontApiClient,
34
+ } from "../../../platform/adapters/veryfront-api-client/index.js";
21
35
  import { extractProjectCandidates } from "./styles-candidate-scanner.js";
22
36
 
23
37
  const logger = serverLogger.component("styles-css-handler");
24
38
 
25
- type GeneratedStylesResult =
26
- | Awaited<ReturnType<typeof generateTailwindCSS>>
27
- | Awaited<ReturnType<typeof getProjectCSS>>;
39
+ type GeneratedStylesResult = Awaited<ReturnType<typeof getProjectCSS>>;
40
+ type StyleArtifactSelectorContext = Omit<ResolveStyleArtifactInput, "styleProfileHash">;
28
41
 
29
42
  export class StylesCSSHandler extends BaseHandler {
30
43
  metadata: HandlerMetadata = {
@@ -40,6 +53,9 @@ export class StylesCSSHandler extends BaseHandler {
40
53
  try {
41
54
  return await this.withProxyContext(ctx, async () => {
42
55
  const responseBuilder = this.createResponseBuilder(ctx).withCache("no-cache");
56
+ const projectScope = ctx.projectSlug ?? ctx.projectDir;
57
+ const styleProfile = createStyleScopeProfile(ctx.config);
58
+ const contentContext = this.getContentContext(ctx);
43
59
  let rawCss: string;
44
60
  try {
45
61
  rawCss = await this.loadStylesheet(ctx);
@@ -49,6 +65,48 @@ export class StylesCSSHandler extends BaseHandler {
49
65
  });
50
66
  rawCss = DEFAULT_STYLESHEET;
51
67
  }
68
+ const preparedContext = this.createPreparedCSSContext(
69
+ projectScope,
70
+ rawCss,
71
+ styleProfile.hash,
72
+ contentContext,
73
+ ctx,
74
+ );
75
+
76
+ if (preparedContext) {
77
+ const prepared = await tryGetPreparedProjectCSS(preparedContext);
78
+ if (prepared) {
79
+ logger.debug("Prepared CSS cache hit", {
80
+ projectScope,
81
+ projectVersion: preparedContext.projectVersion,
82
+ styleProfileHash: styleProfile.hash,
83
+ cssHash: prepared.hash,
84
+ });
85
+
86
+ return this.respond(
87
+ responseBuilder.withContentType("text/css; charset=utf-8", prepared.css, HTTP_OK),
88
+ );
89
+ }
90
+ }
91
+
92
+ const remotePrepared = await this.tryResolveRemotePreparedCSS(
93
+ ctx,
94
+ projectScope,
95
+ styleProfile.hash,
96
+ contentContext,
97
+ preparedContext,
98
+ );
99
+ if (remotePrepared) {
100
+ logger.debug("Prepared CSS resolved via style artifact metadata", {
101
+ projectScope,
102
+ styleProfileHash: styleProfile.hash,
103
+ cssHash: remotePrepared.hash,
104
+ });
105
+
106
+ return this.respond(
107
+ responseBuilder.withContentType("text/css; charset=utf-8", remotePrepared.css, HTTP_OK),
108
+ );
109
+ }
52
110
 
53
111
  let candidates: Set<string>;
54
112
  try {
@@ -59,10 +117,11 @@ export class StylesCSSHandler extends BaseHandler {
59
117
  });
60
118
  candidates = new Set<string>();
61
119
  }
62
- const result = await this.generateStylesheet(ctx, rawCss, candidates);
63
-
64
- if ("error" in result && result.error) {
65
- const formatted = formatCSSError(result.error);
120
+ let result: GeneratedStylesResult;
121
+ try {
122
+ result = await this.generateStylesheet(ctx, rawCss, candidates);
123
+ } catch (error) {
124
+ const formatted = formatCSSError(error instanceof Error ? error : String(error));
66
125
  logger.error("Tailwind error", {
67
126
  error: formatted.message,
68
127
  suggestion: formatted.suggestion,
@@ -105,12 +164,29 @@ body::before {
105
164
  }
106
165
 
107
166
  logger.debug("CSS generated", {
167
+ projectScope,
108
168
  candidates: candidates.size,
109
169
  cssLength: result.css.length,
110
170
  fromCache: "fromCache" in result ? result.fromCache : false,
111
171
  cssHash: "hash" in result ? result.hash : undefined,
112
172
  });
113
173
 
174
+ if (preparedContext && "hash" in result) {
175
+ await storePreparedProjectCSS(preparedContext, {
176
+ css: result.css,
177
+ hash: result.hash,
178
+ });
179
+ }
180
+
181
+ if ("hash" in result) {
182
+ await this.registerPreparedCSSArtifact(
183
+ ctx,
184
+ styleProfile.hash,
185
+ contentContext,
186
+ result.hash,
187
+ );
188
+ }
189
+
114
190
  return this.respond(
115
191
  responseBuilder.withContentType("text/css; charset=utf-8", result.css, HTTP_OK),
116
192
  );
@@ -155,14 +231,188 @@ body::before {
155
231
  rawCss: string,
156
232
  candidates: Set<string>,
157
233
  ): Promise<GeneratedStylesResult> {
158
- if (!ctx.projectSlug) {
159
- return generateTailwindCSS(rawCss, candidates);
160
- }
234
+ const projectScope = ctx.projectSlug ?? ctx.projectDir;
161
235
 
162
- return getProjectCSS(ctx.projectSlug, rawCss, candidates, {
236
+ return getProjectCSS(projectScope, rawCss, candidates, {
163
237
  minify: true,
164
238
  environment: "preview",
165
239
  buildMode: "production",
166
240
  });
167
241
  }
242
+
243
+ private getContentContext(ctx: HandlerContext): ResolvedContentContext | null {
244
+ const wrappedFs = ctx.adapter.fs as { getUnderlyingAdapter?: () => unknown };
245
+ if (typeof wrappedFs.getUnderlyingAdapter !== "function") return null;
246
+
247
+ const fsAdapter = wrappedFs.getUnderlyingAdapter() as {
248
+ getContentContext?: () => ResolvedContentContext | null;
249
+ };
250
+
251
+ return typeof fsAdapter.getContentContext === "function" ? fsAdapter.getContentContext() : null;
252
+ }
253
+
254
+ private getVeryfrontApiClient(ctx: HandlerContext): VeryfrontApiClient | null {
255
+ const wrappedFs = ctx.adapter.fs as { getUnderlyingAdapter?: () => unknown };
256
+ if (typeof wrappedFs.getUnderlyingAdapter !== "function") return null;
257
+
258
+ const fsAdapter = wrappedFs.getUnderlyingAdapter() as {
259
+ getClient?: () => VeryfrontApiClient;
260
+ };
261
+
262
+ return typeof fsAdapter.getClient === "function" ? fsAdapter.getClient() : null;
263
+ }
264
+
265
+ private createPreparedCSSContext(
266
+ projectScope: string | undefined,
267
+ rawCss: string,
268
+ styleProfileHash: string,
269
+ contentContext: ResolvedContentContext | null,
270
+ ctx: HandlerContext,
271
+ ) {
272
+ if (!projectScope) return undefined;
273
+
274
+ return createPreparedProjectCSSContext(
275
+ projectScope,
276
+ resolveStyleContentVersion(contentContext, {
277
+ releaseId: ctx.releaseId,
278
+ branch: ctx.parsedDomain?.branch,
279
+ environmentName: ctx.environmentName,
280
+ }),
281
+ rawCss,
282
+ styleProfileHash,
283
+ {
284
+ minify: true,
285
+ environment: "preview",
286
+ buildMode: "production",
287
+ },
288
+ );
289
+ }
290
+
291
+ private resolveStyleArtifactSelector(
292
+ contentContext: ResolvedContentContext | null,
293
+ ctx: HandlerContext,
294
+ ): StyleArtifactSelectorContext | null {
295
+ if (contentContext?.sourceType === "branch" && contentContext.branch) {
296
+ return {
297
+ branch: contentContext.branch,
298
+ };
299
+ }
300
+
301
+ if (contentContext?.sourceType === "environment" && contentContext.environmentName) {
302
+ return {
303
+ environmentName: contentContext.environmentName,
304
+ };
305
+ }
306
+
307
+ if (contentContext?.sourceType === "release" && contentContext.releaseId) {
308
+ return {
309
+ releaseId: contentContext.releaseId,
310
+ };
311
+ }
312
+
313
+ if (ctx.parsedDomain?.branch) {
314
+ return {
315
+ branch: ctx.parsedDomain.branch,
316
+ };
317
+ }
318
+
319
+ if (ctx.environmentName) {
320
+ return {
321
+ environmentName: ctx.environmentName,
322
+ };
323
+ }
324
+
325
+ if (ctx.releaseId) {
326
+ return {
327
+ releaseId: ctx.releaseId,
328
+ };
329
+ }
330
+
331
+ return null;
332
+ }
333
+
334
+ private async tryResolveRemotePreparedCSS(
335
+ ctx: HandlerContext,
336
+ projectScope: string | undefined,
337
+ styleProfileHash: string,
338
+ contentContext: ResolvedContentContext | null,
339
+ preparedContext?: PreparedProjectCSSRequestContext,
340
+ ): Promise<{ css: string; hash: string } | undefined> {
341
+ if (!projectScope) return undefined;
342
+
343
+ const selector = this.resolveStyleArtifactSelector(contentContext, ctx);
344
+ if (!selector) return undefined;
345
+
346
+ const client = this.getVeryfrontApiClient(ctx);
347
+ if (!client) return undefined;
348
+
349
+ try {
350
+ const resolved = await client.resolveStyleArtifact({
351
+ ...selector,
352
+ styleProfileHash,
353
+ });
354
+
355
+ if (resolved.status !== "ready" || !resolved.artifactHash) {
356
+ return undefined;
357
+ }
358
+
359
+ const css = await this.getPreparedCSSByHash(resolved.artifactHash, projectScope);
360
+ if (!css) return undefined;
361
+
362
+ if (preparedContext) {
363
+ await storePreparedProjectCSS(preparedContext, {
364
+ css,
365
+ hash: resolved.artifactHash,
366
+ });
367
+ }
368
+
369
+ return {
370
+ css,
371
+ hash: resolved.artifactHash,
372
+ };
373
+ } catch (error) {
374
+ logger.debug("Failed to resolve prepared CSS via style artifact metadata", {
375
+ projectScope,
376
+ styleProfileHash,
377
+ error: error instanceof Error ? error.message : String(error),
378
+ });
379
+ return undefined;
380
+ }
381
+ }
382
+
383
+ private async getPreparedCSSByHash(
384
+ cssHash: string,
385
+ projectScope: string,
386
+ ): Promise<string | undefined> {
387
+ const cached = await getCSSByHashAsync(cssHash);
388
+ if (cached) return cached;
389
+ return regenerateCSSByHash(cssHash, projectScope);
390
+ }
391
+
392
+ private async registerPreparedCSSArtifact(
393
+ ctx: HandlerContext,
394
+ styleProfileHash: string,
395
+ contentContext: ResolvedContentContext | null,
396
+ cssHash: string,
397
+ ): Promise<void> {
398
+ const selector = this.resolveStyleArtifactSelector(contentContext, ctx);
399
+ if (!selector) return;
400
+
401
+ const client = this.getVeryfrontApiClient(ctx);
402
+ if (!client) return;
403
+
404
+ try {
405
+ await client.upsertStyleArtifact({
406
+ ...selector,
407
+ styleProfileHash,
408
+ artifactHash: cssHash,
409
+ });
410
+ } catch (error) {
411
+ logger.debug("Failed to register prepared CSS artifact", {
412
+ cssHash,
413
+ styleProfileHash,
414
+ error: error instanceof Error ? error.message : String(error),
415
+ });
416
+ }
417
+ }
168
418
  }