@jimhoyd/urlcode 0.3.0 → 0.4.0-alpha.2
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/.claude/skills/urlcode-authoring/SKILL.md +122 -0
- package/.claude/skills/urlcode-operations/SKILL.md +108 -0
- package/.claude-plugin/marketplace.json +18 -0
- package/CONTRIBUTING.md +30 -2
- package/README.md +195 -255
- package/ROADMAP.md +143 -15
- package/SECURITY.md +31 -9
- package/dist/BUILD-MANIFEST.json +72 -47
- package/dist/adapters.js +4 -23
- package/dist/agent-lists.js +1 -1
- package/dist/agents-guide.js +113 -0
- package/dist/authoring-files.js +60 -0
- package/dist/authoring.js +11 -1
- package/dist/aws.js +4 -3
- package/dist/build-cloudflare.js +11 -24
- package/dist/build-static.js +134 -0
- package/dist/bulk.js +37 -0
- package/dist/capabilities.js +262 -0
- package/dist/capability-query.js +71 -0
- package/dist/catalog.js +105 -0
- package/dist/cli.js +165 -34
- package/dist/client-address.js +1 -1
- package/dist/compliance-rules/baseline.js +9 -17
- package/dist/compliance-rules/privacy.js +7 -18
- package/dist/compliance-rules/shared.js +0 -2
- package/dist/compliance-rules/strict.js +5 -5
- package/dist/compliance.js +6 -8
- package/dist/conditions.js +88 -0
- package/dist/config.js +69 -6
- package/dist/context.js +155 -0
- package/dist/ecosystem-cli.js +88 -0
- package/dist/egress.js +98 -0
- package/dist/examples.js +92 -0
- package/dist/explain-cli.js +64 -0
- package/dist/explain.js +131 -0
- package/dist/extensions.js +231 -0
- package/dist/function-sources.js +49 -5
- package/dist/function-worker.js +3 -1
- package/dist/functions.js +84 -13
- package/dist/guest-api.js +29 -3
- package/dist/index.js +40 -6
- package/dist/init-with.js +165 -0
- package/dist/interchange-cli.js +42 -0
- package/dist/interchange.js +189 -0
- package/dist/manifest.js +109 -0
- package/dist/match.js +2 -2
- package/dist/mcp-authoring.js +147 -0
- package/dist/mcp.js +97 -0
- package/dist/observability.js +7 -21
- package/dist/operator-host.js +29 -0
- package/dist/plugins.js +12 -0
- package/dist/policies/agents.js +2 -2
- package/dist/policies/cache.js +8 -3
- package/dist/policies/compression.js +2 -1
- package/dist/policies/security.js +0 -0
- package/dist/policies.js +1 -1
- package/dist/policy.js +56 -15
- package/dist/prerender.js +100 -41
- package/dist/project-tests.js +3 -3
- package/dist/provider-verification.js +92 -0
- package/dist/proxy.js +44 -0
- package/dist/readiness.js +34 -11
- package/dist/recipes.js +41 -0
- package/dist/route-diff.js +106 -0
- package/dist/router.js +45 -7
- package/dist/runtime.js +164 -64
- package/dist/sandbox.js +48 -0
- package/dist/scaffold.js +0 -0
- package/dist/schema-query.js +62 -0
- package/dist/scripts/operational-drills.js +12 -54
- package/dist/server.js +3 -29
- package/dist/signals.js +24 -0
- package/dist/site.js +0 -0
- package/dist/tooling.js +96 -0
- package/dist/trusted-functions.js +210 -0
- package/dist/types/adapters.d.ts +7 -4
- package/dist/types/agent-lists.d.ts +0 -1
- package/dist/types/agents-guide.d.ts +17 -0
- package/dist/types/authoring-files.d.ts +10 -0
- package/dist/types/aws.d.ts +3 -1
- package/dist/types/build-cloudflare.d.ts +1 -0
- package/dist/types/build-static.d.ts +43 -0
- package/dist/types/bulk.d.ts +27 -0
- package/dist/types/capabilities.d.ts +64 -0
- package/dist/types/capability-query.d.ts +24 -0
- package/dist/types/catalog.d.ts +65 -0
- package/dist/types/client-address.d.ts +0 -1
- package/dist/types/compliance-rules/baseline.d.ts +1 -9
- package/dist/types/compliance-rules/privacy.d.ts +1 -4
- package/dist/types/compliance-rules/shared.d.ts +0 -2
- package/dist/types/compliance-rules/strict.d.ts +0 -5
- package/dist/types/compliance.d.ts +0 -3
- package/dist/types/conditions.d.ts +19 -0
- package/dist/types/config.d.ts +21 -2
- package/dist/types/context.d.ts +66 -0
- package/dist/types/ecosystem-cli.d.ts +17 -0
- package/dist/types/egress.d.ts +46 -0
- package/dist/types/examples.d.ts +50 -0
- package/dist/types/explain-cli.d.ts +11 -0
- package/dist/types/explain.d.ts +95 -0
- package/dist/types/extensions.d.ts +177 -0
- package/dist/types/function-sources.d.ts +9 -0
- package/dist/types/functions.d.ts +48 -5
- package/dist/types/guest-api.d.ts +1 -0
- package/dist/types/index.d.ts +36 -6
- package/dist/types/init-with.d.ts +30 -0
- package/dist/types/interchange-cli.d.ts +16 -0
- package/dist/types/interchange.d.ts +42 -0
- package/dist/types/manifest.d.ts +79 -0
- package/dist/types/match.d.ts +1 -0
- package/dist/types/mcp-authoring.d.ts +92 -0
- package/dist/types/mcp.d.ts +12 -0
- package/dist/types/observability.d.ts +3 -14
- package/dist/types/operator-host.d.ts +8 -0
- package/dist/types/plugins.d.ts +2 -0
- package/dist/types/policies/agents.d.ts +0 -2
- package/dist/types/policies/compression.d.ts +2 -0
- package/dist/types/policies/security.d.ts +0 -1
- package/dist/types/policy.d.ts +15 -4
- package/dist/types/project-tests.d.ts +3 -2
- package/dist/types/provider-verification.d.ts +53 -0
- package/dist/types/proxy.d.ts +21 -0
- package/dist/types/readiness.d.ts +10 -3
- package/dist/types/recipes.d.ts +30 -0
- package/dist/types/route-diff.d.ts +27 -0
- package/dist/types/router.d.ts +2 -1
- package/dist/types/runtime.d.ts +11 -27
- package/dist/types/sandbox.d.ts +12 -0
- package/dist/types/scaffold.d.ts +0 -2
- package/dist/types/schema-query.d.ts +12 -0
- package/dist/types/server.d.ts +1 -4
- package/dist/types/signals.d.ts +25 -0
- package/dist/types/site.d.ts +0 -1
- package/dist/types/tooling.d.ts +115 -0
- package/dist/types/trusted-functions.d.ts +29 -0
- package/dist/types/types.d.ts +71 -7
- package/dist/types/typescript-authoring.d.ts +12 -0
- package/dist/types/vercel.d.ts +3 -1
- package/dist/types/verify-deployment.d.ts +47 -0
- package/dist/types.js +37 -5
- package/dist/typescript-authoring.js +142 -0
- package/dist/vercel.js +4 -3
- package/dist/verify-deployment.js +270 -0
- package/docs/AI-AUTHORING.md +232 -15
- package/docs/AWS.md +4 -4
- package/docs/BEST-PRACTICES.md +3 -2
- package/docs/BULK.md +79 -0
- package/docs/CAPABILITIES.md +192 -0
- package/docs/CAPACITY.md +129 -32
- package/docs/CI.md +142 -0
- package/docs/CLOUDFLARE.md +1 -2
- package/docs/COMPLIANCE.md +6 -9
- package/docs/CONDITIONS.md +74 -0
- package/docs/DEPLOYMENT-CHECKS.md +108 -0
- package/docs/EGRESS.md +125 -0
- package/docs/EXTENSIONS.md +398 -0
- package/docs/FRAMEWORK.md +198 -0
- package/docs/FUNCTION-SECURITY.md +129 -32
- package/docs/INSTALL.md +45 -12
- package/docs/INTERCHANGE.md +134 -0
- package/docs/LOAD-TESTING.md +4 -4
- package/docs/MIDDLEWARE-EXAMPLES.md +75 -0
- package/docs/MIDDLEWARE.md +29 -16
- package/docs/MONITORING.md +2 -19
- package/docs/NEXT-PHASE-PLAN.md +98 -0
- package/docs/NEXT-STEPS.md +634 -0
- package/docs/OBSERVABILITY.md +11 -18
- package/docs/OPEN-DECISIONS.md +212 -0
- package/docs/OPERATIONAL-PROOF.md +30 -31
- package/docs/OPERATIONS.md +29 -35
- package/docs/PLUGINS.md +37 -0
- package/docs/POLICIES.md +23 -309
- package/docs/PRERENDER.md +41 -1
- package/docs/PROJECT-DIRECTION.md +75 -8
- package/docs/PROVIDER-VERIFICATION.md +84 -0
- package/docs/READINESS.md +21 -1
- package/docs/README.md +87 -34
- package/docs/RECIPES.md +99 -0
- package/docs/RELEASE-READINESS.md +57 -35
- package/docs/RELEASE-SECURITY.md +116 -7
- package/docs/RESILIENCE.md +16 -15
- package/docs/ROUTING.md +8 -10
- package/docs/SANDBOX-REVIEW.md +19 -6
- package/docs/SCAFFOLDING.md +0 -2
- package/docs/SECURITY-AUDIT.md +41 -1
- package/docs/SPECIFICATION.md +150 -29
- package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +287 -0
- package/docs/SPIKE-BUSINESS-SUITE.md +1021 -0
- package/docs/SPIKE-CORE-LAYERING.md +337 -0
- package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +209 -0
- package/docs/SPIKE-EXTENSION-MODEL.md +419 -0
- package/docs/SPIKE-EXTENSIONS.md +6 -0
- package/docs/SPIKE-LAMBDA-COMPILE.md +201 -0
- package/docs/SPIKE-MONOREPO.md +322 -0
- package/docs/STANDARDS.md +150 -142
- package/docs/STARTERS.md +21 -1
- package/docs/STATIC.md +94 -0
- package/docs/TOOLING.md +295 -0
- package/docs/TUNNELS.md +0 -3
- package/docs/TYPESCRIPT-AUTHORING.md +82 -0
- package/docs/TYPESCRIPT.md +25 -4
- package/docs/USABILITY-REVIEW.md +129 -0
- package/docs/VERCEL.md +4 -5
- package/docs/VERSION-ALIGNMENT.md +205 -0
- package/docs/YAML-GUIDE.md +15 -479
- package/docs/YAML-REFERENCE.md +143 -22
- package/docs/policies/agents.md +1 -1
- package/docs/policies/cache.md +13 -0
- package/docs/policies/contract.md +52 -0
- package/docs/policies/hardened.md +56 -0
- package/docs/policies/interoperability.md +169 -0
- package/docs/policies/operations.md +45 -0
- package/docs/yaml/assets.md +36 -0
- package/docs/yaml/conditions.md +20 -0
- package/docs/yaml/functions.md +160 -0
- package/docs/yaml/middleware.md +29 -0
- package/docs/yaml/organization.md +74 -0
- package/docs/yaml/policies.md +37 -0
- package/docs/yaml/redirects.md +64 -0
- package/docs/yaml/responses.md +57 -0
- package/docs/yaml/site.md +24 -0
- package/examples/assets/example.yaml +17 -0
- package/examples/aws/example.yaml +20 -0
- package/examples/cloudflare/example.yaml +19 -0
- package/examples/compliance/example.yaml +11 -0
- package/examples/conditions/README.md +12 -0
- package/examples/conditions/example.yaml +19 -0
- package/examples/conditions/tests/requests.json +13 -0
- package/examples/conditions/urlcode.yaml +24 -0
- package/examples/cookbook/README.md +8 -4
- package/examples/cookbook/example.yaml +17 -0
- package/examples/cookbook/functions/catalog.mjs +3 -0
- package/examples/cookbook/functions/fail.mjs +4 -0
- package/examples/cookbook/functions/items.mjs +3 -0
- package/examples/cookbook/functions/profile.mjs +3 -0
- package/examples/cookbook/functions/resource.mjs +3 -0
- package/examples/cookbook/functions/status.mjs +3 -0
- package/examples/cookbook/middleware/auth.mjs +48 -0
- package/examples/cookbook/middleware/body.mjs +15 -0
- package/examples/cookbook/middleware/bucket.mjs +29 -0
- package/examples/cookbook/middleware/cors.mjs +21 -0
- package/examples/cookbook/middleware/debug.mjs +13 -0
- package/examples/cookbook/middleware/envelope.mjs +11 -0
- package/examples/cookbook/middleware/errors.mjs +11 -0
- package/examples/cookbook/middleware/etag.mjs +18 -0
- package/examples/cookbook/middleware/locale.mjs +20 -0
- package/examples/cookbook/middleware/maintenance.mjs +10 -0
- package/examples/cookbook/middleware/methods.mjs +15 -0
- package/examples/cookbook/middleware/negotiate.mjs +20 -0
- package/examples/cookbook/middleware/referer.mjs +12 -0
- package/examples/cookbook/middleware/request-id.mjs +16 -0
- package/examples/cookbook/route-index.json +676 -0
- package/examples/cookbook/routes/middleware.yaml +126 -0
- package/examples/cookbook/tests/requests.json +526 -0
- package/examples/cookbook/urlcode.yaml +1 -0
- package/examples/egress/README.md +22 -0
- package/examples/egress/example.yaml +19 -0
- package/examples/egress/urlcode.yaml +19 -0
- package/examples/extensions/README.md +7 -0
- package/examples/extensions/example.yaml +21 -0
- package/examples/extensions/urlcode.yaml +25 -0
- package/examples/monitoring/example.yaml +8 -0
- package/examples/prerender/README.md +2 -2
- package/examples/prerender/example.yaml +16 -0
- package/examples/provider-conformance/README.md +12 -0
- package/examples/provider-conformance/example.yaml +14 -0
- package/examples/provider-conformance/urlcode.yaml +34 -0
- package/examples/tunnel/example.yaml +8 -0
- package/examples/vercel/example.yaml +19 -0
- package/llms-full.txt +3084 -0
- package/llms.txt +61 -21
- package/package.json +36 -7
- package/packaging/claude-plugin/.claude-plugin/plugin.json +19 -0
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +122 -0
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +108 -0
- package/recipes/authenticated-json-api/README.md +51 -0
- package/recipes/authenticated-json-api/functions/profile.mjs +5 -0
- package/recipes/authenticated-json-api/recipe.yaml +34 -0
- package/recipes/authenticated-json-api/tests/requests.json +39 -0
- package/recipes/authenticated-json-api/urlcode.yaml +12 -0
- package/recipes/contact-form/README.md +25 -0
- package/recipes/contact-form/functions/contact.mjs +17 -0
- package/recipes/contact-form/recipe.yaml +33 -0
- package/recipes/contact-form/tests/requests.json +47 -0
- package/recipes/contact-form/urlcode.yaml +18 -0
- package/recipes/cors-api/README.md +16 -0
- package/recipes/cors-api/functions/items.mjs +3 -0
- package/recipes/cors-api/middleware/cors.mjs +21 -0
- package/recipes/cors-api/recipe.yaml +26 -0
- package/recipes/cors-api/tests/requests.json +65 -0
- package/recipes/cors-api/urlcode.yaml +12 -0
- package/recipes/health-page/README.md +13 -0
- package/recipes/health-page/recipe.yaml +23 -0
- package/recipes/health-page/tests/requests.json +36 -0
- package/recipes/health-page/urlcode.yaml +19 -0
- package/recipes/json-api/README.md +6 -0
- package/recipes/json-api/functions/echo.mjs +3 -0
- package/recipes/json-api/recipe.yaml +25 -0
- package/recipes/json-api/tests/requests.json +34 -0
- package/recipes/json-api/urlcode.yaml +12 -0
- package/recipes/middleware/README.md +34 -0
- package/recipes/middleware/functions/catalog.mjs +3 -0
- package/recipes/middleware/functions/fail.mjs +4 -0
- package/recipes/middleware/functions/items.mjs +3 -0
- package/recipes/middleware/functions/profile.mjs +3 -0
- package/recipes/middleware/functions/resource.mjs +3 -0
- package/recipes/middleware/functions/status.mjs +3 -0
- package/recipes/middleware/middleware/auth.mjs +48 -0
- package/recipes/middleware/middleware/body.mjs +15 -0
- package/recipes/middleware/middleware/bucket.mjs +29 -0
- package/recipes/middleware/middleware/cors.mjs +21 -0
- package/recipes/middleware/middleware/debug.mjs +13 -0
- package/recipes/middleware/middleware/envelope.mjs +11 -0
- package/recipes/middleware/middleware/errors.mjs +11 -0
- package/recipes/middleware/middleware/etag.mjs +18 -0
- package/recipes/middleware/middleware/locale.mjs +20 -0
- package/recipes/middleware/middleware/maintenance.mjs +10 -0
- package/recipes/middleware/middleware/methods.mjs +15 -0
- package/recipes/middleware/middleware/negotiate.mjs +20 -0
- package/recipes/middleware/middleware/referer.mjs +12 -0
- package/recipes/middleware/middleware/request-id.mjs +16 -0
- package/recipes/middleware/public/guide.txt +1 -0
- package/recipes/middleware/recipe.yaml +50 -0
- package/recipes/middleware/tests/requests.json +528 -0
- package/recipes/middleware/urlcode.yaml +127 -0
- package/recipes/protected-download/README.md +22 -0
- package/recipes/protected-download/files/report.txt +1 -0
- package/recipes/protected-download/recipe.yaml +31 -0
- package/recipes/protected-download/tests/requests.json +32 -0
- package/recipes/protected-download/urlcode.yaml +15 -0
- package/recipes/redirect/README.md +7 -0
- package/recipes/redirect/recipe.yaml +25 -0
- package/recipes/redirect/tests/requests.json +19 -0
- package/recipes/redirect/urlcode.yaml +9 -0
- package/recipes/static-plus-api/README.md +15 -0
- package/recipes/static-plus-api/functions/info.mjs +3 -0
- package/recipes/static-plus-api/public/assets/index.html +3 -0
- package/recipes/static-plus-api/public/assets/site.css +1 -0
- package/recipes/static-plus-api/public/index.html +8 -0
- package/recipes/static-plus-api/recipe.yaml +29 -0
- package/recipes/static-plus-api/tests/requests.json +56 -0
- package/recipes/static-plus-api/urlcode.yaml +23 -0
- package/recipes/typescript/README.md +8 -0
- package/recipes/typescript/functions/hello.ts +5 -0
- package/recipes/typescript/recipe.yaml +23 -0
- package/recipes/typescript/tests/requests.json +18 -0
- package/recipes/typescript/urlcode.yaml +5 -0
- package/recipes/webhook-receiver/README.md +20 -0
- package/recipes/webhook-receiver/functions/receive.mjs +16 -0
- package/recipes/webhook-receiver/recipe.yaml +27 -0
- package/recipes/webhook-receiver/tests/requests.json +59 -0
- package/recipes/webhook-receiver/urlcode.yaml +23 -0
- package/schemas/recipe.schema.json +139 -0
- package/schemas/urlcode.schema.json +659 -110
- package/skills/urlcode/SKILL.md +119 -0
- package/starters/default/.github/workflows/urlcode.yml +23 -0
- package/starters/default/.mcp.json +12 -0
- package/starters/default/AGENTS.md +79 -0
- package/starters/default/urlcode.yaml +0 -1
- package/dist/link-api.js +0 -136
- package/dist/link-cli.js +0 -141
- package/dist/link-events.js +0 -76
- package/dist/link-records.js +0 -31
- package/dist/link-store-worker.js +0 -150
- package/dist/link-store.js +0 -250
- package/dist/management-policy.js +0 -41
- package/dist/sqlite-version.js +0 -6
- package/dist/types/link-api.d.ts +0 -30
- package/dist/types/link-cli.d.ts +0 -36
- package/dist/types/link-events.d.ts +0 -27
- package/dist/types/link-records.d.ts +0 -11
- package/dist/types/link-store-worker.d.ts +0 -1
- package/dist/types/link-store.d.ts +0 -130
- package/dist/types/management-policy.d.ts +0 -9
- package/dist/types/sqlite-version.d.ts +0 -1
- package/docs/DYNAMIC-LINKS.md +0 -561
- package/docs/MANAGEMENT-SECURITY.md +0 -82
- package/examples/live-links/README.md +0 -11
- package/examples/live-links/tests/requests.json +0 -6
- package/examples/live-links/urlcode.yaml +0 -16
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { FunctionRoute } from './function-sources.ts';
|
|
2
|
+
import type { FunctionContext, FunctionResult } from './functions.ts';
|
|
3
|
+
import type { GuestRequestPayload } from './guest-api.ts';
|
|
4
|
+
import type { HandlerResult } from './http-response.ts';
|
|
5
|
+
import type { LogFn } from './types.ts';
|
|
6
|
+
export interface TrustedFunctionsOptions {
|
|
7
|
+
timeoutMs?: number | undefined;
|
|
8
|
+
maxBytes?: number | undefined;
|
|
9
|
+
log?: LogFn | undefined;
|
|
10
|
+
}
|
|
11
|
+
interface TrustedDefinition {
|
|
12
|
+
source: string;
|
|
13
|
+
export: string;
|
|
14
|
+
}
|
|
15
|
+
export type TrustedRoute = FunctionRoute<TrustedDefinition>;
|
|
16
|
+
export declare class TrustedFunctions {
|
|
17
|
+
timeoutMs: number;
|
|
18
|
+
maxBytes: number;
|
|
19
|
+
log: LogFn;
|
|
20
|
+
private readonly epoch;
|
|
21
|
+
constructor({ timeoutMs, maxBytes, log }?: TrustedFunctionsOptions);
|
|
22
|
+
start(routes: TrustedRoute[]): Promise<this>;
|
|
23
|
+
private loadExport;
|
|
24
|
+
execute(route: TrustedRoute, request: GuestRequestPayload, context: FunctionContext, native: HandlerResult | undefined): Promise<FunctionResult>;
|
|
25
|
+
private readBody;
|
|
26
|
+
private invoke;
|
|
27
|
+
close(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import type { ExtensionDeclaration, ExtensionPolicies } from './extensions.ts';
|
|
2
|
+
import type { ProxyDefinition } from './proxy.ts';
|
|
3
|
+
import type { SignalDefinition } from './signals.ts';
|
|
4
|
+
import type { RouteMatch } from './conditions.ts';
|
|
1
5
|
import type { HandlerResult, HeaderPair } from './http-response.ts';
|
|
2
6
|
import type { CompiledParameter, MatchableRoute, ParameterLocation, ParameterSchema, RedirectSpec, Scalar, ValueRef } from './match.ts';
|
|
3
7
|
import type { HttpRoute, Reply, RequestBodyPolicy, RespondSpec } from './http-policy.ts';
|
|
@@ -33,10 +37,11 @@ export interface MiddlewareConfig {
|
|
|
33
37
|
source: string;
|
|
34
38
|
export?: string;
|
|
35
39
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
/** A route as YAML may spell it before normalization: `function` and middleware entries may be short-form module paths. */
|
|
41
|
+
export type AuthoredRouteConfig = Omit<RouteConfig, 'function' | 'middleware'> & {
|
|
42
|
+
function?: string | FunctionConfig;
|
|
43
|
+
middleware?: (string | MiddlewareConfig)[];
|
|
44
|
+
};
|
|
40
45
|
export interface PageConfig {
|
|
41
46
|
file: string;
|
|
42
47
|
contentType?: string;
|
|
@@ -73,6 +78,8 @@ export interface PolicyConfigs {
|
|
|
73
78
|
/** One layer of policy configuration (profile, project or route); a layer may declare part of a policy, the merge supplies the rest. */
|
|
74
79
|
export type PolicyLayer = {
|
|
75
80
|
[K in PolicyName]?: Partial<PolicyConfigs[K]> | false;
|
|
81
|
+
} & {
|
|
82
|
+
extensions?: ExtensionPolicies | false;
|
|
76
83
|
};
|
|
77
84
|
export interface PoliciesConfig extends PolicyLayer {
|
|
78
85
|
profile?: string;
|
|
@@ -108,11 +115,60 @@ export interface SiteConfig {
|
|
|
108
115
|
llms?: string;
|
|
109
116
|
}
|
|
110
117
|
/** One route as declared in YAML (plus `generated`, which site.ts stamps on the routes it adds). */
|
|
118
|
+
export interface ConditionalReply {
|
|
119
|
+
redirect?: RedirectConfig;
|
|
120
|
+
respond?: RespondSpec;
|
|
121
|
+
}
|
|
122
|
+
export interface ConditionalConfig {
|
|
123
|
+
cases: (ConditionalReply & {
|
|
124
|
+
match: RouteMatch;
|
|
125
|
+
})[];
|
|
126
|
+
fallback?: ConditionalReply;
|
|
127
|
+
}
|
|
128
|
+
export type EgressHeaders = Record<string, string | {
|
|
129
|
+
secret: string;
|
|
130
|
+
}>;
|
|
131
|
+
export interface ProxyConfig extends Omit<ProxyDefinition, 'headers'> {
|
|
132
|
+
headers?: EgressHeaders;
|
|
133
|
+
}
|
|
134
|
+
export interface SignalConfig {
|
|
135
|
+
url: string;
|
|
136
|
+
headers?: EgressHeaders;
|
|
137
|
+
}
|
|
138
|
+
/** Route-level `auth` short form. Keys other than `required` mirror the auth extension's policy schema and expand to `policies.extensions.auth`. */
|
|
139
|
+
export interface RouteAuthConfig {
|
|
140
|
+
required?: boolean;
|
|
141
|
+
role?: string;
|
|
142
|
+
permission?: string;
|
|
143
|
+
verified?: boolean;
|
|
144
|
+
freshWithinSeconds?: number;
|
|
145
|
+
onDeny?: 401 | 403 | 404 | 'sign-in';
|
|
146
|
+
}
|
|
111
147
|
export interface RouteConfig {
|
|
148
|
+
extension?: string;
|
|
149
|
+
auth?: true | RouteAuthConfig;
|
|
150
|
+
/** Route-level `cache` short form: the same object accepted by `policies.cache`, expanded to it before anything else reads the project. */
|
|
151
|
+
cache?: CacheConfig;
|
|
152
|
+
proxy?: ProxyConfig;
|
|
153
|
+
signals?: SignalConfig[];
|
|
154
|
+
match?: RouteMatch;
|
|
155
|
+
conditional?: ConditionalConfig;
|
|
112
156
|
methods?: string[];
|
|
113
157
|
enabled?: boolean;
|
|
114
158
|
expires?: string;
|
|
115
159
|
description?: string;
|
|
160
|
+
/** Opt into the isolated QuickJS/WASM worker pool for this route's `function`/`middleware`
|
|
161
|
+
* chain (docs/FUNCTION-SECURITY.md). Default false: trusted, in-process, unsandboxed
|
|
162
|
+
* execution (docs/SPIKE-DEFAULT-TRUST-MODEL.md). Applies uniformly to the whole
|
|
163
|
+
* chain — `function` and any `middleware` on the same route run in the same mode. */
|
|
164
|
+
sandbox?: boolean;
|
|
165
|
+
/** Optional, human-authored justification for this route's sandbox decision — why it
|
|
166
|
+
* needs isolation when `sandbox: true`, or why it is safe to trust when it is not.
|
|
167
|
+
* Parsed and schema-validated (max 500 characters, schemas/urlcode.schema.json), stored
|
|
168
|
+
* on the compiled route and surfaced by `explain`/`context`/manifest next to `sandbox`.
|
|
169
|
+
* Never inferred or enforced: the trust decision remains the author's judgment call
|
|
170
|
+
* (docs/AI-AUTHORING.md, "Deciding when a route needs sandbox: true"). */
|
|
171
|
+
sandboxReason?: string;
|
|
116
172
|
parameters?: ParameterConfig[];
|
|
117
173
|
redirect?: RedirectConfig;
|
|
118
174
|
function?: FunctionConfig;
|
|
@@ -129,16 +185,15 @@ export interface RouteConfig {
|
|
|
129
185
|
};
|
|
130
186
|
respond?: RespondSpec;
|
|
131
187
|
middleware?: MiddlewareConfig[];
|
|
132
|
-
link?: LinkConfig;
|
|
133
188
|
policies?: PoliciesConfig;
|
|
134
189
|
/** Set by site.ts on a route it generated (`site.<key>`); never declared in YAML. */
|
|
135
190
|
generated?: string;
|
|
136
191
|
}
|
|
137
192
|
export interface ProjectDocument {
|
|
138
193
|
version: '1';
|
|
194
|
+
extensions?: Record<string, ExtensionDeclaration>;
|
|
139
195
|
routes: Record<string, RouteConfig>;
|
|
140
196
|
includes?: string[];
|
|
141
|
-
dynamicLinks?: boolean;
|
|
142
197
|
policies?: PoliciesConfig;
|
|
143
198
|
profiles?: Record<string, PolicyLayer>;
|
|
144
199
|
site?: SiteConfig;
|
|
@@ -210,6 +265,16 @@ export interface CompiledRoute extends Omit<RouteConfig, 'methods' | 'parameters
|
|
|
210
265
|
policy?: PolicyChain | null;
|
|
211
266
|
/** Attached by build-cloudflare: the compiled policy states shipped in the Worker artifact. */
|
|
212
267
|
compiledPolicies?: Record<string, unknown>;
|
|
268
|
+
extensionPolicyNames?: string[];
|
|
269
|
+
compiledProxy?: ProxyDefinition;
|
|
270
|
+
compiledSignals?: SignalDefinition[];
|
|
271
|
+
conditionalRoutes?: {
|
|
272
|
+
cases: {
|
|
273
|
+
match: RouteMatch;
|
|
274
|
+
route: CompiledRoute;
|
|
275
|
+
}[];
|
|
276
|
+
fallback?: CompiledRoute;
|
|
277
|
+
};
|
|
213
278
|
}
|
|
214
279
|
export interface CompiledRouteTable {
|
|
215
280
|
exact: Map<string, CompiledRoute>;
|
|
@@ -327,6 +392,5 @@ export interface TestPlan {
|
|
|
327
392
|
inventory: PlanInventoryEntry[];
|
|
328
393
|
cases: unknown[];
|
|
329
394
|
resolve?(path: string): string | undefined;
|
|
330
|
-
dynamicLinks?: boolean;
|
|
331
395
|
policies?: Record<string, PolicyInventory>;
|
|
332
396
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface TypeScriptBuildReport {
|
|
2
|
+
output: string;
|
|
3
|
+
dryRun: boolean;
|
|
4
|
+
modules: string[];
|
|
5
|
+
files: string[];
|
|
6
|
+
typeChecked: false;
|
|
7
|
+
}
|
|
8
|
+
/** Transpile a project snapshot ahead of runtime. No project compiler settings,
|
|
9
|
+
* plugins, package resolution, subprocesses or guest code execution are used. */
|
|
10
|
+
export declare function buildTypeScriptProject(project: string, output: string, { dryRun }?: {
|
|
11
|
+
dryRun?: boolean | undefined;
|
|
12
|
+
}): Promise<TypeScriptBuildReport>;
|
package/dist/types/vercel.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RuntimeExtension } from './extensions.ts';
|
|
1
2
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
3
|
import type { Environment } from './adapters.ts';
|
|
3
4
|
import type { HostPlugin } from './runtime.ts';
|
|
@@ -7,6 +8,7 @@ export interface VercelHandlerOptions {
|
|
|
7
8
|
environment?: Environment | undefined;
|
|
8
9
|
maxBodyBytes?: number | undefined;
|
|
9
10
|
plugins?: HostPlugin[] | undefined;
|
|
11
|
+
extensions?: RuntimeExtension[] | undefined;
|
|
10
12
|
}
|
|
11
13
|
export type VercelHandler = (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
12
|
-
export declare function createVercelHandler({ project, origin, environment, maxBodyBytes, plugins }?: VercelHandlerOptions): VercelHandler;
|
|
14
|
+
export declare function createVercelHandler({ project, origin, environment, maxBodyBytes, plugins, extensions }?: VercelHandlerOptions): VercelHandler;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { RuntimeOptions } from './runtime.ts';
|
|
2
|
+
import type { ComplianceOptions, ComplianceReport, Severity } from './compliance.ts';
|
|
3
|
+
import type { LogFn } from './types.ts';
|
|
4
|
+
export type { Severity } from './compliance.ts';
|
|
5
|
+
export type FailOn = Severity | 'none';
|
|
6
|
+
export type CheckName = 'probes' | 'fixtures' | 'security' | 'cache' | 'compression' | 'agents' | 'throttle' | 'site' | 'methods' | 'errors' | 'head' | 'transport';
|
|
7
|
+
export interface VerifyFinding {
|
|
8
|
+
check: CheckName;
|
|
9
|
+
severity: Severity;
|
|
10
|
+
route?: string;
|
|
11
|
+
message: string;
|
|
12
|
+
expected?: string;
|
|
13
|
+
observed?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface VerifyOptions extends Pick<RuntimeOptions, 'permissions'> {
|
|
16
|
+
target: string;
|
|
17
|
+
origin?: string | undefined;
|
|
18
|
+
expectRoutes?: number | undefined;
|
|
19
|
+
timeoutMs?: number | undefined;
|
|
20
|
+
expectMetrics?: boolean | undefined;
|
|
21
|
+
failOn?: FailOn | undefined;
|
|
22
|
+
compliance?: ComplianceOptions | undefined;
|
|
23
|
+
complianceWarn?: boolean | undefined;
|
|
24
|
+
log?: LogFn | undefined;
|
|
25
|
+
}
|
|
26
|
+
export interface VerifyReport {
|
|
27
|
+
target: string;
|
|
28
|
+
version: {
|
|
29
|
+
local: string;
|
|
30
|
+
observed: string | null;
|
|
31
|
+
};
|
|
32
|
+
routes: {
|
|
33
|
+
local: number;
|
|
34
|
+
observed: number | null;
|
|
35
|
+
expected: number | null;
|
|
36
|
+
};
|
|
37
|
+
requests: number;
|
|
38
|
+
checks: number;
|
|
39
|
+
findings: VerifyFinding[];
|
|
40
|
+
counts: Record<Severity, number>;
|
|
41
|
+
notes: string[];
|
|
42
|
+
failOn: FailOn;
|
|
43
|
+
pass: boolean;
|
|
44
|
+
compliance: ComplianceReport | null;
|
|
45
|
+
}
|
|
46
|
+
export declare const failLevels: readonly FailOn[];
|
|
47
|
+
export declare function verifyDeployment(project: string, { target, origin, expectRoutes, timeoutMs, expectMetrics, failOn, compliance, complianceWarn, log, permissions }: VerifyOptions): Promise<VerifyReport>;
|
package/dist/types.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
1
5
|
// Types shared across modules: the validated YAML document, the compiled
|
|
2
6
|
// route the router produces from it, and the host-side policy contract.
|
|
3
7
|
// This file is type-only (nothing here exists at run time) and append-only:
|
|
@@ -28,7 +32,8 @@
|
|
|
28
32
|
|
|
29
33
|
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
/** A route as YAML may spell it before normalization: `function` and middleware entries may be short-form module paths. */
|
|
36
|
+
|
|
32
37
|
|
|
33
38
|
|
|
34
39
|
|
|
@@ -39,7 +44,7 @@
|
|
|
39
44
|
|
|
40
45
|
/** One `policies` block or profile layer: every policy optional, `false` disables it. */
|
|
41
46
|
/** One layer of policy configuration (profile, project or route); a layer may declare part of a policy, the merge supplies the rest. */
|
|
42
|
-
|
|
47
|
+
|
|
43
48
|
|
|
44
49
|
/** The result of layering profiles and route keys: what compiles, per policy. */
|
|
45
50
|
|
|
@@ -52,18 +57,42 @@
|
|
|
52
57
|
|
|
53
58
|
|
|
54
59
|
/** One route as declared in YAML (plus `generated`, which site.ts stamps on the routes it adds). */
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
/** Route-level `auth` short form. Keys other than `required` mirror the auth extension's policy schema and expand to `policies.extensions.auth`. */
|
|
66
|
+
|
|
55
67
|
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
56
73
|
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
57
86
|
|
|
58
87
|
|
|
59
88
|
|
|
60
89
|
|
|
61
|
-
|
|
90
|
+
|
|
62
91
|
|
|
63
92
|
|
|
64
93
|
|
|
65
94
|
|
|
66
|
-
|
|
95
|
+
|
|
67
96
|
|
|
68
97
|
|
|
69
98
|
/** What config.ts returns: the entry document, the merged route table and the files it came from. */
|
|
@@ -101,6 +130,9 @@
|
|
|
101
130
|
|
|
102
131
|
|
|
103
132
|
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
104
136
|
|
|
105
137
|
|
|
106
138
|
|
|
@@ -173,5 +205,5 @@
|
|
|
173
205
|
|
|
174
206
|
|
|
175
207
|
|
|
176
|
-
|
|
208
|
+
|
|
177
209
|
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import {realpath,readdir,mkdtemp,rm} from 'node:fs/promises';
|
|
2
|
+
import {join,posix} from 'node:path';
|
|
3
|
+
import {tmpdir} from 'node:os';
|
|
4
|
+
|
|
5
|
+
import {init,parse} from 'es-module-lexer';
|
|
6
|
+
import {stringify} from 'yaml';
|
|
7
|
+
import {loadDocument} from './config.js';
|
|
8
|
+
import {collectFunctionSources,routeFunctions} from './function-sources.js';
|
|
9
|
+
import {authoringPath,authoringFile,readAuthoringFile,publishAuthoringProject} from './authoring-files.js';
|
|
10
|
+
import {assert} from './errors.js';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const emitted=(path )=>path.replace(/\.ts$/,'.js');
|
|
14
|
+
// Sandboxed-guest budget (docs/FUNCTION-SECURITY.md): what one QuickJS snapshot
|
|
15
|
+
// may cost. Trusted (non-`sandbox: true`) routes run through Node's own module
|
|
16
|
+
// resolution at serve time, so neither this budget nor the relative/static
|
|
17
|
+
// import-only rule below applies to them; only their file-read size is capped,
|
|
18
|
+
// generously, to bound authoring-time memory use.
|
|
19
|
+
const SANDBOX_MODULE_LIMIT=128,SANDBOX_MODULE_BYTE_LIMIT=1048576,SANDBOX_TOTAL_BYTE_LIMIT=4194304,TRUSTED_MODULE_BYTE_LIMIT=16*1048576;
|
|
20
|
+
|
|
21
|
+
/** Transpile a project snapshot ahead of runtime. No project compiler settings,
|
|
22
|
+
* plugins, package resolution, subprocesses or guest code execution are used. */
|
|
23
|
+
export async function buildTypeScriptProject(project ,output ,{dryRun=false} ={}) {
|
|
24
|
+
const root=await realpath(project),loaded=await loadDocument(root),files=new Map (),modules=new Map ();
|
|
25
|
+
const {default:ts}=await import('typescript');
|
|
26
|
+
// Per-path trust, so a module visited once (recursively, from its importer)
|
|
27
|
+
// is never reprocessed under a different trust level.
|
|
28
|
+
const moduleTrust=new Map ();
|
|
29
|
+
let sandboxedSourceBytes=0,sandboxedModuleCount=0,assetBytes=0;
|
|
30
|
+
await init;
|
|
31
|
+
async function collect(path ,sandboxed ) {
|
|
32
|
+
authoringPath(path);assert(/\.(?:ts|js|mjs)$/.test(path) && !path.endsWith('.d.ts'),'Guest source must be .ts, .js or .mjs');
|
|
33
|
+
const seen=moduleTrust.get(path);
|
|
34
|
+
if(seen!==undefined){assert(seen===sandboxed,'Module is imported by both a sandboxed and a trusted route');return;}
|
|
35
|
+
moduleTrust.set(path,sandboxed);
|
|
36
|
+
let bytes ;
|
|
37
|
+
if(sandboxed){
|
|
38
|
+
assert(sandboxedModuleCount<SANDBOX_MODULE_LIMIT,'Function module limit exceeded');sandboxedModuleCount++;
|
|
39
|
+
bytes=await readAuthoringFile(root,path,SANDBOX_MODULE_BYTE_LIMIT);sandboxedSourceBytes+=bytes.length;
|
|
40
|
+
assert(sandboxedSourceBytes<=SANDBOX_TOTAL_BYTE_LIMIT,'Function source limit exceeded');
|
|
41
|
+
} else {
|
|
42
|
+
bytes=await readAuthoringFile(root,path,TRUSTED_MODULE_BYTE_LIMIT);
|
|
43
|
+
}
|
|
44
|
+
const source=new TextDecoder('utf-8',{fatal:true}).decode(bytes);
|
|
45
|
+
modules.set(path,emitted(path));
|
|
46
|
+
let code=source;
|
|
47
|
+
if(path.endsWith('.ts')){
|
|
48
|
+
const ast=ts.createSourceFile(path,source,ts.ScriptTarget.ES2022,true,ts.ScriptKind.TS);
|
|
49
|
+
// Bare imports are forbidden even if they would be erased as type-only —
|
|
50
|
+
// but only for the sandboxed guest surface; a trusted route resolves
|
|
51
|
+
// them through Node like any other module once served.
|
|
52
|
+
const inspect=(node ) =>{
|
|
53
|
+
assert(!ts.isImportEqualsDeclaration(node) && !(ts.isExportAssignment(node) && node.isExportEquals),'CommonJS TypeScript module syntax is unsupported');
|
|
54
|
+
if(sandboxed && (ts.isImportDeclaration(node)||ts.isExportDeclaration(node)) && node.moduleSpecifier){
|
|
55
|
+
assert(ts.isStringLiteral(node.moduleSpecifier),'Only literal relative imports are supported');
|
|
56
|
+
const name=node.moduleSpecifier.text;
|
|
57
|
+
assert((name.startsWith('./')||name.startsWith('../')) && /\.(?:ts|js|mjs)$/.test(name),'Only relative guest module imports are supported');
|
|
58
|
+
}
|
|
59
|
+
ts.forEachChild(node,inspect);
|
|
60
|
+
};
|
|
61
|
+
inspect(ast);
|
|
62
|
+
const result=ts.transpileModule(source,{fileName:path,reportDiagnostics:true,compilerOptions:{
|
|
63
|
+
target:ts.ScriptTarget.ES2022,module:ts.ModuleKind.ESNext,isolatedModules:true,verbatimModuleSyntax:true,
|
|
64
|
+
sourceMap:false,inlineSourceMap:false,removeComments:false,
|
|
65
|
+
}});
|
|
66
|
+
assert(!result.diagnostics?.some(d=>d.category===ts.DiagnosticCategory.Error),'Invalid TypeScript guest source');
|
|
67
|
+
code=result.outputText;
|
|
68
|
+
}
|
|
69
|
+
const [imports]=parse(code);const edits =[];
|
|
70
|
+
for(const item of imports){
|
|
71
|
+
if(sandboxed){
|
|
72
|
+
assert(item.type==='static' && typeof item.specifier==='string' && !item.attributes && !item.phase,'Dynamic imports and import.meta are unsupported in sandbox functions');
|
|
73
|
+
assert(item.specifier.startsWith('./')||item.specifier.startsWith('../'),'Only relative guest module imports are supported');
|
|
74
|
+
assert(!/[\\\u0000-\u001f]/u.test(item.specifier),'Invalid guest import path');
|
|
75
|
+
const dependency=posix.normalize(posix.join(posix.dirname(path),item.specifier));
|
|
76
|
+
await collect(dependency,true);
|
|
77
|
+
edits.push({start:item.start-1,end:item.end+1,value:JSON.stringify(emitted(item.specifier))});
|
|
78
|
+
} else {
|
|
79
|
+
// Trusted routes get full Node module resolution at serve time: bare/
|
|
80
|
+
// npm specifiers, dynamic import() and import.meta pass through
|
|
81
|
+
// untouched. Only literal relative imports of project .ts/.js/.mjs
|
|
82
|
+
// modules are rewritten and recursively collected.
|
|
83
|
+
if(typeof item.specifier!=='string')continue;
|
|
84
|
+
if(!(item.specifier.startsWith('./')||item.specifier.startsWith('../')))continue;
|
|
85
|
+
assert(!/[\\\u0000-\u001f]/u.test(item.specifier),'Invalid guest import path');
|
|
86
|
+
if(!/\.(?:ts|js|mjs)$/.test(item.specifier))continue;
|
|
87
|
+
const dependency=posix.normalize(posix.join(posix.dirname(path),item.specifier));
|
|
88
|
+
await collect(dependency,false);
|
|
89
|
+
// A static specifier's start/end exclude its quotes; a dynamic
|
|
90
|
+
// import()'s already include them (es-module-lexer's own asymmetry).
|
|
91
|
+
const [start,end]=item.type==='dynamic'?[item.start,item.end]:[item.start-1,item.end+1];
|
|
92
|
+
edits.push({start,end,value:JSON.stringify(emitted(item.specifier))});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for(const edit of edits.sort((a,b)=>b.start-a.start))code=code.slice(0,edit.start)+edit.value+code.slice(edit.end);
|
|
96
|
+
const target=emitted(path);assert(!files.has(target),'Guest output module collision');files.set(target,code);
|
|
97
|
+
}
|
|
98
|
+
for(const route of Object.values(loaded.routes))for(const definition of routeFunctions(route)){
|
|
99
|
+
await collect(definition.source,!!route.sandbox);definition.source=emitted(definition.source);
|
|
100
|
+
}
|
|
101
|
+
async function asset(path ) {
|
|
102
|
+
if(files.has(path))return;assert(files.size<10000,'Authoring file limit exceeded');
|
|
103
|
+
const bytes=await readAuthoringFile(root,path,16*1048576);assetBytes+=bytes.length;
|
|
104
|
+
assert(assetBytes<=64*1048576,'Authoring asset limit exceeded');files.set(path,bytes);
|
|
105
|
+
}
|
|
106
|
+
async function directory(path ) {
|
|
107
|
+
const absolute=await authoringFile(root,path,true);
|
|
108
|
+
const entries=await readdir(absolute,{withFileTypes:true});
|
|
109
|
+
assert(entries.length>0,'Empty static directories need an asset before authoring build');
|
|
110
|
+
for(const entry of entries){
|
|
111
|
+
const child=path+'/'+entry.name;authoringPath(child);
|
|
112
|
+
assert(!entry.isSymbolicLink(),'Authoring through symlinks is forbidden');
|
|
113
|
+
if(entry.isDirectory())await directory(child);else await asset(child);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
for(const route of Object.values(loaded.routes)){
|
|
117
|
+
for(const ref of [route.page,route.download])if(ref)await asset(ref.file);
|
|
118
|
+
if(route.static)await directory(route.static.directory);
|
|
119
|
+
}
|
|
120
|
+
for(const ref of [loaded.document.site?.favicon,loaded.document.site?.llms])if(ref)await asset(ref);
|
|
121
|
+
// Request fixtures describe behavior the emitted project must keep, so they travel with it.
|
|
122
|
+
try{await asset('tests/requests.json');}catch(error){if(!(error instanceof Error && 'code' in error && error.code==='ENOENT'))throw error;}
|
|
123
|
+
// Flatten includes using the loader's duplicate-checked route table. Original
|
|
124
|
+
// project metadata stays in the entry; executable sources are the only edits.
|
|
125
|
+
const document={...loaded.document,routes:loaded.routes};delete document.includes;
|
|
126
|
+
assert(!files.has('urlcode.yaml'),'Guest source conflicts with entry configuration');
|
|
127
|
+
files.set('urlcode.yaml',stringify(document));
|
|
128
|
+
// Reuse the exact runtime module parser/path/source-budget validation on the
|
|
129
|
+
// emitted snapshot before touching the requested destination. This is the
|
|
130
|
+
// sandboxed guest's own parser/budget contract, so it only applies to
|
|
131
|
+
// `sandbox: true` routes; a trusted route's emitted module runs through
|
|
132
|
+
// Node's own resolution and carries none of that budget.
|
|
133
|
+
const temporary=await mkdtemp(join(tmpdir(),'urlcode-ts-'));
|
|
134
|
+
try {
|
|
135
|
+
const validation=await publishAuthoringProject(join(temporary,'project'),files);
|
|
136
|
+
await collectFunctionSources(Object.values(loaded.routes).filter(route=>route.sandbox).map(route=>({
|
|
137
|
+
middleware:(route.middleware||[]).map(def=>({source:join(validation,def.source),export:def.export||'default'})),
|
|
138
|
+
...(route.function?{function:{source:join(validation,route.function.source),export:route.function.export||'default'}}:{}),
|
|
139
|
+
})),validation);
|
|
140
|
+
}finally{await rm(temporary,{recursive:true,force:true});}
|
|
141
|
+
return {output:await publishAuthoringProject(output,files,dryRun),dryRun,modules:[...modules.values()].sort(),files:[...files.keys()].sort(),typeChecked:false};
|
|
142
|
+
}
|
package/dist/vercel.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
import { randomUUID } from 'node:crypto';
|
|
2
3
|
|
|
3
4
|
import { activateNativeOnly, lazyRuntime, resolveOrigin } from './adapters.js';
|
|
@@ -6,7 +7,7 @@ import { activateNativeOnly, lazyRuntime, resolveOrigin } from './adapters.js';
|
|
|
6
7
|
import { writeResponse, writeError } from './http-response.js';
|
|
7
8
|
import { assert, HttpError } from './errors.js';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
const platformOrigins = ['VERCEL_PROJECT_PRODUCTION_URL','VERCEL_URL','VERCEL_BRANCH_URL'];
|
|
@@ -31,9 +32,9 @@ function readBody(req , limit ) {
|
|
|
31
32
|
// instance and reused across warm invocations; a failed activation is not
|
|
32
33
|
// cached, so a fixed deployment recovers without a code change.
|
|
33
34
|
export function createVercelHandler({ project = process.cwd(), origin, environment = process.env,
|
|
34
|
-
maxBodyBytes = 1048576, plugins } = {}) {
|
|
35
|
+
maxBodyBytes = 1048576, plugins, extensions } = {}) {
|
|
35
36
|
assert(Number.isInteger(maxBodyBytes) && maxBodyBytes >= 1 && maxBodyBytes <= 16777216, 'Request limit must be 1–16777216 bytes');
|
|
36
|
-
const ready = lazyRuntime(() => activateNativeOnly(project, environment, { target: 'vercel', plugins }));
|
|
37
|
+
const ready = lazyRuntime(() => activateNativeOnly(project, environment, { target: 'vercel', plugins, extensions, origin:resolveOrigin(origin,environment,platformOrigins) }));
|
|
37
38
|
|
|
38
39
|
return async function handler(req,res) {
|
|
39
40
|
const requestId = randomUUID();
|