@jimhoyd/urlcode 0.5.6 → 0.5.8

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 (113) hide show
  1. package/.claude/skills/urlcode-authoring/SKILL.md +15 -0
  2. package/.claude/skills/urlcode-operations/SKILL.md +4 -0
  3. package/README.md +24 -14
  4. package/dist/BUILD-MANIFEST.json +50 -49
  5. package/dist/agents-guide.js +5 -2
  6. package/dist/assets.js +2 -2
  7. package/dist/authoring.js +3 -58
  8. package/dist/aws.js +21 -4
  9. package/dist/body-schema.js +2 -3
  10. package/dist/capability-query.js +3 -3
  11. package/dist/catalog.js +1 -1
  12. package/dist/cli.js +42 -15
  13. package/dist/cloudflare.js +26 -1
  14. package/dist/config.js +1 -1
  15. package/dist/context.js +6 -6
  16. package/dist/egress.js +1 -1
  17. package/dist/examples.js +2 -2
  18. package/dist/explain.js +4 -6
  19. package/dist/extension-artifacts.js +8 -8
  20. package/dist/extension-transport.js +6 -4
  21. package/dist/function-worker.js +5 -2
  22. package/dist/functions.js +1 -1
  23. package/dist/guest-api.js +22 -15
  24. package/dist/http-policy.js +1 -3
  25. package/dist/http-response.js +61 -10
  26. package/dist/init-with.js +8 -8
  27. package/dist/interchange.js +3 -2
  28. package/dist/logging.js +4 -4
  29. package/dist/match.js +1 -1
  30. package/dist/mcp-authoring.js +1 -2
  31. package/dist/mcp.js +2 -2
  32. package/dist/object-guards.js +17 -0
  33. package/dist/pattern-guard.js +33 -3
  34. package/dist/policies/cache.js +16 -4
  35. package/dist/policies/compression.js +1 -1
  36. package/dist/policies/throttle.js +1 -1
  37. package/dist/policy.js +3 -3
  38. package/dist/prerender.js +1 -2
  39. package/dist/project-dependencies.js +8 -8
  40. package/dist/proxy.js +1 -1
  41. package/dist/readiness.js +16 -17
  42. package/dist/review.js +2 -2
  43. package/dist/route-diff.js +4 -4
  44. package/dist/router.js +1 -1
  45. package/dist/runtime.js +4 -1
  46. package/dist/scaffold.js +1 -1
  47. package/dist/schema-query.js +1 -1
  48. package/dist/server.js +49 -7
  49. package/dist/signals.js +2 -2
  50. package/dist/site.js +2 -2
  51. package/dist/trusted-functions.js +1 -1
  52. package/dist/types/assets.d.ts +3 -2
  53. package/dist/types/authoring.d.ts +3 -6
  54. package/dist/types/body-schema.d.ts +2 -1
  55. package/dist/types/catalog.d.ts +2 -1
  56. package/dist/types/config.d.ts +0 -8
  57. package/dist/types/context.d.ts +3 -1
  58. package/dist/types/egress.d.ts +1 -1
  59. package/dist/types/explain.d.ts +4 -4
  60. package/dist/types/extension-artifacts.d.ts +4 -13
  61. package/dist/types/extension-transport.d.ts +6 -4
  62. package/dist/types/functions.d.ts +1 -1
  63. package/dist/types/http-response.d.ts +7 -3
  64. package/dist/types/init-with.d.ts +3 -9
  65. package/dist/types/logging.d.ts +4 -3
  66. package/dist/types/match.d.ts +2 -1
  67. package/dist/types/object-guards.d.ts +7 -0
  68. package/dist/types/pattern-guard.d.ts +0 -1
  69. package/dist/types/policies/cache.d.ts +4 -3
  70. package/dist/types/policies/compression.d.ts +1 -1
  71. package/dist/types/policies/throttle.d.ts +1 -1
  72. package/dist/types/policy.d.ts +4 -3
  73. package/dist/types/project-dependencies.d.ts +1 -40
  74. package/dist/types/proxy.d.ts +2 -1
  75. package/dist/types/readiness.d.ts +12 -16
  76. package/dist/types/review.d.ts +0 -2
  77. package/dist/types/route-diff.d.ts +4 -3
  78. package/dist/types/router.d.ts +1 -1
  79. package/dist/types/server.d.ts +22 -0
  80. package/dist/types/signals.d.ts +3 -2
  81. package/dist/types/site.d.ts +1 -2
  82. package/dist/types/trusted-functions.d.ts +1 -1
  83. package/dist/types/types.d.ts +17 -11
  84. package/dist/types/vercel.d.ts +1 -0
  85. package/dist/types/verify-deployment.d.ts +1 -1
  86. package/dist/types.js +18 -11
  87. package/dist/vercel.js +12 -3
  88. package/dist/verify-deployment.js +29 -11
  89. package/docs/AI-AUTHORING.md +9 -0
  90. package/docs/FUNCTION-SECURITY.md +4 -0
  91. package/docs/README.md +2 -2
  92. package/docs/TOOLING.md +27 -1
  93. package/examples/assets/Makefile +1 -1
  94. package/examples/compliance/rules.mjs +2 -2
  95. package/llms-full.txt +44 -13
  96. package/llms.txt +9 -2
  97. package/package.json +4 -3
  98. package/skills/urlcode/SKILL.md +6 -6
  99. package/starters/default/.github/workflows/urlcode.yml +2 -1
  100. package/starters/default/AGENTS.md +3 -3
  101. package/starters/default/Makefile +1 -1
  102. package/starters/default/README.md +13 -11
  103. package/starters/default/tests/requests.json +0 -50
  104. package/starters/default/urlcode.yaml +1 -4
  105. package/dist/scripts/operational-drills.js +0 -33
  106. package/starters/default/functions/hello.mjs +0 -3
  107. package/starters/default/middleware/headers.mjs +0 -6
  108. package/starters/default/routes/functions.yaml +0 -20
  109. package/starters/default/routes/marketing/links.yaml +0 -7
  110. package/starters/page/README.md +0 -14
  111. package/starters/page/public/index.html +0 -12
  112. package/starters/page/tests/requests.json +0 -17
  113. package/starters/page/urlcode.yaml +0 -6
@@ -1,7 +1,6 @@
1
- import type { ScaffoldResult } from './extensions.ts';
2
1
  import type { DependencyPin } from './project-dependencies.ts';
3
2
  import { type BundleTransport } from './extension-bundles.ts';
4
- export interface InitWithOptions {
3
+ interface InitWithOptions {
5
4
  cwd?: string | undefined;
6
5
  /** Default true: record exact pins for core, the named extensions and their declared peers. */
7
6
  manifest?: boolean | undefined;
@@ -14,7 +13,7 @@ export interface InitWithOptions {
14
13
  /** Test-only transport injection; production uses GitHub attestation verification. */
15
14
  bundleTransport?: BundleTransport | undefined;
16
15
  }
17
- export interface InitWithResult {
16
+ interface InitWithResult {
18
17
  directory: string;
19
18
  project: string;
20
19
  hostFile: string;
@@ -24,15 +23,10 @@ export interface InitWithResult {
24
23
  dependencies: DependencyPin[];
25
24
  }
26
25
  export declare function parseWithNames(value: string): string[];
27
- /**
28
- * Orders the requested set from the scaffolds' declared `requires`, `after`, `provides` and `conflicts`, never from
29
- * the `--with` spelling. Kahn's algorithm with the lexically smallest ready extension first, so the result is
30
- * deterministic and identical for every permutation. Refuses a missing requirement, a conflict or a cycle by name.
31
- */
32
- export declare function orderScaffolds(results: readonly ScaffoldResult[]): ScaffoldResult[];
33
26
  /**
34
27
  * `urlcode init <directory> --with a,b`: the starter under `app/`, every extension's fragments merged into one
35
28
  * `urlcode.yaml`, one `host.mjs`, one `README.md` and the extensions' own files. All packages are resolved and
36
29
  * their scaffolds computed before anything is written, so a refusal leaves no directory behind.
37
30
  */
38
31
  export declare function initProjectWith(destination: string, requested: readonly string[], { cwd, manifest, pins, acknowledgements, bundleRelease, bundleTransport }?: InitWithOptions): Promise<InitWithResult>;
32
+ export {};
@@ -1,9 +1,10 @@
1
- export type JsonLogger = (event: object) => void;
1
+ export declare function createJsonLogger(stream?: LogSink, maxBufferBytes?: number): JsonLogger;
2
+ type JsonLogger = (event: object) => void;
2
3
  /** What the logger needs from its sink: the members of a Writable it touches. process.stdout satisfies it. */
3
- export interface LogSink {
4
+ interface LogSink {
4
5
  write(chunk: string): unknown;
5
6
  writableLength: number;
6
7
  destroyed?: boolean;
7
8
  on?(event: 'error', listener: () => void): unknown;
8
9
  }
9
- export declare function createJsonLogger(stream?: LogSink, maxBufferBytes?: number): JsonLogger;
10
+ export {};
@@ -1,5 +1,5 @@
1
1
  export type ParameterLocation = 'path' | 'query' | 'header';
2
- export type ScalarType = 'string' | 'integer' | 'number' | 'boolean';
2
+ type ScalarType = 'string' | 'integer' | 'number' | 'boolean';
3
3
  export type Scalar = string | number | boolean;
4
4
  /** A parsed scalar, a parsed array, or a schema default (which the schema may shape freely). */
5
5
  export type ParameterValue = Scalar | Scalar[] | unknown;
@@ -81,3 +81,4 @@ export declare function contextFor(route: MatchableRoute, path: Record<string, s
81
81
  export declare function redirectLocation(route: MatchableRoute & {
82
82
  redirect: RedirectSpec;
83
83
  }, context: RequestContext, query: URLSearchParams): string;
84
+ export {};
@@ -0,0 +1,7 @@
1
+ export type UnknownRecord = Record<string, unknown>;
2
+ /** True for a non-null, non-array object -- the shape most parsed JSON/YAML fields expect. */
3
+ export declare const isRecord: (value: unknown) => value is UnknownRecord;
4
+ /** True for a `key` that `object` itself declares (not inherited). */
5
+ export declare const own: (object: object, key: string) => boolean;
6
+ /** True when `error` is a Node `Error` carrying the given `code` (e.g. `'ENOENT'`). */
7
+ export declare const isCode: (error: unknown, code: string) => boolean;
@@ -1,4 +1,3 @@
1
- export declare const maxPatternLength = 128;
2
1
  export declare const maxPatternInputLength = 128;
3
2
  /**
4
3
  * Accepts an author regex only when it is conservatively safe to run on every
@@ -2,7 +2,7 @@ import type { HandlerResult, HeaderPair } from '../http-response.ts';
2
2
  import type { LogFn, PolicyContext, PolicyRequest, PolicyShared, PolicySupport, TargetName } from '../types.ts';
3
3
  export declare const name = "cache";
4
4
  export declare const phases: readonly string[];
5
- export type Strategy = 'no-store' | 'revalidate' | 'public' | 'immutable' | 'swr' | 'sie' | 'micro' | 'cdn-only' | 'private';
5
+ type Strategy = 'no-store' | 'revalidate' | 'public' | 'immutable' | 'swr' | 'sie' | 'micro' | 'cdn-only' | 'private';
6
6
  export interface CacheConfig {
7
7
  strategy: Strategy;
8
8
  maxAge?: number;
@@ -17,7 +17,7 @@ export interface CacheConfig {
17
17
  force?: boolean;
18
18
  }
19
19
  /** A stored 200 representation: the result minus its body and headers, which are kept separately. */
20
- export interface CacheEntry {
20
+ interface CacheEntry {
21
21
  result: Omit<HandlerResult, 'body' | 'headers'>;
22
22
  headers: HeaderPair[];
23
23
  body: Buffer;
@@ -25,7 +25,7 @@ export interface CacheEntry {
25
25
  revalidating: boolean;
26
26
  }
27
27
  /** The in-flight fill for one key; waiters share its promise up to MAX_WAITERS. */
28
- export interface Flight {
28
+ interface Flight {
29
29
  waiters: number;
30
30
  promise: Promise<CacheEntry | null>;
31
31
  resolve: (entry: CacheEntry | null) => void;
@@ -80,3 +80,4 @@ export declare function onResponse(state: CacheState, req: PolicyRequest, result
80
80
  export declare function onError(state: CacheState, req: PolicyRequest, _error?: unknown): void;
81
81
  export declare function describe(state: CacheState): CacheDescription;
82
82
  export declare function close(shared: PolicyShared | undefined): Promise<void>;
83
+ export {};
@@ -2,7 +2,7 @@ import type { HandlerResult } from '../http-response.ts';
2
2
  import type { AssetResult, PolicyContext, PolicyRequest, PolicyShared, PolicySupport, TargetName } from '../types.ts';
3
3
  export declare const name = "compression";
4
4
  export declare const phases: readonly string[];
5
- export type Coding = 'br' | 'gzip' | 'deflate' | 'zstd';
5
+ type Coding = 'br' | 'gzip' | 'deflate' | 'zstd';
6
6
  export interface CompressionConfig {
7
7
  encodings?: Coding[];
8
8
  minBytes?: number;
@@ -2,7 +2,7 @@ import type { HandlerResult } from '../http-response.ts';
2
2
  import type { LogFn, PolicyContext, PolicyRequest, PolicyShared, PolicySupport, TargetName } from '../types.ts';
3
3
  export declare const name = "throttle";
4
4
  export declare const phases: readonly string[];
5
- export type Partition = 'client' | 'route' | 'client-route';
5
+ type Partition = 'client' | 'route' | 'client-route';
6
6
  export interface ThrottleConfig {
7
7
  quota: number;
8
8
  window: number;
@@ -1,10 +1,10 @@
1
1
  import type { FunctionSources } from './function-sources.ts';
2
2
  import type { LoadedDocument } from './types.ts';
3
- export interface EgressGrants {
3
+ interface EgressGrants {
4
4
  proxy?: string[];
5
5
  signals?: string[];
6
6
  }
7
- export interface RouteGrant {
7
+ interface RouteGrant {
8
8
  env?: string[];
9
9
  secrets?: string[];
10
10
  egress?: EgressGrants;
@@ -16,7 +16,7 @@ export interface OperatorPolicy {
16
16
  routes: Record<string, RouteGrant>;
17
17
  }
18
18
  /** The function snapshot plus the hash operator grants are pinned to. */
19
- export interface FunctionSnapshot extends FunctionSources {
19
+ interface FunctionSnapshot extends FunctionSources {
20
20
  projectSha256: string;
21
21
  }
22
22
  export declare function prepareFunctionSnapshot(loaded: LoadedDocument): Promise<FunctionSnapshot>;
@@ -30,3 +30,4 @@ export declare function authorizeEgress(loaded: LoadedDocument, projectSha256: s
30
30
  proxy: string[];
31
31
  signals: string[];
32
32
  };
33
+ export {};
@@ -1,43 +1,4 @@
1
- /**
2
- * Exact dependency pins for a generated application.
3
- *
4
- * `urlcode init --with` resolves whatever `@jimhoyd/urlcode-<name>` packages are already installed beside the
5
- * invoking directory. Without a manifest the generated site records nothing about which versions it was built
6
- * against, so a later `npm install @jimhoyd/urlcode-auth` in that site can resolve a different set (#212). This
7
- * module reads the versions that were actually resolved, validates the whole set against the packages' own
8
- * declared `peerDependencies`, and renders a `package.json` pinning every one of them exactly.
9
- *
10
- * It never runs a package manager: generating a lockfile stays an explicit `npm install` the operator runs after
11
- * reviewing the manifest. It also never imports an extension implementation -- only package metadata is read, by
12
- * a name the caller supplied -- so core's generic extension boundary is unchanged.
13
- */
14
- export declare const CORE_PACKAGE = "@jimhoyd/urlcode";
15
- interface Version {
16
- major: number;
17
- minor: number;
18
- patch: number;
19
- pre: readonly (string | number)[];
20
- }
21
- export declare function parseVersion(value: string): Version | null;
22
- export declare function compareVersions(a: Version, b: Version): number;
23
1
  export declare function satisfiesRange(version: string, range: string, context?: string): boolean;
24
- export interface InstalledPackage {
25
- name: string;
26
- version: string;
27
- directory: string;
28
- peers: Record<string, string>;
29
- optionalPeers: ReadonlySet<string>;
30
- node: string | undefined;
31
- }
32
- /**
33
- * Walks `node_modules` upwards from the invoking directory, exactly like Node's own resolution but reading the
34
- * package's manifest rather than its entry point. Reading the manifest directly (instead of resolving the entry)
35
- * means a package whose `exports` does not expose `./package.json` is still inspectable, and nothing in the
36
- * package is loaded or executed.
37
- */
38
- export declare function findInstalledPackage(name: string, from: string): Promise<InstalledPackage | null>;
39
- /** The version of the runtime executing this command; that is the version a generated site is pinned to. */
40
- export declare function runningCore(): Promise<InstalledPackage>;
41
2
  export interface DependencyPin {
42
3
  name: string;
43
4
  version: string;
@@ -56,7 +17,7 @@ export interface DependencySet {
56
17
  /** True when any pin points at a local path or tarball. */
57
18
  local: boolean;
58
19
  }
59
- export interface DependencyOptions {
20
+ interface DependencyOptions {
60
21
  cwd?: string | undefined;
61
22
  /** `--pin <package>=<specifier>`: an operator-chosen specifier, for local tarballs and mirrors. */
62
23
  overrides?: ReadonlyMap<string, string> | undefined;
@@ -6,7 +6,7 @@ export interface ProxyDefinition {
6
6
  responseHeaders?: string[];
7
7
  headers?: Record<string, string>;
8
8
  }
9
- export interface ProxyInput {
9
+ interface ProxyInput {
10
10
  method: string;
11
11
  url: string | URL;
12
12
  params: Record<string, unknown>;
@@ -19,3 +19,4 @@ export interface EgressTransport {
19
19
  }
20
20
  export declare function validateProxy(definition: ProxyDefinition): void;
21
21
  export declare function executeProxy(client: EgressTransport, definition: ProxyDefinition, input: ProxyInput): Promise<EgressResponse>;
22
+ export {};
@@ -1,10 +1,9 @@
1
1
  import { Agent } from 'node:http';
2
2
  import type { AddressInfo } from 'node:net';
3
- import type { CompiledRedirect, CompiledRoute, LogFn, PlanInventoryEntry, PolicyInventory } from './types.ts';
3
+ import type { CompiledRedirect, CompiledRoute, HandlerName, LogFn, PlanInventoryEntry, PolicyInventory } from './types.ts';
4
4
  import type { ComplianceOptions, ComplianceReport } from './compliance.ts';
5
5
  import type { CompiledRoutes } from './match.ts';
6
- export type { RouteState } from './types.ts';
7
- export type HandlerName = 'extension' | 'proxy' | 'conditional' | 'redirect' | 'function' | 'page' | 'static' | 'download' | 'respond';
6
+ export type { RouteState, HandlerName } from './types.ts';
8
7
  /** One configured route as the inventory reports it: a PlanInventoryEntry with the handler kind named. */
9
8
  export interface RouteInventory extends PlanInventoryEntry {
10
9
  handler: HandlerName | undefined;
@@ -27,29 +26,28 @@ export interface RequestCase {
27
26
  capture?: Record<string, CaptureSpec> | undefined;
28
27
  }
29
28
  /** Where a captured value comes from: a dotted path into a JSON response body, or one response header. */
30
- export type CaptureSpec = {
29
+ type CaptureSpec = {
31
30
  json: string;
32
31
  } | {
33
32
  header: string;
34
33
  };
35
34
  /** A step that closes and restarts the runtime on the same project and data directory. */
36
- export interface RestartStep {
35
+ interface RestartStep {
37
36
  restart: true;
38
37
  }
39
38
  /** An ordered fixture: requests that share captured values, optionally with restarts between them. */
40
- export interface StepsFixture {
39
+ interface StepsFixture {
41
40
  steps: (RequestCase | RestartStep)[];
42
41
  }
43
42
  export type Fixture = RequestCase | StepsFixture;
44
43
  export declare const isStepsFixture: (fixture: Fixture) => fixture is StepsFixture;
45
- export declare const isRestartable: (app: AuditableApp) => app is RestartableApp;
46
44
  export interface ProjectPlan {
47
45
  inventory: RouteInventory[];
48
46
  cases: RequestCase[];
49
47
  resolve: (path: string) => string | undefined;
50
48
  }
51
49
  /** `captured` holds values from a step's `capture`; callers use it for substitution only and never print it. */
52
- export interface HitResult {
50
+ interface HitResult {
53
51
  pass: boolean;
54
52
  status: number;
55
53
  durationMs: number;
@@ -74,12 +72,12 @@ export interface RestartableApp extends AuditableApp {
74
72
  restart(): Promise<void>;
75
73
  }
76
74
  export type { ComplianceOptions, ComplianceReport } from './compliance.ts';
77
- export interface AuditOptions {
75
+ interface AuditOptions {
78
76
  expectRoutes?: number | undefined;
79
77
  log?: LogFn | undefined;
80
78
  compliance?: ComplianceOptions | undefined;
81
79
  }
82
- export interface AuditReport {
80
+ interface AuditReport {
83
81
  elapsedMs: number;
84
82
  ready: boolean;
85
83
  /** Empty when `ready`; otherwise one stable code per failed condition:
@@ -134,7 +132,7 @@ export interface AuditReport {
134
132
  message: string;
135
133
  }[];
136
134
  }
137
- export interface BenchmarkOptions {
135
+ interface BenchmarkOptions {
138
136
  requests?: number | undefined;
139
137
  concurrency?: number | undefined;
140
138
  maxP95Ms?: number | undefined;
@@ -142,7 +140,7 @@ export interface BenchmarkOptions {
142
140
  warmup?: number | undefined;
143
141
  target?: string | undefined;
144
142
  }
145
- export interface BenchmarkReport {
143
+ interface BenchmarkReport {
146
144
  pass: boolean;
147
145
  requested: number;
148
146
  completed: number;
@@ -174,17 +172,15 @@ export declare const hasRedirect: (route: CompiledRoute) => route is CompiledRou
174
172
  export declare const probeAgent = "Mozilla/5.0 (compatible; RouteProbe/0.1)";
175
173
  export declare function projectPlan(compiled: CompiledRoutes<CompiledRoute>): ProjectPlan;
176
174
  export declare function readFixtures(root: string, optional?: boolean): Promise<Fixture[]>;
177
- /** Single-request fixtures only: the benchmark replays these and cannot run ordered steps. */
178
- export declare function readCases(root: string, optional?: boolean): Promise<RequestCase[]>;
179
175
  /** One request a fixture run sent: `test` is the request as sent (captured values filled in), `original` as written. Print `original`, never `test`. */
180
- export interface FixtureStep {
176
+ interface FixtureStep {
181
177
  case: number;
182
178
  fixture: number;
183
179
  test: RequestCase;
184
180
  original: RequestCase;
185
181
  result: HitResult;
186
182
  }
187
- export interface FixtureHost {
183
+ interface FixtureHost {
188
184
  app: AuditableApp;
189
185
  agent: Agent;
190
186
  target?: BenchmarkTarget | undefined;
@@ -25,6 +25,4 @@ export interface ProjectReview {
25
25
  observations: ReviewObservation[];
26
26
  summary: Record<ReviewCategory, number>;
27
27
  }
28
- export declare const reviewModuleByteLimit = 1048576;
29
- export declare const reviewExcerptLimit = 240;
30
28
  export declare function reviewProject(project: string, options?: InspectOptions): Promise<ProjectReview>;
@@ -1,6 +1,6 @@
1
1
  import type { PlanInventoryEntry } from './types.ts';
2
2
  /** One route as the diff sees it: the inventory entry plus its policy description from the `policies` map. */
3
- export interface RouteRecord extends PlanInventoryEntry {
3
+ interface RouteRecord extends PlanInventoryEntry {
4
4
  policy?: Record<string, unknown>;
5
5
  }
6
6
  /** The parts of a `urlcode routes` report the diff reads. */
@@ -8,12 +8,12 @@ export interface RouteSnapshot {
8
8
  inventory: PlanInventoryEntry[];
9
9
  policies?: Record<string, Record<string, unknown>> | undefined;
10
10
  }
11
- export interface RouteChange {
11
+ interface RouteChange {
12
12
  path: string;
13
13
  before: RouteRecord;
14
14
  after: RouteRecord;
15
15
  }
16
- export interface RouteDiff {
16
+ interface RouteDiff {
17
17
  added: RouteRecord[];
18
18
  removed: RouteRecord[];
19
19
  changed: RouteChange[];
@@ -25,3 +25,4 @@ export declare function diffRoutes(before: RouteSnapshot, after: RouteSnapshot):
25
25
  export declare const hasRouteChanges: (diff: RouteDiff) => boolean;
26
26
  /** Renders a diff as Markdown: one table per nonempty section, or "No route changes". */
27
27
  export declare function renderRouteDiff(diff: RouteDiff): string;
28
+ export {};
@@ -2,7 +2,7 @@ import type { RuntimeExtension } from './extensions.ts';
2
2
  import type { CompiledRouteTable, LoadedDocument } from './types.ts';
3
3
  export { parseTarget, matchRoute, contextFor, resolveValue, redirectLocation } from './match.ts';
4
4
  /** The grants compileRoutes consults: a validated OperatorPolicy (policy.ts) or nothing, which denies every binding. */
5
- export interface BindingPermissions {
5
+ interface BindingPermissions {
6
6
  projectSha256?: string;
7
7
  routes?: Record<string, {
8
8
  env?: string[];
@@ -16,6 +16,28 @@ export interface ServerOptions extends Omit<RuntimeOptions, 'observers'> {
16
16
  observers?: Observer[] | undefined;
17
17
  metrics?: boolean | undefined;
18
18
  metricsIntervalMs?: number | undefined;
19
+ /** Expose build version and route count on `/_urlcode/health`. Off by default so an
20
+ * unauthenticated probe does not disclose deployment details; defaults to `metrics`
21
+ * so enabling the (also unauthenticated-by-default) metrics exposition keeps its
22
+ * existing level of disclosure. */
23
+ healthDetails?: boolean | undefined;
24
+ /** Milliseconds `close()` waits, with the listener still open and `/_urlcode/ready`
25
+ * already reporting unhealthy, before it stops accepting connections. Gives a load
26
+ * balancer time to notice the readiness change and stop routing new traffic here.
27
+ * `/_urlcode/health` (liveness) stays healthy during this window. 0 disables the delay. */
28
+ readinessDrainMs?: number | undefined;
29
+ /** Milliseconds `close()` gives in-flight HTTP connections to finish once it stops
30
+ * accepting new ones, before forcing them closed. Keep this below the process
31
+ * supervisor's stop grace period (Docker's `--stop-timeout`, Kubernetes'
32
+ * `terminationGracePeriodSeconds`) combined with `readinessDrainMs`, or the process
33
+ * can be SIGKILLed mid-drain. */
34
+ closeTimeoutMs?: number | undefined;
35
+ /** Milliseconds allowed to receive a request's headers before the socket is reset. */
36
+ headersTimeoutMs?: number | undefined;
37
+ /** Milliseconds allowed for an entire request (headers and body) before the socket is reset. */
38
+ requestTimeoutMs?: number | undefined;
39
+ /** Milliseconds an idle keep-alive connection is held open for reuse. */
40
+ keepAliveTimeoutMs?: number | undefined;
19
41
  /** Test helper. Directory the project may use for its own files, offered as the `URLCODE_DATA_DIR`
20
42
  * environment value (a route reads it through a declared `env` binding). Created if absent and
21
43
  * never deleted by `close()`, so a later server started on the same directory sees the same data. */
@@ -3,12 +3,12 @@ export interface SignalDefinition {
3
3
  url: string;
4
4
  headers?: Record<string, string>;
5
5
  }
6
- export interface SignalEvent {
6
+ interface SignalEvent {
7
7
  route: string;
8
8
  status: number;
9
9
  method: string;
10
10
  }
11
- export interface SignalStats {
11
+ interface SignalStats {
12
12
  accepted: number;
13
13
  delivered: number;
14
14
  failed: number;
@@ -23,3 +23,4 @@ export declare class SignalBroker {
23
23
  emit(definition: SignalDefinition, event: SignalEvent): boolean;
24
24
  close(): Promise<void>;
25
25
  }
26
+ export {};
@@ -1,5 +1,5 @@
1
1
  import type { LoadedDocument, LogFn, ProjectDocument, RouteConfig, SiteConfig } from './types.ts';
2
- export interface SiteOptions {
2
+ interface SiteOptions {
3
3
  origin?: string | undefined;
4
4
  log?: LogFn;
5
5
  routes?: Record<string, RouteConfig>;
@@ -8,6 +8,5 @@ type SiteKey = keyof SiteConfig;
8
8
  export declare const generatedPaths: Readonly<Record<SiteKey, string>>;
9
9
  export declare function expandSite(document: ProjectDocument, root: string, { origin, log, routes }?: SiteOptions): Promise<Record<string, RouteConfig>>;
10
10
  export declare function applySite(loaded: LoadedDocument, options?: SiteOptions): Promise<Record<string, RouteConfig>>;
11
- export declare const notFoundInlineLimit = 65536;
12
11
  export declare function inlineNotFound(loaded: LoadedDocument): Promise<boolean>;
13
12
  export {};
@@ -2,7 +2,7 @@ import type { FunctionRoute } from './function-sources.ts';
2
2
  import type { FunctionContext, FunctionResult } from './functions.ts';
3
3
  import type { GuestRequestPayload } from './guest-api.ts';
4
4
  import type { HandlerResult } from './http-response.ts';
5
- export interface TrustedFunctionsOptions {
5
+ interface TrustedFunctionsOptions {
6
6
  timeoutMs?: number | undefined;
7
7
  maxBytes?: number | undefined;
8
8
  }
@@ -27,13 +27,13 @@ export interface ParameterConfig {
27
27
  * degrades to its literal default rather than failing); with no `default`, a missing grant
28
28
  * fails route compilation (docs/yaml/functions.md, "Host overrides").
29
29
  */
30
- export interface EnvBinding {
30
+ interface EnvBinding {
31
31
  value?: string;
32
32
  env?: string;
33
33
  default?: string;
34
34
  }
35
35
  /** `secrets` binding: the `secret` name to read from the process environment. */
36
- export interface SecretBinding {
36
+ interface SecretBinding {
37
37
  secret: string;
38
38
  }
39
39
  export interface FunctionConfig {
@@ -100,7 +100,7 @@ export interface RobotsConfig {
100
100
  sitemap?: boolean;
101
101
  extra?: string[];
102
102
  }
103
- export type Changefreq = 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
103
+ type Changefreq = 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
104
104
  export interface SitemapConfig {
105
105
  exclude?: string[];
106
106
  changefreq?: Changefreq;
@@ -124,11 +124,11 @@ export interface SiteConfig {
124
124
  notFound?: string;
125
125
  }
126
126
  /** One route as declared in YAML (plus `generated`, which site.ts stamps on the routes it adds). */
127
- export interface ConditionalReply {
127
+ interface ConditionalReply {
128
128
  redirect?: RedirectConfig;
129
129
  respond?: RespondSpec;
130
130
  }
131
- export interface ConditionalConfig {
131
+ interface ConditionalConfig {
132
132
  cases: (ConditionalReply & {
133
133
  match: RouteMatch;
134
134
  })[];
@@ -137,15 +137,15 @@ export interface ConditionalConfig {
137
137
  export type EgressHeaders = Record<string, string | {
138
138
  secret: string;
139
139
  }>;
140
- export interface ProxyConfig extends Omit<ProxyDefinition, 'headers'> {
140
+ interface ProxyConfig extends Omit<ProxyDefinition, 'headers'> {
141
141
  headers?: EgressHeaders;
142
142
  }
143
- export interface SignalConfig {
143
+ interface SignalConfig {
144
144
  url: string;
145
145
  headers?: EgressHeaders;
146
146
  }
147
147
  /** Route-level `auth` short form. Keys other than `required` mirror the auth extension's policy schema and expand to `policies.extensions.auth`. */
148
- export interface RouteAuthConfig {
148
+ interface RouteAuthConfig {
149
149
  required?: boolean;
150
150
  role?: string;
151
151
  permission?: string;
@@ -202,6 +202,11 @@ export interface RouteConfig {
202
202
  /** Set by site.ts on a route it generated (`site.<key>`); never declared in YAML. */
203
203
  generated?: string;
204
204
  }
205
+ /** The route-level fields that select a handler, in priority order for the rare case more than one is set. */
206
+ export declare const handlerNames: readonly ["extension", "proxy", "conditional", "redirect", "function", "page", "static", "download", "respond"];
207
+ export type HandlerName = typeof handlerNames[number];
208
+ /** The first declared handler field's name, or `fallback` when the route (or, for a partial view such as `explain`'s route summary, the fields read) declares none. Shared by examples.ts and context.ts, whose only difference was this fallback string. */
209
+ export declare function resolveHandlerName(route: Partial<Record<HandlerName, unknown>>, fallback: string): string;
205
210
  /** A named, reusable `request` and `response.headers` block a route selects with `use`. */
206
211
  export interface SharedBlock {
207
212
  request?: RouteConfig['request'];
@@ -225,12 +230,12 @@ export interface LoadedDocument {
225
230
  files: string[];
226
231
  version: string;
227
232
  }
228
- export interface CompiledFunction {
233
+ interface CompiledFunction {
229
234
  source: string;
230
235
  export: string;
231
236
  args?: Record<string, ValueRef | Scalar>;
232
237
  }
233
- export interface CompiledMiddleware {
238
+ interface CompiledMiddleware {
234
239
  source: string;
235
240
  export: string;
236
241
  }
@@ -389,7 +394,7 @@ export type PolicyInventory = {
389
394
  };
390
395
  };
391
396
  /** A module paired with the state it compiled for one route, in phase order. */
392
- export type PolicyEntry = [PolicyModule, unknown];
397
+ type PolicyEntry = [PolicyModule, unknown];
393
398
  /** What compilePolicies returns for a route: ordered hook chains, the audit summary and each state by name. */
394
399
  export type PolicyChain = {
395
400
  request: PolicyEntry[];
@@ -423,3 +428,4 @@ export interface TestPlan {
423
428
  resolve?(path: string): string | undefined;
424
429
  policies?: Record<string, PolicyInventory>;
425
430
  }
431
+ export {};
@@ -11,4 +11,5 @@ export interface VercelHandlerOptions {
11
11
  extensions?: RuntimeExtension[] | undefined;
12
12
  }
13
13
  export type VercelHandler = (req: IncomingMessage, res: ServerResponse) => Promise<void>;
14
+ export declare function forwardedClient(headers: Headers, headerCounts: Record<string, number>): string | undefined;
14
15
  export declare function createVercelHandler({ project, origin, environment, maxBodyBytes, plugins, extensions }?: VercelHandlerOptions): VercelHandler;
@@ -3,7 +3,7 @@ import type { ComplianceOptions, ComplianceReport, Severity } from './compliance
3
3
  import type { LogFn } from './types.ts';
4
4
  export type { Severity } from './compliance.ts';
5
5
  export type FailOn = Severity | 'none';
6
- export type CheckName = 'probes' | 'fixtures' | 'security' | 'cache' | 'compression' | 'agents' | 'throttle' | 'site' | 'methods' | 'errors' | 'head' | 'transport';
6
+ type CheckName = 'probes' | 'fixtures' | 'security' | 'cache' | 'compression' | 'agents' | 'throttle' | 'site' | 'methods' | 'errors' | 'head' | 'transport';
7
7
  export interface VerifyFinding {
8
8
  check: CheckName;
9
9
  severity: Severity;
package/dist/types.js CHANGED
@@ -34,9 +34,9 @@
34
34
  * degrades to its literal default rather than failing); with no `default`, a missing grant
35
35
  * fails route compilation (docs/yaml/functions.md, "Host overrides").
36
36
  */
37
-
37
+
38
38
  /** `secrets` binding: the `secret` name to read from the process environment. */
39
-
39
+
40
40
 
41
41
 
42
42
  /** A route as YAML may spell it before normalization: `function` and middleware entries may be short-form module paths. */
@@ -56,7 +56,7 @@
56
56
  /** The result of layering profiles and route keys: what compiles, per policy. */
57
57
 
58
58
 
59
-
59
+
60
60
 
61
61
 
62
62
 
@@ -64,13 +64,13 @@
64
64
 
65
65
 
66
66
  /** One route as declared in YAML (plus `generated`, which site.ts stamps on the routes it adds). */
67
-
68
-
67
+
68
+
69
69
 
70
-
71
-
70
+
71
+
72
72
  /** Route-level `auth` short form. Keys other than `required` mirror the auth extension's policy schema and expand to `policies.extensions.auth`. */
73
-
73
+
74
74
 
75
75
 
76
76
 
@@ -102,6 +102,13 @@
102
102
 
103
103
 
104
104
 
105
+ /** The route-level fields that select a handler, in priority order for the rare case more than one is set. */
106
+ export const handlerNames = ['extension','proxy','conditional','redirect','function','page','static','download','respond'] ;
107
+
108
+ /** The first declared handler field's name, or `fallback` when the route (or, for a partial view such as `explain`'s route summary, the fields read) declares none. Shared by examples.ts and context.ts, whose only difference was this fallback string. */
109
+ export function resolveHandlerName(route , fallback ) {
110
+ return handlerNames.find(name => route[name] !== undefined) ?? fallback;
111
+ }
105
112
  /** A named, reusable `request` and `response.headers` block a route selects with `use`. */
106
113
 
107
114
 
@@ -114,8 +121,8 @@
114
121
  // ---------------------------------------------------------------------------
115
122
  // Compiled routes and assets.
116
123
 
117
-
118
-
124
+
125
+
119
126
  /** One file read into the asset snapshot; a static route holds a Map of them keyed by relative path. */
120
127
 
121
128
 
@@ -199,7 +206,7 @@
199
206
  /** A route's policy inventory: each policy's describe() plus the support it got; a delegated policy carries only `target`. */
200
207
 
201
208
  /** A module paired with the state it compiled for one route, in phase order. */
202
-
209
+
203
210
  /** What compilePolicies returns for a route: ordered hook chains, the audit summary and each state by name. */
204
211
 
205
212