veryfront 0.1.283 → 0.1.285
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.d.ts +0 -8
- package/esm/deno.js +8 -11
- package/esm/src/agent/agent-service.d.ts +28 -6
- package/esm/src/agent/agent-service.d.ts.map +1 -1
- package/esm/src/agent/agent-service.js +23 -1
- package/esm/src/agent/index.d.ts +1 -1
- package/esm/src/agent/index.d.ts.map +1 -1
- package/esm/src/embedding/resolve.d.ts.map +1 -1
- package/esm/src/embedding/resolve.js +15 -2
- package/esm/src/embedding/veryfront-cloud/provider.d.ts.map +1 -1
- package/esm/src/embedding/veryfront-cloud/provider.js +2 -7
- package/esm/src/extensions/contracts.js +3 -1
- package/esm/src/extensions/interfaces/ai-provider.d.ts +50 -0
- package/esm/src/extensions/interfaces/ai-provider.d.ts.map +1 -0
- package/esm/src/extensions/interfaces/ai-provider.js +13 -0
- package/esm/src/extensions/interfaces/code-parser.d.ts +11 -0
- package/esm/src/extensions/interfaces/code-parser.d.ts.map +1 -1
- package/esm/src/extensions/interfaces/css-processor.d.ts +41 -22
- package/esm/src/extensions/interfaces/css-processor.d.ts.map +1 -1
- package/esm/src/extensions/interfaces/css-processor.js +10 -1
- package/esm/src/extensions/interfaces/index.d.ts +5 -4
- package/esm/src/extensions/interfaces/index.d.ts.map +1 -1
- package/esm/src/extensions/interfaces/index.js +1 -0
- package/esm/src/extensions/interfaces/schema-validator.d.ts +84 -5
- package/esm/src/extensions/interfaces/schema-validator.d.ts.map +1 -1
- package/esm/src/extensions/interfaces/schema-validator.js +5 -0
- package/esm/src/extensions/loader.d.ts +7 -0
- package/esm/src/extensions/loader.d.ts.map +1 -1
- package/esm/src/extensions/loader.js +12 -0
- package/esm/src/extensions/orchestrate.d.ts +2 -0
- package/esm/src/extensions/orchestrate.d.ts.map +1 -1
- package/esm/src/extensions/orchestrate.js +3 -0
- package/esm/src/extensions/recommendations.d.ts.map +1 -1
- package/esm/src/extensions/recommendations.js +4 -1
- package/esm/src/extensions/registries/ai-provider-registry.d.ts +11 -0
- package/esm/src/extensions/registries/ai-provider-registry.d.ts.map +1 -0
- package/esm/src/extensions/registries/ai-provider-registry.js +40 -0
- package/esm/src/html/styles-builder/plugin-loader.d.ts.map +1 -1
- package/esm/src/html/styles-builder/plugin-loader.js +4 -16
- package/esm/src/html/styles-builder/tailwind-compiler-cache.d.ts +8 -2
- package/esm/src/html/styles-builder/tailwind-compiler-cache.d.ts.map +1 -1
- package/esm/src/html/styles-builder/tailwind-compiler-cache.js +20 -3
- package/esm/src/provider/model-registry.d.ts.map +1 -1
- package/esm/src/provider/model-registry.js +33 -6
- package/esm/src/provider/runtime-loader/provider-embedding-responses.d.ts +1 -0
- package/esm/src/provider/runtime-loader/provider-embedding-responses.d.ts.map +1 -1
- package/esm/src/provider/runtime-loader/provider-embedding-responses.js +1 -1
- package/esm/src/provider/runtime-loader/provider-http.d.ts +9 -0
- package/esm/src/provider/runtime-loader/provider-http.d.ts.map +1 -1
- package/esm/src/provider/runtime-loader/provider-http.js +2 -2
- package/esm/src/provider/runtime-loader.d.ts +120 -9
- package/esm/src/provider/runtime-loader.d.ts.map +1 -1
- package/esm/src/provider/runtime-loader.js +13 -943
- package/esm/src/provider/veryfront-cloud/provider.d.ts.map +1 -1
- package/esm/src/provider/veryfront-cloud/provider.js +30 -15
- 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/lazy-sandbox.d.ts +3 -0
- package/esm/src/sandbox/lazy-sandbox.d.ts.map +1 -1
- package/esm/src/sandbox/lazy-sandbox.js +22 -1
- package/esm/src/schemas/define.d.ts +31 -0
- package/esm/src/schemas/define.d.ts.map +1 -0
- package/esm/src/schemas/define.js +42 -0
- package/esm/src/schemas/index.d.ts +7 -2
- package/esm/src/schemas/index.d.ts.map +1 -1
- package/esm/src/schemas/index.js +10 -2
- package/esm/src/schemas/zod-adapter.d.ts +25 -0
- package/esm/src/schemas/zod-adapter.d.ts.map +1 -0
- package/esm/src/schemas/zod-adapter.js +120 -0
- package/esm/src/server/bootstrap.d.ts.map +1 -1
- package/esm/src/server/bootstrap.js +5 -0
- package/esm/src/transforms/plugins/babel-node-positions.d.ts +6 -7
- package/esm/src/transforms/plugins/babel-node-positions.d.ts.map +1 -1
- package/esm/src/transforms/plugins/babel-node-positions.js +10 -123
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -6
- package/src/deno.js +8 -11
- package/src/src/agent/agent-service.ts +91 -7
- package/src/src/agent/index.ts +4 -0
- package/src/src/embedding/resolve.ts +18 -7
- package/src/src/embedding/veryfront-cloud/provider.ts +4 -10
- package/src/src/extensions/contracts.ts +3 -3
- package/src/src/extensions/interfaces/ai-provider.ts +54 -0
- package/src/src/extensions/interfaces/code-parser.ts +12 -0
- package/src/src/extensions/interfaces/css-processor.ts +43 -22
- package/src/src/extensions/interfaces/index.ts +15 -11
- package/src/src/extensions/interfaces/schema-validator.ts +112 -5
- package/src/src/extensions/loader.ts +14 -0
- package/src/src/extensions/orchestrate.ts +5 -0
- package/src/src/extensions/recommendations.ts +4 -1
- package/src/src/extensions/registries/ai-provider-registry.ts +53 -0
- package/src/src/html/styles-builder/plugin-loader.ts +4 -16
- package/src/src/html/styles-builder/tailwind-compiler-cache.ts +27 -6
- package/src/src/provider/model-registry.ts +34 -15
- package/src/src/provider/runtime-loader/provider-embedding-responses.ts +1 -1
- package/src/src/provider/runtime-loader/provider-http.ts +2 -2
- package/src/src/provider/runtime-loader.ts +41 -1189
- package/src/src/provider/veryfront-cloud/provider.ts +35 -19
- package/src/src/sandbox/index.ts +5 -1
- package/src/src/sandbox/lazy-sandbox.ts +25 -1
- package/src/src/schemas/define.ts +48 -0
- package/src/src/schemas/index.ts +13 -2
- package/src/src/schemas/zod-adapter.ts +180 -0
- package/src/src/server/bootstrap.ts +5 -0
- package/src/src/transforms/plugins/babel-node-positions.ts +11 -173
- package/src/src/utils/version-constant.ts +1 -1
- package/esm/src/extensions/interfaces/ai-model-provider.d.ts +0 -94
- package/esm/src/extensions/interfaces/ai-model-provider.d.ts.map +0 -1
- package/esm/src/extensions/interfaces/ai-model-provider.js +0 -8
- package/src/src/extensions/interfaces/ai-model-provider.ts +0 -100
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { createError, toError } from "../../errors/veryfront-error.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "../runtime-loader.js";
|
|
2
|
+
import { createGoogleModelRuntime } from "../runtime-loader.js";
|
|
3
|
+
import { tryResolve } from "../../extensions/contracts.js";
|
|
4
|
+
import type { AIProviderRegistry } from "../../extensions/interfaces/index.js";
|
|
5
|
+
import { AIProviderRegistryName } from "../../extensions/interfaces/index.js";
|
|
7
6
|
import type { ModelRuntime } from "../types.js";
|
|
8
7
|
import {
|
|
9
8
|
createVeryfrontCloudFetch,
|
|
@@ -19,13 +18,22 @@ export function createVeryfrontCloudModel(modelId: string): ModelRuntime {
|
|
|
19
18
|
const fetch = createVeryfrontCloudFetch(apiToken, projectSlug);
|
|
20
19
|
|
|
21
20
|
switch (provider) {
|
|
22
|
-
case "anthropic":
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
case "anthropic": {
|
|
22
|
+
const registry = tryResolve<AIProviderRegistry>(AIProviderRegistryName);
|
|
23
|
+
const anthropic = registry?.get("anthropic");
|
|
24
|
+
if (anthropic) {
|
|
25
|
+
return anthropic.createModel(upstreamModelId, {
|
|
26
|
+
credential: apiToken,
|
|
27
|
+
authToken: apiToken,
|
|
28
|
+
baseURL,
|
|
29
|
+
name: "veryfront-cloud",
|
|
30
|
+
fetch,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
throw new Error(
|
|
34
|
+
"Anthropic provider not installed. Add @veryfront/ext-anthropic to use anthropic/* models via veryfront-cloud.",
|
|
35
|
+
);
|
|
36
|
+
}
|
|
29
37
|
|
|
30
38
|
case "google":
|
|
31
39
|
return createGoogleModelRuntime({
|
|
@@ -36,13 +44,21 @@ export function createVeryfrontCloudModel(modelId: string): ModelRuntime {
|
|
|
36
44
|
}, upstreamModelId);
|
|
37
45
|
|
|
38
46
|
case "openai":
|
|
39
|
-
case "moonshotai":
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
case "moonshotai": {
|
|
48
|
+
const registry = tryResolve<AIProviderRegistry>(AIProviderRegistryName);
|
|
49
|
+
const openai = registry?.get("openai");
|
|
50
|
+
if (openai) {
|
|
51
|
+
return openai.createModel(upstreamModelId, {
|
|
52
|
+
credential: apiToken,
|
|
53
|
+
baseURL,
|
|
54
|
+
name: "veryfront-cloud",
|
|
55
|
+
fetch,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
throw new Error(
|
|
59
|
+
"OpenAI provider not installed. Add @veryfront/ext-openai to use openai/moonshotai models via veryfront-cloud.",
|
|
60
|
+
);
|
|
61
|
+
}
|
|
46
62
|
|
|
47
63
|
default: {
|
|
48
64
|
const _exhaustive: never = provider;
|
package/src/src/sandbox/index.ts
CHANGED
|
@@ -34,4 +34,8 @@ export {
|
|
|
34
34
|
type SandboxOptions,
|
|
35
35
|
type SandboxSession,
|
|
36
36
|
} from "./sandbox.js";
|
|
37
|
-
export {
|
|
37
|
+
export {
|
|
38
|
+
LazySandbox,
|
|
39
|
+
type LazySandboxOptions,
|
|
40
|
+
resolveDefaultSandboxRuntimeEndpoint,
|
|
41
|
+
} from "./lazy-sandbox.js";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as dntShim from "../../_dnt.shims.js";
|
|
2
2
|
import { REQUEST_ERROR } from "../errors/index.js";
|
|
3
|
+
import { getHostEnv } from "../platform/compat/process.js";
|
|
3
4
|
import {
|
|
4
5
|
type CommandJob,
|
|
5
6
|
type CommandJobOutput,
|
|
@@ -45,6 +46,28 @@ const REPROVISIONABLE_EXEC_START_ERROR_CODES = new Set([
|
|
|
45
46
|
"ENOTFOUND",
|
|
46
47
|
"EHOSTUNREACH",
|
|
47
48
|
]);
|
|
49
|
+
const VERYFRONT_SANDBOX_PUBLIC_HOST_PATTERN = /^([a-z0-9-]+)\.sandbox\.veryfront\.[a-z0-9.-]+$/i;
|
|
50
|
+
|
|
51
|
+
export function resolveDefaultSandboxRuntimeEndpoint(input: { endpoint: string }): string {
|
|
52
|
+
if (!getHostEnv("KUBERNETES_SERVICE_HOST")) {
|
|
53
|
+
return input.endpoint;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let hostname: string;
|
|
57
|
+
try {
|
|
58
|
+
hostname = new URL(input.endpoint).hostname;
|
|
59
|
+
} catch {
|
|
60
|
+
return input.endpoint;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const match = hostname.match(VERYFRONT_SANDBOX_PUBLIC_HOST_PATTERN);
|
|
64
|
+
const shortId = match?.[1];
|
|
65
|
+
if (!shortId) {
|
|
66
|
+
return input.endpoint;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return `http://sandbox.veryfront-sandbox-${shortId}.svc.cluster.local`;
|
|
70
|
+
}
|
|
48
71
|
|
|
49
72
|
/** Lazily provisions sandbox sessions and keeps them alive while in use. */
|
|
50
73
|
export class LazySandbox {
|
|
@@ -625,7 +648,8 @@ export class LazySandbox {
|
|
|
625
648
|
private resolveRuntimeEndpoint(): string {
|
|
626
649
|
const endpoint = this.requireEndpoint();
|
|
627
650
|
const sessionId = this.requireSessionId();
|
|
628
|
-
return this.resolveRuntimeEndpointOption?.({ endpoint, sessionId }) ??
|
|
651
|
+
return this.resolveRuntimeEndpointOption?.({ endpoint, sessionId }) ??
|
|
652
|
+
resolveDefaultSandboxRuntimeEndpoint({ endpoint });
|
|
629
653
|
}
|
|
630
654
|
|
|
631
655
|
private requireSessionId(): string {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy schema factory.
|
|
3
|
+
*
|
|
4
|
+
* `defineSchema(factory)` returns a memoized getter that resolves the
|
|
5
|
+
* `SchemaValidator` extension contract on first call and materializes the
|
|
6
|
+
* schema via the provided factory. This indirection lets core modules declare
|
|
7
|
+
* schemas without importing zod directly — a real validator (typically
|
|
8
|
+
* `@veryfront/ext-zod`) must be registered in the contract registry before
|
|
9
|
+
* the schema is first accessed.
|
|
10
|
+
*
|
|
11
|
+
* @module schemas/define
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { tryResolve } from "../extensions/contracts.js";
|
|
15
|
+
import type {
|
|
16
|
+
Schema,
|
|
17
|
+
SchemaFactory,
|
|
18
|
+
SchemaValidator,
|
|
19
|
+
} from "../extensions/interfaces/index.js";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Wrap a schema factory so that it is built lazily on first call.
|
|
23
|
+
*
|
|
24
|
+
* @param factory - Receives a `SchemaValidator` and returns a `Schema<T>`.
|
|
25
|
+
* @returns A zero-arg getter that caches and returns the built schema.
|
|
26
|
+
* @throws Error when no `SchemaValidator` contract is registered.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* const getUserSchema = defineSchema((v) =>
|
|
31
|
+
* v.object({ id: v.string().uuid(), name: v.string().min(1) })
|
|
32
|
+
* );
|
|
33
|
+
*
|
|
34
|
+
* const user = getUserSchema().parse(input);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function defineSchema<T>(factory: SchemaFactory<T>): () => Schema<T> {
|
|
38
|
+
let cached: Schema<T> | undefined;
|
|
39
|
+
return () => {
|
|
40
|
+
if (cached) return cached;
|
|
41
|
+
const v = tryResolve<SchemaValidator>("SchemaValidator");
|
|
42
|
+
if (!v) {
|
|
43
|
+
throw new Error("SchemaValidator contract unresolved — install ext-zod");
|
|
44
|
+
}
|
|
45
|
+
cached = factory(v);
|
|
46
|
+
return cached;
|
|
47
|
+
};
|
|
48
|
+
}
|
package/src/src/schemas/index.ts
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Reusable
|
|
3
|
-
* pagination) and primitives (file paths, hex colors, semver, timestamps)
|
|
2
|
+
* Reusable validation schemas — common types (email, slug, URL, UUID,
|
|
3
|
+
* pagination) and primitives (file paths, hex colors, semver, timestamps),
|
|
4
|
+
* plus the `defineSchema` lazy-factory helper.
|
|
5
|
+
*
|
|
6
|
+
* Importing this module also registers the default zod-backed
|
|
7
|
+
* `SchemaValidator` adapter so that `defineSchema(...)` works out of the box.
|
|
4
8
|
*
|
|
5
9
|
* @module schemas
|
|
6
10
|
*/
|
|
7
11
|
|
|
12
|
+
import { registerZodAdapter } from "./zod-adapter.js";
|
|
13
|
+
|
|
14
|
+
// Register the default SchemaValidator implementation once at module load.
|
|
15
|
+
registerZodAdapter();
|
|
16
|
+
|
|
17
|
+
export { defineSchema } from "./define.js";
|
|
18
|
+
|
|
8
19
|
export {
|
|
9
20
|
CommonSchemas,
|
|
10
21
|
type DateRange,
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod-backed `SchemaValidator` adapter.
|
|
3
|
+
*
|
|
4
|
+
* This is the default (core-provided) implementation of the
|
|
5
|
+
* `SchemaValidator` contract. It thinly wraps zod so that core modules can
|
|
6
|
+
* declare schemas through the extension-neutral DSL while still getting zod's
|
|
7
|
+
* runtime behavior.
|
|
8
|
+
*
|
|
9
|
+
* The entire zod surface used by the contract is confined to this file; when
|
|
10
|
+
* `@veryfront/ext-zod` takes over in Phase B this file will be deleted and
|
|
11
|
+
* the `"zod"` import map entry removed.
|
|
12
|
+
*
|
|
13
|
+
* @module schemas/zod-adapter
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
import { register } from "../extensions/contracts.js";
|
|
18
|
+
import type {
|
|
19
|
+
InferShape,
|
|
20
|
+
Schema,
|
|
21
|
+
SchemaValidator,
|
|
22
|
+
SchemaValidatorCoerce,
|
|
23
|
+
ValidationIssue,
|
|
24
|
+
ValidationResult,
|
|
25
|
+
} from "../extensions/interfaces/index.js";
|
|
26
|
+
|
|
27
|
+
// deno-lint-ignore no-explicit-any -- zod's chainable APIs return parametric types
|
|
28
|
+
type AnyZodSchema = z.ZodType<any, any, any>;
|
|
29
|
+
|
|
30
|
+
/** Unwrap our opaque Schema<T> back to the underlying zod schema. */
|
|
31
|
+
function toZod<T>(schema: Schema<T>): AnyZodSchema {
|
|
32
|
+
return (schema as unknown as { __zod: AnyZodSchema }).__zod;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Wrap a zod schema as an opaque Schema<T> with chainables routed through zod. */
|
|
36
|
+
function wrap<T>(zs: AnyZodSchema): Schema<T> {
|
|
37
|
+
// The wrapper fakes the full Schema<T> surface; unsupported chainables on
|
|
38
|
+
// unsuitable kinds (e.g. calling `.email()` on a number) throw at runtime
|
|
39
|
+
// just like zod would.
|
|
40
|
+
// deno-lint-ignore no-explicit-any -- safe within this adapter
|
|
41
|
+
const anyZs = zs as any;
|
|
42
|
+
const s: Schema<T> = {
|
|
43
|
+
_output: undefined as unknown as T,
|
|
44
|
+
optional: () => wrap<T | undefined>(zs.optional()),
|
|
45
|
+
nullable: () => wrap<T | null>(zs.nullable()),
|
|
46
|
+
nullish: () => wrap<T | null | undefined>(zs.nullish()),
|
|
47
|
+
default: (value: T | (() => T)) => wrap<T>(anyZs.default(value)),
|
|
48
|
+
describe: (description: string) => wrap<T>(zs.describe(description)),
|
|
49
|
+
refine: (
|
|
50
|
+
check: (value: T) => boolean,
|
|
51
|
+
message?: string | { message?: string },
|
|
52
|
+
) => wrap<T>(zs.refine(check as (v: unknown) => boolean, message as never)),
|
|
53
|
+
transform: <U>(fn: (value: T) => U) => wrap<U>(zs.transform(fn as never)),
|
|
54
|
+
strict: () => wrap<T>(anyZs.strict()),
|
|
55
|
+
passthrough: () => wrap<T>(anyZs.passthrough()),
|
|
56
|
+
partial: () => wrap<Partial<T>>(anyZs.partial()),
|
|
57
|
+
extend: <U extends Record<string, Schema<unknown>>>(shape: U) => {
|
|
58
|
+
const zodShape = toZodShape(shape);
|
|
59
|
+
return wrap<T & { [K in keyof U]: U[K] extends Schema<infer V> ? V : never }>(
|
|
60
|
+
anyZs.extend(zodShape),
|
|
61
|
+
);
|
|
62
|
+
},
|
|
63
|
+
merge: <U>(other: Schema<U>) => wrap<T & U>(anyZs.merge(toZod(other))),
|
|
64
|
+
min: (value: number, message?: string) => wrap<T>(anyZs.min(value, message)),
|
|
65
|
+
max: (value: number, message?: string) => wrap<T>(anyZs.max(value, message)),
|
|
66
|
+
int: (message?: string) => wrap<T>(anyZs.int(message)),
|
|
67
|
+
positive: (message?: string) => wrap<T>(anyZs.positive(message)),
|
|
68
|
+
nonnegative: (message?: string) => wrap<T>(anyZs.nonnegative(message)),
|
|
69
|
+
regex: (pattern: RegExp, message?: string) => wrap<T>(anyZs.regex(pattern, message)),
|
|
70
|
+
email: (message?: string) => wrap<T>(anyZs.email(message)),
|
|
71
|
+
url: (message?: string) => wrap<T>(anyZs.url(message)),
|
|
72
|
+
uuid: (message?: string) => wrap<T>(anyZs.uuid(message)),
|
|
73
|
+
datetime: (message?: string) => wrap<T>(anyZs.datetime(message)),
|
|
74
|
+
parse: (data: unknown): T => zs.parse(data) as T,
|
|
75
|
+
safeParse: (data: unknown): ValidationResult<T> => {
|
|
76
|
+
const res = zs.safeParse(data);
|
|
77
|
+
if (res.success) return { success: true, data: res.data as T };
|
|
78
|
+
const issues: ValidationIssue[] = res.error.issues.map((issue) => ({
|
|
79
|
+
path: issue.path as (string | number)[],
|
|
80
|
+
message: issue.message,
|
|
81
|
+
code: issue.code,
|
|
82
|
+
}));
|
|
83
|
+
return { success: false, issues, error: res.error };
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
// Attach the underlying zod schema for adapter round-trips without
|
|
87
|
+
// widening the public Schema<T> surface.
|
|
88
|
+
(s as unknown as { __zod: AnyZodSchema }).__zod = zs;
|
|
89
|
+
return s;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function toZodShape(
|
|
93
|
+
shape: Record<string, Schema<unknown>>,
|
|
94
|
+
): Record<string, AnyZodSchema> {
|
|
95
|
+
const out: Record<string, AnyZodSchema> = {};
|
|
96
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
97
|
+
out[key] = toZod(value);
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const coerce: SchemaValidatorCoerce = {
|
|
103
|
+
string: (): Schema<string> => wrap(z.coerce.string()),
|
|
104
|
+
number: (): Schema<number> => wrap(z.coerce.number()),
|
|
105
|
+
boolean: (): Schema<boolean> => wrap(z.coerce.boolean()),
|
|
106
|
+
date: (): Schema<Date> => wrap(z.coerce.date()),
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/** The zod-backed `SchemaValidator` singleton registered by `registerZodAdapter`. */
|
|
110
|
+
export const zodAdapter: SchemaValidator = {
|
|
111
|
+
string: (): Schema<string> => wrap(z.string()),
|
|
112
|
+
number: (): Schema<number> => wrap(z.number()),
|
|
113
|
+
boolean: (): Schema<boolean> => wrap(z.boolean()),
|
|
114
|
+
date: (): Schema<Date> => wrap(z.date()),
|
|
115
|
+
null: (): Schema<null> => wrap(z.null()),
|
|
116
|
+
unknown: (): Schema<unknown> => wrap(z.unknown()),
|
|
117
|
+
// deno-lint-ignore no-explicit-any -- contract mirrors zod's `any` constructor
|
|
118
|
+
any: (): Schema<any> => wrap(z.any()),
|
|
119
|
+
|
|
120
|
+
object: <S extends Record<string, Schema<unknown>>>(shape: S): Schema<InferShape<S>> =>
|
|
121
|
+
wrap(z.object(toZodShape(shape))),
|
|
122
|
+
|
|
123
|
+
array: <T>(element: Schema<T>): Schema<T[]> => wrap(z.array(toZod(element))),
|
|
124
|
+
|
|
125
|
+
record: <K extends string | number | symbol, V>(
|
|
126
|
+
keys: Schema<K>,
|
|
127
|
+
values: Schema<V>,
|
|
128
|
+
): Schema<Record<K, V>> => wrap(z.record(toZod(keys) as unknown as z.ZodString, toZod(values))),
|
|
129
|
+
|
|
130
|
+
union: <T extends readonly [Schema<unknown>, ...Schema<unknown>[]]>(
|
|
131
|
+
schemas: T,
|
|
132
|
+
): Schema<T[number] extends Schema<infer U> ? U : never> => {
|
|
133
|
+
const zodSchemas = schemas.map((s: Schema<unknown>) => toZod(s)) as unknown as [
|
|
134
|
+
AnyZodSchema,
|
|
135
|
+
AnyZodSchema,
|
|
136
|
+
...AnyZodSchema[],
|
|
137
|
+
];
|
|
138
|
+
return wrap(z.union(zodSchemas));
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
discriminatedUnion: <
|
|
142
|
+
K extends string,
|
|
143
|
+
T extends readonly [Schema<unknown>, ...Schema<unknown>[]],
|
|
144
|
+
>(
|
|
145
|
+
discriminator: K,
|
|
146
|
+
schemas: T,
|
|
147
|
+
): Schema<T[number] extends Schema<infer U> ? U : never> => {
|
|
148
|
+
const zodSchemas = schemas.map((s: Schema<unknown>) => toZod(s)) as unknown as [
|
|
149
|
+
// deno-lint-ignore no-explicit-any -- discriminated-union variants widen here
|
|
150
|
+
z.ZodObject<any>,
|
|
151
|
+
// deno-lint-ignore no-explicit-any -- discriminated-union variants widen here
|
|
152
|
+
z.ZodObject<any>,
|
|
153
|
+
// deno-lint-ignore no-explicit-any -- discriminated-union variants widen here
|
|
154
|
+
...z.ZodObject<any>[],
|
|
155
|
+
];
|
|
156
|
+
return wrap(z.discriminatedUnion(discriminator, zodSchemas));
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
literal: <T extends string | number | boolean | null>(value: T): Schema<T> =>
|
|
160
|
+
wrap(z.literal(value as never)),
|
|
161
|
+
|
|
162
|
+
enum: <T extends readonly [string, ...string[]]>(values: T): Schema<T[number]> =>
|
|
163
|
+
wrap(
|
|
164
|
+
(z.enum as unknown as (v: readonly [string, ...string[]]) => AnyZodSchema)(values),
|
|
165
|
+
),
|
|
166
|
+
|
|
167
|
+
coerce,
|
|
168
|
+
|
|
169
|
+
validate: <T>(schema: Schema<T>, data: unknown): ValidationResult<T> => schema.safeParse(data),
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Register the zod adapter as the default `SchemaValidator` implementation.
|
|
174
|
+
*
|
|
175
|
+
* Called once at core bootstrap (`src/schemas/index.ts` side-effect import).
|
|
176
|
+
* Phase B will delete this function when `@veryfront/ext-zod` takes over.
|
|
177
|
+
*/
|
|
178
|
+
export function registerZodAdapter(): void {
|
|
179
|
+
register<SchemaValidator>("SchemaValidator", zodAdapter);
|
|
180
|
+
}
|
|
@@ -3,6 +3,8 @@ import type { VeryfrontConfig } from "../config/index.js";
|
|
|
3
3
|
import type { InvalidationProjectContext } from "../platform/adapters/fs/veryfront/types.js";
|
|
4
4
|
import { clearConfigCache, getConfig } from "../config/index.js";
|
|
5
5
|
import { type ExtensionLoader, orchestrateExtensions, tryResolve } from "../extensions/index.js";
|
|
6
|
+
import { AIProviderRegistryName } from "../extensions/interfaces/index.js";
|
|
7
|
+
import { createAIProviderRegistry } from "../extensions/registries/ai-provider-registry.js";
|
|
6
8
|
import type { TracingExporter } from "../extensions/interfaces/tracing-exporter.js";
|
|
7
9
|
import {
|
|
8
10
|
setGlobalActiveSpanAccessor,
|
|
@@ -198,6 +200,7 @@ export async function bootstrap(
|
|
|
198
200
|
projectDir,
|
|
199
201
|
config,
|
|
200
202
|
logger: bootstrapLog,
|
|
203
|
+
primeContracts: { [AIProviderRegistryName]: createAIProviderRegistry() },
|
|
201
204
|
});
|
|
202
205
|
wireTracingShim();
|
|
203
206
|
return {
|
|
@@ -239,6 +242,7 @@ export async function bootstrap(
|
|
|
239
242
|
projectDir,
|
|
240
243
|
config,
|
|
241
244
|
logger: bootstrapLog,
|
|
245
|
+
primeContracts: { [AIProviderRegistryName]: createAIProviderRegistry() },
|
|
242
246
|
});
|
|
243
247
|
wireTracingShim();
|
|
244
248
|
return {
|
|
@@ -302,6 +306,7 @@ export async function bootstrap(
|
|
|
302
306
|
projectDir,
|
|
303
307
|
config,
|
|
304
308
|
logger: bootstrapLog,
|
|
309
|
+
primeContracts: { [AIProviderRegistryName]: createAIProviderRegistry() },
|
|
305
310
|
}),
|
|
306
311
|
fsDispose,
|
|
307
312
|
);
|
|
@@ -1,184 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Shim over the `CodeParser` contract's `injectJsxNodePositions()` method.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* The actual Babel-based implementation lives in `@veryfront/ext-babel`.
|
|
5
|
+
* Core modules continue to import from this path; the shim resolves the
|
|
6
|
+
* contract at call time. Position injection powers Studio Navigator only —
|
|
7
|
+
* if `ext-babel` is not installed we return the source unchanged rather
|
|
8
|
+
* than fail the SSR path.
|
|
6
9
|
*/
|
|
7
10
|
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import * as generateModule from "@babel/generator";
|
|
11
|
-
import * as t from "@babel/types";
|
|
12
|
-
|
|
13
|
-
// Local type definitions for Babel traverse/generate (they don't bundle types)
|
|
14
|
-
interface BabelNodePath<T = t.Node> {
|
|
15
|
-
node: T;
|
|
16
|
-
parent: t.Node;
|
|
17
|
-
parentPath: BabelNodePath | null;
|
|
18
|
-
scope: unknown;
|
|
19
|
-
type: string;
|
|
20
|
-
skip(): void;
|
|
21
|
-
stop(): void;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
interface BabelGeneratorResult {
|
|
25
|
-
code: string;
|
|
26
|
-
map?: unknown;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
type TraverseFunction = (ast: t.Node, opts: Record<string, unknown>) => void;
|
|
30
|
-
type GenerateFunction = (ast: t.Node, opts?: Record<string, unknown>) => BabelGeneratorResult;
|
|
31
|
-
|
|
32
|
-
interface ModuleWithDefault<T> {
|
|
33
|
-
default: T | { default: T };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function resolveDefaultExport<T>(mod: unknown): T {
|
|
37
|
-
const m = mod as ModuleWithDefault<T>;
|
|
38
|
-
if (typeof m.default === "function") return m.default as T;
|
|
39
|
-
|
|
40
|
-
const nested = m.default as { default?: T } | undefined;
|
|
41
|
-
if (typeof nested?.default === "function") return nested.default as T;
|
|
42
|
-
|
|
43
|
-
return mod as T;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const traverse: TraverseFunction = resolveDefaultExport<TraverseFunction>(traverseModule);
|
|
47
|
-
const generate: GenerateFunction = resolveDefaultExport<GenerateFunction>(generateModule);
|
|
48
|
-
|
|
49
|
-
const SKIPPED_ELEMENTS = new Set([
|
|
50
|
-
"html",
|
|
51
|
-
"head",
|
|
52
|
-
"title",
|
|
53
|
-
"body",
|
|
54
|
-
"link",
|
|
55
|
-
"base",
|
|
56
|
-
"meta",
|
|
57
|
-
"script",
|
|
58
|
-
"style",
|
|
59
|
-
"noscript",
|
|
60
|
-
"template",
|
|
61
|
-
"svg",
|
|
62
|
-
"path",
|
|
63
|
-
"circle",
|
|
64
|
-
"ellipse",
|
|
65
|
-
"line",
|
|
66
|
-
"polygon",
|
|
67
|
-
"polyline",
|
|
68
|
-
"rect",
|
|
69
|
-
"g",
|
|
70
|
-
"defs",
|
|
71
|
-
"linearGradient",
|
|
72
|
-
"radialGradient",
|
|
73
|
-
"stop",
|
|
74
|
-
"text",
|
|
75
|
-
"tspan",
|
|
76
|
-
"use",
|
|
77
|
-
"filter",
|
|
78
|
-
]);
|
|
11
|
+
import { tryResolve } from "../../extensions/contracts.js";
|
|
12
|
+
import type { CodeParser } from "../../extensions/interfaces/index.js";
|
|
79
13
|
|
|
80
14
|
interface TransformOptions {
|
|
81
15
|
filePath: string;
|
|
82
16
|
}
|
|
83
17
|
|
|
84
|
-
function getElementName(openingElement: t.JSXOpeningElement): string {
|
|
85
|
-
const { name } = openingElement;
|
|
86
|
-
|
|
87
|
-
if (t.isJSXIdentifier(name)) return name.name;
|
|
88
|
-
|
|
89
|
-
if (!t.isJSXMemberExpression(name)) return "DynamicComponent";
|
|
90
|
-
|
|
91
|
-
const parts: string[] = [];
|
|
92
|
-
let current: t.JSXMemberExpression | t.JSXIdentifier = name;
|
|
93
|
-
|
|
94
|
-
while (t.isJSXMemberExpression(current)) {
|
|
95
|
-
if (t.isJSXIdentifier(current.property)) parts.unshift(current.property.name);
|
|
96
|
-
current = current.object;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (t.isJSXIdentifier(current)) parts.unshift(current.name);
|
|
100
|
-
|
|
101
|
-
return parts.length ? parts.join(".") : "MemberExpression";
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function isFragment(openingElement: t.JSXOpeningElement): boolean {
|
|
105
|
-
const { name } = openingElement;
|
|
106
|
-
|
|
107
|
-
if (t.isJSXMemberExpression(name)) {
|
|
108
|
-
return (
|
|
109
|
-
t.isJSXIdentifier(name.object) &&
|
|
110
|
-
name.object.name === "React" &&
|
|
111
|
-
t.isJSXIdentifier(name.property) &&
|
|
112
|
-
name.property.name === "Fragment"
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return t.isJSXIdentifier(name) && name.name === "Fragment";
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function hasPositionAttribute(attributes: (t.JSXAttribute | t.JSXSpreadAttribute)[]): boolean {
|
|
120
|
-
return attributes.some((attr) => {
|
|
121
|
-
if (!t.isJSXAttribute(attr) || !t.isJSXIdentifier(attr.name)) return false;
|
|
122
|
-
return attr.name.name === "data-node-line" || attr.name.name === "data-vf-id";
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Transform TSX source to inject position data attributes into JSX elements.
|
|
128
|
-
* This enables Studio Navigator to map rendered elements back to source positions.
|
|
129
|
-
*/
|
|
130
18
|
export function injectNodePositions(source: string, options: TransformOptions): string {
|
|
131
|
-
|
|
132
|
-
if (!
|
|
133
|
-
|
|
134
|
-
try {
|
|
135
|
-
const ast = parser.parse(source, {
|
|
136
|
-
sourceType: "module",
|
|
137
|
-
plugins: ["typescript", "jsx"],
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
let nodeCounter = 0;
|
|
141
|
-
|
|
142
|
-
traverse(ast as t.Node, {
|
|
143
|
-
JSXElement: {
|
|
144
|
-
enter(path: BabelNodePath<t.JSXElement>) {
|
|
145
|
-
const openingElement = path.node.openingElement;
|
|
146
|
-
const elementName = getElementName(openingElement);
|
|
147
|
-
|
|
148
|
-
if (SKIPPED_ELEMENTS.has(elementName.toLowerCase())) return;
|
|
149
|
-
if (isFragment(openingElement)) return;
|
|
150
|
-
if (hasPositionAttribute(openingElement.attributes)) return;
|
|
151
|
-
|
|
152
|
-
const loc = openingElement.loc;
|
|
153
|
-
if (!loc) return;
|
|
154
|
-
|
|
155
|
-
const nodeId = `node-${nodeCounter++}`;
|
|
156
|
-
openingElement.attributes.push(
|
|
157
|
-
t.jsxAttribute(t.jsxIdentifier("data-node-id"), t.stringLiteral(nodeId)),
|
|
158
|
-
t.jsxAttribute(
|
|
159
|
-
t.jsxIdentifier("data-node-file"),
|
|
160
|
-
t.stringLiteral(options.filePath),
|
|
161
|
-
),
|
|
162
|
-
t.jsxAttribute(t.jsxIdentifier("data-node-name"), t.stringLiteral(elementName)),
|
|
163
|
-
t.jsxAttribute(
|
|
164
|
-
t.jsxIdentifier("data-node-line"),
|
|
165
|
-
t.stringLiteral(String(loc.start.line)),
|
|
166
|
-
),
|
|
167
|
-
t.jsxAttribute(
|
|
168
|
-
t.jsxIdentifier("data-node-column"),
|
|
169
|
-
t.stringLiteral(String(loc.start.column)),
|
|
170
|
-
),
|
|
171
|
-
);
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
return generate(ast as t.Node, {
|
|
177
|
-
retainLines: true,
|
|
178
|
-
compact: false,
|
|
179
|
-
}).code;
|
|
180
|
-
} catch (_) {
|
|
181
|
-
/* expected: source may not be parseable TSX/JSX */
|
|
182
|
-
return source;
|
|
183
|
-
}
|
|
19
|
+
const parser = tryResolve<CodeParser>("CodeParser");
|
|
20
|
+
if (!parser) return source;
|
|
21
|
+
return parser.injectJsxNodePositions(source, options);
|
|
184
22
|
}
|