@jimhoyd/urlcode 0.3.0 → 0.4.0-alpha.1

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 (326) hide show
  1. package/.claude/skills/urlcode-authoring/SKILL.md +106 -0
  2. package/.claude/skills/urlcode-operations/SKILL.md +114 -0
  3. package/.claude-plugin/marketplace.json +18 -0
  4. package/CONTRIBUTING.md +30 -2
  5. package/README.md +157 -230
  6. package/ROADMAP.md +85 -2
  7. package/SECURITY.md +8 -1
  8. package/dist/BUILD-MANIFEST.json +62 -32
  9. package/dist/adapters.js +4 -23
  10. package/dist/agent-lists.js +1 -1
  11. package/dist/agents-guide.js +113 -0
  12. package/dist/authoring-files.js +60 -0
  13. package/dist/authoring.js +11 -1
  14. package/dist/aws.js +4 -3
  15. package/dist/build-cloudflare.js +11 -24
  16. package/dist/bulk.js +37 -0
  17. package/dist/capabilities.js +208 -0
  18. package/dist/capability-query.js +72 -0
  19. package/dist/catalog.js +105 -0
  20. package/dist/cli.js +154 -15
  21. package/dist/client-address.js +1 -1
  22. package/dist/compliance-rules/baseline.js +8 -8
  23. package/dist/compliance-rules/privacy.js +3 -3
  24. package/dist/compliance-rules/strict.js +5 -5
  25. package/dist/conditions.js +88 -0
  26. package/dist/config.js +60 -4
  27. package/dist/context.js +156 -0
  28. package/dist/ecosystem-cli.js +88 -0
  29. package/dist/egress.js +98 -0
  30. package/dist/examples.js +92 -0
  31. package/dist/explain-cli.js +64 -0
  32. package/dist/explain.js +132 -0
  33. package/dist/extensions.js +172 -0
  34. package/dist/function-sources.js +15 -3
  35. package/dist/index.js +37 -0
  36. package/dist/init-with.js +165 -0
  37. package/dist/interchange-cli.js +42 -0
  38. package/dist/interchange.js +189 -0
  39. package/dist/link-cli.js +1 -1
  40. package/dist/management-policy.js +0 -1
  41. package/dist/manifest.js +111 -0
  42. package/dist/match.js +2 -2
  43. package/dist/mcp-authoring.js +147 -0
  44. package/dist/mcp.js +97 -0
  45. package/dist/observability.js +6 -0
  46. package/dist/operator-host.js +29 -0
  47. package/dist/plugins.js +12 -0
  48. package/dist/policies/agents.js +2 -2
  49. package/dist/policies/compression.js +2 -1
  50. package/dist/policies/security.js +0 -0
  51. package/dist/policies.js +1 -1
  52. package/dist/policy.js +29 -7
  53. package/dist/prerender.js +100 -41
  54. package/dist/project-tests.js +3 -3
  55. package/dist/provider-verification.js +92 -0
  56. package/dist/proxy.js +44 -0
  57. package/dist/readiness.js +5 -5
  58. package/dist/recipes.js +41 -0
  59. package/dist/route-diff.js +106 -0
  60. package/dist/router.js +42 -2
  61. package/dist/runtime.js +95 -14
  62. package/dist/schema-query.js +62 -0
  63. package/dist/signals.js +24 -0
  64. package/dist/site.js +0 -0
  65. package/dist/tooling.js +96 -0
  66. package/dist/types/adapters.d.ts +7 -4
  67. package/dist/types/agent-lists.d.ts +0 -1
  68. package/dist/types/agents-guide.d.ts +17 -0
  69. package/dist/types/authoring-files.d.ts +10 -0
  70. package/dist/types/aws.d.ts +3 -1
  71. package/dist/types/build-cloudflare.d.ts +1 -0
  72. package/dist/types/bulk.d.ts +27 -0
  73. package/dist/types/capabilities.d.ts +55 -0
  74. package/dist/types/capability-query.d.ts +24 -0
  75. package/dist/types/catalog.d.ts +65 -0
  76. package/dist/types/client-address.d.ts +0 -1
  77. package/dist/types/compliance-rules/baseline.d.ts +1 -9
  78. package/dist/types/compliance-rules/privacy.d.ts +1 -4
  79. package/dist/types/compliance-rules/strict.d.ts +0 -5
  80. package/dist/types/conditions.d.ts +19 -0
  81. package/dist/types/config.d.ts +20 -2
  82. package/dist/types/context.d.ts +65 -0
  83. package/dist/types/ecosystem-cli.d.ts +17 -0
  84. package/dist/types/egress.d.ts +46 -0
  85. package/dist/types/examples.d.ts +50 -0
  86. package/dist/types/explain-cli.d.ts +11 -0
  87. package/dist/types/explain.d.ts +95 -0
  88. package/dist/types/extensions.d.ts +122 -0
  89. package/dist/types/function-sources.d.ts +5 -0
  90. package/dist/types/index.d.ts +33 -0
  91. package/dist/types/init-with.d.ts +30 -0
  92. package/dist/types/interchange-cli.d.ts +16 -0
  93. package/dist/types/interchange.d.ts +42 -0
  94. package/dist/types/link-cli.d.ts +2 -1
  95. package/dist/types/management-policy.d.ts +0 -1
  96. package/dist/types/manifest.d.ts +81 -0
  97. package/dist/types/match.d.ts +1 -0
  98. package/dist/types/mcp-authoring.d.ts +92 -0
  99. package/dist/types/mcp.d.ts +12 -0
  100. package/dist/types/observability.d.ts +2 -0
  101. package/dist/types/operator-host.d.ts +8 -0
  102. package/dist/types/plugins.d.ts +2 -0
  103. package/dist/types/policies/agents.d.ts +0 -2
  104. package/dist/types/policies/compression.d.ts +2 -0
  105. package/dist/types/policies/security.d.ts +0 -1
  106. package/dist/types/policy.d.ts +15 -4
  107. package/dist/types/project-tests.d.ts +3 -1
  108. package/dist/types/provider-verification.d.ts +53 -0
  109. package/dist/types/proxy.d.ts +21 -0
  110. package/dist/types/readiness.d.ts +1 -1
  111. package/dist/types/recipes.d.ts +30 -0
  112. package/dist/types/route-diff.d.ts +27 -0
  113. package/dist/types/runtime.d.ts +11 -0
  114. package/dist/types/schema-query.d.ts +12 -0
  115. package/dist/types/signals.d.ts +25 -0
  116. package/dist/types/site.d.ts +0 -1
  117. package/dist/types/tooling.d.ts +115 -0
  118. package/dist/types/types.d.ts +57 -0
  119. package/dist/types/typescript-authoring.d.ts +12 -0
  120. package/dist/types/vercel.d.ts +3 -1
  121. package/dist/types/verify-deployment.d.ts +47 -0
  122. package/dist/types.js +21 -2
  123. package/dist/typescript-authoring.js +104 -0
  124. package/dist/vercel.js +4 -3
  125. package/dist/verify-deployment.js +270 -0
  126. package/docs/AI-AUTHORING.md +130 -8
  127. package/docs/BULK.md +79 -0
  128. package/docs/CAPABILITIES.md +179 -0
  129. package/docs/CAPACITY.md +1 -1
  130. package/docs/CI.md +142 -0
  131. package/docs/CONDITIONS.md +74 -0
  132. package/docs/DEPLOYMENT-CHECKS.md +108 -0
  133. package/docs/DYNAMIC-LINKS.md +18 -518
  134. package/docs/EGRESS.md +125 -0
  135. package/docs/EXTENSIONS.md +226 -0
  136. package/docs/FRAMEWORK.md +182 -0
  137. package/docs/INSTALL.md +45 -7
  138. package/docs/INTERCHANGE.md +134 -0
  139. package/docs/MIDDLEWARE-EXAMPLES.md +75 -0
  140. package/docs/MIDDLEWARE.md +2 -0
  141. package/docs/NEXT-PHASE-PLAN.md +90 -0
  142. package/docs/NEXT-STEPS.md +415 -0
  143. package/docs/OBSERVABILITY.md +4 -2
  144. package/docs/OPERATIONAL-PROOF.md +4 -1
  145. package/docs/OPERATIONS.md +6 -3
  146. package/docs/PLUGINS.md +37 -0
  147. package/docs/POLICIES.md +12 -309
  148. package/docs/PRERENDER.md +40 -0
  149. package/docs/PROJECT-DIRECTION.md +42 -0
  150. package/docs/PROVIDER-VERIFICATION.md +84 -0
  151. package/docs/READINESS.md +21 -1
  152. package/docs/README.md +82 -31
  153. package/docs/RECIPES.md +99 -0
  154. package/docs/RELEASE-READINESS.md +11 -9
  155. package/docs/RELEASE-SECURITY.md +27 -4
  156. package/docs/SECURITY-AUDIT.md +1 -1
  157. package/docs/SPECIFICATION.md +95 -8
  158. package/docs/SPIKE-BUSINESS-SUITE.md +1013 -0
  159. package/docs/SPIKE-EXTENSION-MODEL.md +419 -0
  160. package/docs/SPIKE-EXTENSIONS.md +1 -0
  161. package/docs/SPIKE-LAMBDA-COMPILE.md +199 -0
  162. package/docs/STANDARDS.md +150 -142
  163. package/docs/STARTERS.md +21 -1
  164. package/docs/TOOLING.md +291 -0
  165. package/docs/TYPESCRIPT-AUTHORING.md +67 -0
  166. package/docs/TYPESCRIPT.md +1 -1
  167. package/docs/USABILITY-REVIEW.md +123 -0
  168. package/docs/YAML-GUIDE.md +18 -479
  169. package/docs/YAML-REFERENCE.md +127 -16
  170. package/docs/links/cli.md +110 -0
  171. package/docs/links/limits.md +175 -0
  172. package/docs/links/management-api.md +80 -0
  173. package/docs/links/pools.md +75 -0
  174. package/docs/links/setup.md +135 -0
  175. package/docs/policies/agents.md +1 -1
  176. package/docs/policies/contract.md +52 -0
  177. package/docs/policies/hardened.md +56 -0
  178. package/docs/policies/interoperability.md +169 -0
  179. package/docs/policies/operations.md +45 -0
  180. package/docs/yaml/assets.md +36 -0
  181. package/docs/yaml/conditions.md +20 -0
  182. package/docs/yaml/functions.md +160 -0
  183. package/docs/yaml/links.md +30 -0
  184. package/docs/yaml/middleware.md +29 -0
  185. package/docs/yaml/organization.md +74 -0
  186. package/docs/yaml/policies.md +37 -0
  187. package/docs/yaml/redirects.md +64 -0
  188. package/docs/yaml/responses.md +57 -0
  189. package/docs/yaml/site.md +24 -0
  190. package/examples/assets/example.yaml +17 -0
  191. package/examples/aws/example.yaml +20 -0
  192. package/examples/cloudflare/example.yaml +19 -0
  193. package/examples/compliance/example.yaml +11 -0
  194. package/examples/conditions/README.md +12 -0
  195. package/examples/conditions/example.yaml +19 -0
  196. package/examples/conditions/tests/requests.json +13 -0
  197. package/examples/conditions/urlcode.yaml +24 -0
  198. package/examples/cookbook/README.md +8 -4
  199. package/examples/cookbook/example.yaml +17 -0
  200. package/examples/cookbook/functions/catalog.mjs +3 -0
  201. package/examples/cookbook/functions/fail.mjs +4 -0
  202. package/examples/cookbook/functions/items.mjs +3 -0
  203. package/examples/cookbook/functions/profile.mjs +3 -0
  204. package/examples/cookbook/functions/resource.mjs +3 -0
  205. package/examples/cookbook/functions/status.mjs +3 -0
  206. package/examples/cookbook/middleware/auth.mjs +48 -0
  207. package/examples/cookbook/middleware/body.mjs +15 -0
  208. package/examples/cookbook/middleware/bucket.mjs +19 -0
  209. package/examples/cookbook/middleware/cors.mjs +21 -0
  210. package/examples/cookbook/middleware/debug.mjs +13 -0
  211. package/examples/cookbook/middleware/envelope.mjs +11 -0
  212. package/examples/cookbook/middleware/errors.mjs +11 -0
  213. package/examples/cookbook/middleware/etag.mjs +18 -0
  214. package/examples/cookbook/middleware/locale.mjs +16 -0
  215. package/examples/cookbook/middleware/maintenance.mjs +10 -0
  216. package/examples/cookbook/middleware/methods.mjs +15 -0
  217. package/examples/cookbook/middleware/negotiate.mjs +20 -0
  218. package/examples/cookbook/middleware/referer.mjs +12 -0
  219. package/examples/cookbook/middleware/request-id.mjs +16 -0
  220. package/examples/cookbook/route-index.json +676 -0
  221. package/examples/cookbook/routes/middleware.yaml +126 -0
  222. package/examples/cookbook/tests/requests.json +526 -0
  223. package/examples/cookbook/urlcode.yaml +1 -0
  224. package/examples/egress/README.md +22 -0
  225. package/examples/egress/example.yaml +19 -0
  226. package/examples/egress/urlcode.yaml +19 -0
  227. package/examples/extensions/README.md +7 -0
  228. package/examples/extensions/example.yaml +21 -0
  229. package/examples/extensions/urlcode.yaml +25 -0
  230. package/examples/live-links/example.yaml +21 -0
  231. package/examples/monitoring/example.yaml +8 -0
  232. package/examples/prerender/example.yaml +16 -0
  233. package/examples/provider-conformance/README.md +12 -0
  234. package/examples/provider-conformance/example.yaml +14 -0
  235. package/examples/provider-conformance/urlcode.yaml +34 -0
  236. package/examples/tunnel/example.yaml +8 -0
  237. package/examples/vercel/example.yaml +19 -0
  238. package/llms-full.txt +2709 -0
  239. package/llms.txt +48 -19
  240. package/package.json +29 -7
  241. package/packaging/claude-plugin/.claude-plugin/plugin.json +19 -0
  242. package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +106 -0
  243. package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +114 -0
  244. package/recipes/authenticated-json-api/README.md +51 -0
  245. package/recipes/authenticated-json-api/functions/profile.mjs +5 -0
  246. package/recipes/authenticated-json-api/recipe.yaml +34 -0
  247. package/recipes/authenticated-json-api/tests/requests.json +39 -0
  248. package/recipes/authenticated-json-api/urlcode.yaml +12 -0
  249. package/recipes/contact-form/README.md +25 -0
  250. package/recipes/contact-form/functions/contact.mjs +17 -0
  251. package/recipes/contact-form/recipe.yaml +33 -0
  252. package/recipes/contact-form/tests/requests.json +47 -0
  253. package/recipes/contact-form/urlcode.yaml +18 -0
  254. package/recipes/cors-api/README.md +16 -0
  255. package/recipes/cors-api/functions/items.mjs +3 -0
  256. package/recipes/cors-api/middleware/cors.mjs +21 -0
  257. package/recipes/cors-api/recipe.yaml +26 -0
  258. package/recipes/cors-api/tests/requests.json +65 -0
  259. package/recipes/cors-api/urlcode.yaml +12 -0
  260. package/recipes/health-page/README.md +13 -0
  261. package/recipes/health-page/recipe.yaml +23 -0
  262. package/recipes/health-page/tests/requests.json +36 -0
  263. package/recipes/health-page/urlcode.yaml +19 -0
  264. package/recipes/json-api/README.md +6 -0
  265. package/recipes/json-api/functions/echo.mjs +3 -0
  266. package/recipes/json-api/recipe.yaml +25 -0
  267. package/recipes/json-api/tests/requests.json +34 -0
  268. package/recipes/json-api/urlcode.yaml +12 -0
  269. package/recipes/middleware/README.md +34 -0
  270. package/recipes/middleware/functions/catalog.mjs +3 -0
  271. package/recipes/middleware/functions/fail.mjs +4 -0
  272. package/recipes/middleware/functions/items.mjs +3 -0
  273. package/recipes/middleware/functions/profile.mjs +3 -0
  274. package/recipes/middleware/functions/resource.mjs +3 -0
  275. package/recipes/middleware/functions/status.mjs +3 -0
  276. package/recipes/middleware/middleware/auth.mjs +48 -0
  277. package/recipes/middleware/middleware/body.mjs +15 -0
  278. package/recipes/middleware/middleware/bucket.mjs +19 -0
  279. package/recipes/middleware/middleware/cors.mjs +21 -0
  280. package/recipes/middleware/middleware/debug.mjs +13 -0
  281. package/recipes/middleware/middleware/envelope.mjs +11 -0
  282. package/recipes/middleware/middleware/errors.mjs +11 -0
  283. package/recipes/middleware/middleware/etag.mjs +18 -0
  284. package/recipes/middleware/middleware/locale.mjs +16 -0
  285. package/recipes/middleware/middleware/maintenance.mjs +10 -0
  286. package/recipes/middleware/middleware/methods.mjs +15 -0
  287. package/recipes/middleware/middleware/negotiate.mjs +20 -0
  288. package/recipes/middleware/middleware/referer.mjs +12 -0
  289. package/recipes/middleware/middleware/request-id.mjs +16 -0
  290. package/recipes/middleware/public/guide.txt +1 -0
  291. package/recipes/middleware/recipe.yaml +50 -0
  292. package/recipes/middleware/tests/requests.json +528 -0
  293. package/recipes/middleware/urlcode.yaml +127 -0
  294. package/recipes/protected-download/README.md +22 -0
  295. package/recipes/protected-download/files/report.txt +1 -0
  296. package/recipes/protected-download/recipe.yaml +31 -0
  297. package/recipes/protected-download/tests/requests.json +32 -0
  298. package/recipes/protected-download/urlcode.yaml +15 -0
  299. package/recipes/redirect/README.md +7 -0
  300. package/recipes/redirect/recipe.yaml +25 -0
  301. package/recipes/redirect/tests/requests.json +19 -0
  302. package/recipes/redirect/urlcode.yaml +9 -0
  303. package/recipes/static-plus-api/README.md +15 -0
  304. package/recipes/static-plus-api/functions/info.mjs +3 -0
  305. package/recipes/static-plus-api/public/assets/index.html +3 -0
  306. package/recipes/static-plus-api/public/assets/site.css +1 -0
  307. package/recipes/static-plus-api/public/index.html +8 -0
  308. package/recipes/static-plus-api/recipe.yaml +29 -0
  309. package/recipes/static-plus-api/tests/requests.json +56 -0
  310. package/recipes/static-plus-api/urlcode.yaml +23 -0
  311. package/recipes/typescript/README.md +7 -0
  312. package/recipes/typescript/functions/hello.ts +5 -0
  313. package/recipes/typescript/recipe.yaml +23 -0
  314. package/recipes/typescript/tests/requests.json +18 -0
  315. package/recipes/typescript/urlcode.yaml +5 -0
  316. package/recipes/webhook-receiver/README.md +16 -0
  317. package/recipes/webhook-receiver/functions/receive.mjs +16 -0
  318. package/recipes/webhook-receiver/recipe.yaml +26 -0
  319. package/recipes/webhook-receiver/tests/requests.json +59 -0
  320. package/recipes/webhook-receiver/urlcode.yaml +16 -0
  321. package/schemas/recipe.schema.json +138 -0
  322. package/schemas/urlcode.schema.json +656 -80
  323. package/skills/urlcode/SKILL.md +98 -0
  324. package/starters/default/.github/workflows/urlcode.yml +23 -0
  325. package/starters/default/.mcp.json +12 -0
  326. package/starters/default/AGENTS.md +79 -0
@@ -0,0 +1,96 @@
1
+ import {loadDocument} from './config.js';
2
+ import {applySite} from './site.js';
3
+ import {prepareFunctionSnapshot,requestedPermissions} from './policy.js';
4
+ import {compileRoutes,matchRoute,parseTarget} from './router.js';
5
+ import {compilePolicies,closePolicies} from './policies.js';
6
+ import {analyzeCompiledCapabilities,routeCapabilities} from './capabilities.js';
7
+
8
+ import {importRoutes,exportRoutes} from './interchange.js';
9
+
10
+ import {listRecipes,showRecipe,searchRecipes} from './recipes.js';
11
+ import {listExamples,searchExamples} from './examples.js';
12
+
13
+ import {effectiveExtensionPolicies} from './extensions.js';
14
+
15
+ import {loadOperatorHost} from './operator-host.js';
16
+ import {explainCompiledRoute,nearestRoutes} from './explain.js';
17
+
18
+ export {getCapabilities} from './capabilities.js';
19
+ export {getCapability} from './capability-query.js';
20
+
21
+ export {getSchemaFragment,schemaPathNames} from './schema-query.js';
22
+
23
+ export {listRecipes,showRecipe,searchRecipes,listExamples,searchExamples};
24
+ export {buildContext,renderContext,estimateTokens,documentationTokens} from './context.js';
25
+
26
+
27
+ /** `extensions` are operator registrations from a host file; explain reports whether each requirement has a provider. Nothing is activated. */
28
+
29
+ function routesOf(table ) {return [...table.exact.values(),...[...table.byLength.values()].flat(),...table.mounts];}
30
+ export async function prepare(project ,options ={}) {
31
+ const loaded=await loadDocument(project);await applySite(loaded,{...(options.origin?{origin:options.origin}:{})});
32
+ const snapshot=await prepareFunctionSnapshot(loaded),bindings =Object.create(null);
33
+ for(const route of Object.values(loaded.routes)) {for(const ref of Object.values(route.env||{}))if(ref.env)bindings[ref.env]='validation-only';for(const ref of Object.values(route.secrets||{}))bindings[ref.secret]='validation-only';}
34
+ const compiled=await compileRoutes(loaded,bindings,requestedPermissions(loaded,snapshot),snapshot.projectSha256),routes=routesOf(compiled);
35
+ const shared ={target:'node',routes:routes.length,log:()=>{}};
36
+ // The same policy inventory the runtime attaches (src/runtime.ts): compiled for every route when the project declares any.
37
+ const anyPolicy=Boolean(loaded.document.policies)||routes.some(route=>route.policies),chains=new Map ();
38
+ try {for(const route of routes){const chain=await compilePolicies(loaded.document,route,{route,shared,target:'node',root:loaded.root});if(anyPolicy)chains.set(route.pattern,chain);}}finally{await closePolicies(shared);}
39
+ return {loaded,compiled,routes,chains,projectSha256:snapshot.projectSha256};
40
+ }
41
+ function compatibilitySummary(report ) {return {target:report.target,compatible:report.compatible,deployment:report.deployment,requirementCount:report.requirements.length,issueCount:report.issues.length};}
42
+ /** Semantic authoring inspection; no binding reads, sandbox execution or runtime activation. */
43
+ export async function inspectProject(project ,options ={}) {
44
+ const offset=options.offset??0,limit=options.limit??100;
45
+ if(!Number.isSafeInteger(offset)||offset<0||!Number.isSafeInteger(limit)||limit<1||limit>1000)throw new Error('Invalid inspection page');
46
+ const {loaded,compiled,routes,projectSha256}=await prepare(project,options);
47
+ const report=analyzeCompiledCapabilities(loaded.document,compiled,options.target??'self-hosted');
48
+ return {format:1,projectSha256,routeCount:compiled.count,offset,limit,routes:routes.slice(offset,offset+limit).map(route=>({path:route.pattern,methods:route.methods,enabled:route.enabled!==false,capabilities:routeCapabilities(route,loaded.document)})),compatibility:{...compatibilitySummary(report),offset,limit,hasMore:offset+limit<report.issues.length,issues:report.issues.slice(offset,offset+limit)}};
49
+ }
50
+ export async function validateProject(project ,options ={}) {
51
+ const result=await inspectProject(project,{...options,offset:0,limit:1});
52
+ const {target,compatible,deployment,requirementCount,issueCount,issues}=result.compatibility;
53
+ return {valid:true,projectSha256:result.projectSha256,routeCount:result.routeCount,compatibility:{target,compatible,deployment,requirementCount,issueCount,firstIssue:issues[0]??null}};
54
+ }
55
+
56
+ /** Explain the route a path selects from the compiled IR: effective methods, handler, middleware, inputs, policies, cache outcome, bindings and target support. Nothing executes and no binding is read. */
57
+ export async function explainRoute(project ,target ,options ={}) {
58
+ const {loaded,compiled,chains,projectSha256}=await prepare(project,options),match=matchRoute(compiled,parseTarget(target));
59
+ if(!match)return {matched:false,nearest:nearestRoutes(target,routesOf(compiled).map(route=>route.pattern)),note:'No route selects this path.'};
60
+ return explainCompiledRoute(loaded,match.route,chains.get(match.route.pattern),{extensions:options.extensions,projectSha256});
61
+ }
62
+ /** Every route's explanation, in the router's precedence order. */
63
+ export async function explainProject(project ,options ={}) {
64
+ const {loaded,routes,chains,projectSha256}=await prepare(project,options);
65
+ return {projectSha256,routeCount:routes.length,routes:routes.map(route=>explainCompiledRoute(loaded,route,chains.get(route.pattern),{extensions:options.extensions,projectSha256}))};
66
+ }
67
+ export async function previewImport(options ) {return importRoutes(options);}
68
+ export async function previewExport(project ,format ,acceptProviderDifferences=false) {const loaded=await loadDocument(project);const {includes:_includes,...document}=loaded.document;return exportRoutes({format,document:{...document,routes:loaded.routes},acceptProviderDifferences});}
69
+
70
+
71
+
72
+
73
+
74
+ /** Reports registered extension contracts against the project's declarations. Never activates an extension. */
75
+ export async function describeExtensions(project ,registrations ) {
76
+ const loaded=await loadDocument(project),{projectSha256}=await prepareFunctionSnapshot(loaded),routes=Object.entries(loaded.routes);
77
+ const declarations=Object.entries(loaded.document.extensions??{});
78
+ const mountsOf=(name )=>routes.filter(([,route])=>route.extension===name).map(([path])=>path.endsWith('/*')?path.slice(0,-2):path);
79
+ const policyRoutesOf=(name )=>routes.filter(([,route])=>Object.hasOwn(effectiveExtensionPolicies(loaded.document,route),name)).map(([path])=>path);
80
+ const registered=new Set((registrations??[]).map(registration=>registration.name));
81
+ const declared=declarations.map(([name,declaration])=>({name,version:String(declaration.version),registered:registered.has(name),mounts:mountsOf(name),policyRoutes:policyRoutesOf(name)}));
82
+ if(registrations===undefined)return {format:1,projectSha256,hostLoaded:false,note:'Configuration and policy schemas come from the operator host file; supply --host-file to print them.',extensions:[],declared};
83
+ const extensions=registrations.map(registration=>({
84
+ name:String(registration.name),version:String(registration.version),targets:Array.isArray(registration.targets)?registration.targets.map(String):[],
85
+ credentialHeaders:Array.isArray(registration.credentialHeaders)?registration.credentialHeaders.map(String):[],
86
+ schema:structuredClone(registration.schema??{}),policySchema:registration.policySchema?structuredClone(registration.policySchema):null,
87
+ declared:Object.hasOwn(loaded.document.extensions??{},registration.name),revisionPinned:registration.projectSha256===projectSha256,
88
+ mounts:mountsOf(registration.name),policyRoutes:policyRoutesOf(registration.name),
89
+ }));
90
+ return {format:1,projectSha256,hostLoaded:true,note:'Schemas describe operator-installed contracts; inspection activates nothing and grants no revision.',extensions,declared};
91
+ }
92
+ /** Executes the trusted operator host file to read its registrations, then releases it. */
93
+ export async function inspectExtensions(options ) {
94
+ const host=await loadOperatorHost(options.hostFile,options.project);
95
+ try{return await describeExtensions(options.project,options.hostFile===undefined?undefined:host.extensions??[]);}finally{await host.close?.();}
96
+ }
@@ -1,12 +1,15 @@
1
+ import type { RuntimeExtension } from './extensions.ts';
1
2
  import type { HostPlugin, OperatorPolicy, Runtime } from './runtime.ts';
2
- import type { TargetName } from './types.ts';
3
3
  /** The subset of process.env a hosted adapter reads. */
4
4
  export type Environment = Record<string, string | undefined>;
5
- export interface NativeOnlyOptions {
6
- target?: TargetName | undefined;
5
+ interface NativeOnlyOptions {
6
+ target: 'aws' | 'vercel';
7
7
  plugins?: HostPlugin[] | undefined;
8
+ extensions?: RuntimeExtension[] | undefined;
9
+ origin?: string | undefined;
8
10
  }
9
11
  export declare function readPolicyFromEnvironment(environment: Environment): OperatorPolicy | undefined;
10
- export declare function activateNativeOnly(project: string, environment: Environment, { target, plugins }?: NativeOnlyOptions): Promise<Runtime>;
12
+ export declare function activateNativeOnly(project: string, environment: Environment, { target, plugins, extensions, origin }: NativeOnlyOptions): Promise<Runtime>;
11
13
  export declare function lazyRuntime<T>(activate: () => Promise<T>): () => Promise<T>;
12
14
  export declare function resolveOrigin(origin: string | undefined, environment: Environment, platformVariables: string[]): string | undefined;
15
+ export {};
@@ -1,5 +1,4 @@
1
1
  import type { AgentEntry, AgentsConfig } from './policies/agents.ts';
2
- export declare const MAX_LIST_ENTRIES = 4096;
3
2
  export declare function loadListFile(root: string, reference: string, routePattern?: string): Promise<AgentEntry[]>;
4
3
  export declare function loadListFiles(references: string[], root: string | undefined, routePattern: string): Promise<Record<string, AgentEntry[]>>;
5
4
  export declare function resolveLists(config: AgentsConfig | undefined, root: string, routePattern?: string): Promise<AgentsConfig | undefined>;
@@ -0,0 +1,17 @@
1
+ /** Where the packaged agent skill lives, relative to the installed @jimhoyd/urlcode package. */
2
+ export declare const skillPath = "skills/urlcode/SKILL.md";
3
+ /** The MCP registration file `urlcode init` writes beside the project (Claude Code and Codex read this shape). */
4
+ export declare const mcpConfigFile = ".mcp.json";
5
+ /**
6
+ * Renders `.mcp.json` registering the read-only `urlcode mcp` server for the project at `project`, relative
7
+ * to the file. `--allow-authoring` is deliberately absent: the operator adds it by hand when they want it.
8
+ */
9
+ export declare function renderMcpConfig(project?: string): string;
10
+ /**
11
+ * The application-level AGENTS.md written by `urlcode init`. Built from the
12
+ * installed runtime's capability catalog, so it names only the handlers,
13
+ * policies and site keys this version implements. Under 80 lines by design.
14
+ */
15
+ export declare function renderAgentsGuide({ routes }: {
16
+ routes: number;
17
+ }): string;
@@ -0,0 +1,10 @@
1
+ /** Authoring output never copies hidden state, package hooks, or credential files. */
2
+ export declare function authoringPath(path: string): string;
3
+ export declare function authoringFile(root: string, path: string, directory?: boolean): Promise<string>;
4
+ export declare function readAuthoringFile(root: string, path: string, limit: number): Promise<Buffer>;
5
+ /** Reserve a fresh directory exclusively, then publish the entry config last.
6
+ * Failed writes remove only the directory created by this invocation. No existing
7
+ * directory (even an empty one) is accepted; consumers see no activatable project
8
+ * until every dependency has been written. Callers must own the output parent.
9
+ */
10
+ export declare function publishAuthoringProject(output: string, files: ReadonlyMap<string, Buffer | string>, dryRun?: boolean): Promise<string>;
@@ -1,3 +1,4 @@
1
+ import type { RuntimeExtension } from './extensions.ts';
1
2
  import type { Environment } from './adapters.ts';
2
3
  import type { HostPlugin } from './runtime.ts';
3
4
  export interface LambdaHandlerOptions {
@@ -6,6 +7,7 @@ export interface LambdaHandlerOptions {
6
7
  environment?: Environment | undefined;
7
8
  maxBodyBytes?: number | undefined;
8
9
  plugins?: HostPlugin[] | undefined;
10
+ extensions?: RuntimeExtension[] | undefined;
9
11
  }
10
12
  /** A Lambda payload format 2.0 event, as far as this adapter reads it. */
11
13
  export interface LambdaEvent {
@@ -32,4 +34,4 @@ export interface LambdaResponse {
32
34
  isBase64Encoded: true;
33
35
  }
34
36
  export type LambdaHandler = (event: unknown) => Promise<LambdaResponse>;
35
- export declare function createLambdaHandler({ project, origin, environment, maxBodyBytes, plugins }?: LambdaHandlerOptions): LambdaHandler;
37
+ export declare function createLambdaHandler({ project, origin, environment, maxBodyBytes, plugins, extensions }?: LambdaHandlerOptions): LambdaHandler;
@@ -10,5 +10,6 @@ export interface BuildReport {
10
10
  version: string;
11
11
  routes: number;
12
12
  validators: number;
13
+ manifest: string;
13
14
  }
14
15
  export declare function buildCloudflare(project: string, { out, origin, log }?: BuildOptions): Promise<BuildReport>;
@@ -0,0 +1,27 @@
1
+ import type { ConversionDiagnostic } from './interchange.ts';
2
+ export type BulkFormat = 'csv' | 'json' | 'yaml';
3
+ export interface BulkFilePlan {
4
+ path: string;
5
+ routeCount: number;
6
+ firstPath?: string;
7
+ lastPath?: string;
8
+ }
9
+ export interface BulkImportReport {
10
+ ok: boolean;
11
+ dryRun: boolean;
12
+ output?: string;
13
+ routeCount: number;
14
+ diagnostics: ConversionDiagnostic[];
15
+ files: BulkFilePlan[];
16
+ source: {
17
+ name: string;
18
+ format: BulkFormat;
19
+ sha256: string;
20
+ };
21
+ }
22
+ /** Import ordinary redirect rows into small, portable include files. There is no
23
+ * merge mode: duplicate rules and existing output directories are refused. */
24
+ export declare function importBulkProject(text: string, format: BulkFormat, output: string, { dryRun, source }?: {
25
+ dryRun?: boolean | undefined;
26
+ source?: string | undefined;
27
+ }): Promise<BulkImportReport>;
@@ -0,0 +1,55 @@
1
+ import type { CompiledRoute, CompiledRouteTable, LoadedDocument, PolicySupport, ProjectDocument, RouteConfig } from './types.ts';
2
+ export declare const capabilityTargets: readonly ["self-hosted", "cloudflare", "aws", "vercel"];
3
+ export type CapabilityTarget = typeof capabilityTargets[number];
4
+ export type CapabilitySupport = PolicySupport | 'conditional' | 'unknown';
5
+ export declare const capabilityNames: readonly ["extension", "policies.extensions", "proxy", "signals", "conditional", "conditions", "redirect", "respond", "page", "static", "download", "function", "middleware", "link", "dynamicLinks", "parameters", "methods", "enabled", "expires", "request.body", "response.headers", "bindings", "policies.agents", "policies.security", "policies.cache", "policies.compression", "policies.throttle"];
6
+ export type CapabilityName = typeof capabilityNames[number];
7
+ export interface CapabilityDecision {
8
+ support: CapabilitySupport;
9
+ reason: string;
10
+ }
11
+ export interface CapabilityRequirement extends CapabilityDecision {
12
+ path: string;
13
+ capability: CapabilityName;
14
+ }
15
+ export interface CompatibilityReport {
16
+ target: CapabilityTarget;
17
+ compatible: boolean;
18
+ requirements: CapabilityRequirement[];
19
+ issues: CapabilityRequirement[];
20
+ deployment: 'local-runtime' | 'unverified';
21
+ }
22
+ export interface CapabilityCatalog {
23
+ format: 1;
24
+ targets: {
25
+ target: CapabilityTarget;
26
+ deployment: CompatibilityReport['deployment'];
27
+ }[];
28
+ capabilities: {
29
+ capability: CapabilityName;
30
+ targets: Partial<Record<CapabilityTarget, CapabilityDecision>>;
31
+ }[];
32
+ }
33
+ export declare function normalizeCapabilityTarget(target: string): CapabilityTarget;
34
+ /** Catalog, not a claim that every configuration or provider deployment works. */
35
+ export declare function getCapabilities(target?: string): CapabilityCatalog;
36
+ /** A safe projection shared by declaration preflight and the existing compiled IR. No values escape. */
37
+ export declare function routeCapabilities(route: RouteConfig | CompiledRoute, document: ProjectDocument): CapabilityName[];
38
+ /** Preflight only: call after schema validation/site expansion, before resolving bindings. */
39
+ export declare function analyzeProjectCapabilities(loaded: LoadedDocument, target: string): CompatibilityReport;
40
+ /** Analyze normalized route semantics without exporting validators, resources or resolved secrets. */
41
+ export declare function analyzeCompiledCapabilities(document: ProjectDocument, compiled: CompiledRouteTable, target: string): CompatibilityReport;
42
+ export declare function assertTargetCompatibility(report: CompatibilityReport): void;
43
+ export declare function formatCapabilities(catalog: CapabilityCatalog): string;
44
+ export type CapabilityKind = 'handler' | 'policy' | 'routing' | 'request' | 'binding' | 'egress' | 'middleware' | 'project';
45
+ export interface CapabilityDetail {
46
+ kind: CapabilityKind;
47
+ summary: string;
48
+ /** Dotted schema paths (`urlcode schema <path>`) whose fragments describe this capability's YAML. */
49
+ schema: string[];
50
+ constraints: string[];
51
+ /** Operator authority the capability needs at activation; never binding values. */
52
+ grants: string[];
53
+ }
54
+ /** Static facts about each catalog entry. Per-target support stays in `decision`; recipe and cookbook usage is scanned by `getCapability`. */
55
+ export declare const capabilityDetails: Record<CapabilityName, CapabilityDetail>;
@@ -0,0 +1,24 @@
1
+ import { formatCapabilities } from './capabilities.ts';
2
+ import type { CapabilityDecision, CapabilityDetail, CapabilityName, CapabilityTarget } from './capabilities.ts';
3
+ import type { SchemaFragment } from './schema-query.ts';
4
+ export interface CapabilityUsage {
5
+ file: string;
6
+ routes: string[];
7
+ }
8
+ export interface CapabilityEntry extends CapabilityDetail {
9
+ format: 1;
10
+ name: CapabilityName;
11
+ schemaFragments: SchemaFragment[];
12
+ targets: Record<CapabilityTarget, CapabilityDecision>;
13
+ refused: {
14
+ target: CapabilityTarget;
15
+ reason: string;
16
+ }[];
17
+ recipes: CapabilityUsage[];
18
+ cookbook: CapabilityUsage[];
19
+ }
20
+ export declare function capabilityNameList(): readonly CapabilityName[];
21
+ /** One catalog entry with its schema fragments and bundled usage. No project, credentials or network are read. */
22
+ export declare function getCapability(name: string): CapabilityEntry;
23
+ export declare function formatCapability(entry: CapabilityEntry): string;
24
+ export { formatCapabilities };
@@ -0,0 +1,65 @@
1
+ import type { CapabilityName, CapabilityTarget } from './capabilities.ts';
2
+ /**
3
+ * The metadata shape shared by recipes/NAME/recipe.yaml and examples/NAME/example.yaml
4
+ * (schemas/recipe.schema.json). The catalog entries are fixed package data: names
5
+ * come from a list in code, never from a directory scan, a registry or an argument.
6
+ */
7
+ export type TargetVerdict = 'compatible' | 'conditional' | 'refused' | 'unknown';
8
+ export type Complexity = 'starter' | 'intermediate' | 'advanced';
9
+ export interface CatalogMetadata {
10
+ id: string;
11
+ description: string;
12
+ tags: string[];
13
+ complexity: Complexity;
14
+ runnable?: boolean;
15
+ capabilities?: string[];
16
+ targets?: Record<CapabilityTarget, TargetVerdict>;
17
+ routes?: number;
18
+ services?: {
19
+ name: string;
20
+ description: string;
21
+ }[];
22
+ grants?: {
23
+ kind: string;
24
+ description: string;
25
+ }[];
26
+ inputs?: {
27
+ name: string;
28
+ file: string;
29
+ description: string;
30
+ }[];
31
+ files: string[];
32
+ tests?: {
33
+ fixtures?: string;
34
+ commands: string[];
35
+ };
36
+ behavior?: string[];
37
+ }
38
+ /** The fields the capability preflight determines; `npm run check` refuses hand-written values that differ. */
39
+ export interface DerivedMetadata {
40
+ capabilities: CapabilityName[];
41
+ targets: Record<CapabilityTarget, TargetVerdict>;
42
+ routes: number;
43
+ }
44
+ export interface SearchHit<T extends CatalogMetadata> {
45
+ entry: T;
46
+ score: number;
47
+ matched: string[];
48
+ }
49
+ export declare const metadataFiles: {
50
+ readonly recipe: "recipe.yaml";
51
+ readonly example: "example.yaml";
52
+ };
53
+ /** Reads and schema-validates one metadata file; the id must equal the directory name, and file lists stay authoring-safe paths. */
54
+ export declare function readMetadata(root: string, id: string, file: 'recipe.yaml' | 'example.yaml'): Promise<CatalogMetadata>;
55
+ /** Preflight only: loads the project, expands site routes and asks the capability analysis for every target. No bindings, code or activation. */
56
+ export declare function deriveMetadata(root: string): Promise<DerivedMetadata>;
57
+ /** Reports where hand-written derived fields disagree with the preflight; empty means consistent. */
58
+ export declare function derivedDifferences(metadata: CatalogMetadata, derived: DerivedMetadata): string[];
59
+ export declare function searchTerms(text: string): string[];
60
+ /**
61
+ * Local search over id, description, tags and capabilities: every term must match
62
+ * somewhere; the score prefers whole-tag and id hits over description substrings.
63
+ * Ties keep catalog order, so the smallest entry wins when a caller sorts by size first.
64
+ */
65
+ export declare function searchMetadata<T extends CatalogMetadata>(entries: readonly T[], text: string, extraText?: (entry: T) => string[]): SearchHit<T>[];
@@ -4,6 +4,5 @@ export interface Cidr {
4
4
  }
5
5
  export declare function parseCidr(text: string): Cidr;
6
6
  export declare function compileTrustedProxies(list?: string | string[]): Cidr[];
7
- export declare function isTrustedProxy(address: string, trusted: Cidr[]): boolean;
8
7
  export declare function resolveClient(peer: string | undefined, forwarded: string | undefined, trusted: Cidr[]): string | undefined;
9
8
  export declare function normalizeAddress(address: unknown): string | undefined;
@@ -1,12 +1,4 @@
1
- import type { ComplianceRule, ProjectRule, RouteRule } from '../compliance.ts';
1
+ import type { ComplianceRule, ProjectRule } from '../compliance.ts';
2
2
  export declare const profile = "baseline";
3
- export declare const securityHeaders: RouteRule;
4
- export declare const hstsOrigin: ProjectRule;
5
- export declare const secretsCompression: RouteRule;
6
- export declare const secretsNoStore: RouteRule;
7
- export declare const cacheControlDeclared: RouteRule;
8
- export declare const throttleFunctions: RouteRule;
9
3
  export declare const robots: ProjectRule;
10
- export declare const expiredRoutes: ProjectRule;
11
- export declare const managementPrivate: ProjectRule;
12
4
  export declare const rules: readonly ComplianceRule[];
@@ -1,6 +1,3 @@
1
- import type { ComplianceRule, ProjectRule, RouteRule } from '../compliance.ts';
1
+ import type { ComplianceRule } from '../compliance.ts';
2
2
  export declare const profile = "privacy";
3
- export declare const requestLogMinimal: ProjectRule;
4
- export declare const linkEventsOff: ProjectRule;
5
- export declare const detailedParameters: RouteRule;
6
3
  export declare const rules: readonly ComplianceRule[];
@@ -1,9 +1,4 @@
1
1
  import type { ComplianceRule, RouteRule } from '../compliance.ts';
2
2
  export declare const profile = "strict";
3
- export declare const headerBudgetBytes = 8192;
4
3
  export declare const csp: RouteRule;
5
- export declare const throttleAll: RouteRule;
6
- export declare const listsPinned: RouteRule;
7
- export declare const redirectHttps: RouteRule;
8
- export declare const headerBudget: RouteRule;
9
4
  export declare const rules: readonly ComplianceRule[];
@@ -0,0 +1,19 @@
1
+ /** Bounded conjunction of exact string comparisons; no regex or implicit detection. */
2
+ export interface RouteMatch {
3
+ query?: Record<string, string>;
4
+ headers?: Record<string, string>;
5
+ cookies?: Record<string, string>;
6
+ host?: string;
7
+ method?: string;
8
+ }
9
+ export interface ConditionRequest {
10
+ query: URLSearchParams;
11
+ headers: Headers;
12
+ method: string;
13
+ origin: string;
14
+ headerCounts?: Record<string, number> | undefined;
15
+ }
16
+ export declare function normalizeMatch(match: RouteMatch): RouteMatch;
17
+ /** Cases must be disjoint: at least one shared fact must demand different values. */
18
+ export declare function assertDisjointMatches(matches: RouteMatch[]): void;
19
+ export declare function matchesRoute(match: RouteMatch, request: ConditionRequest): boolean;
@@ -1,4 +1,4 @@
1
- import type { LoadedDocument, ProjectDocument } from './types.ts';
1
+ import type { AuthoredRouteConfig, LoadedDocument, ProjectDocument, RouteConfig } from './types.ts';
2
2
  /** What config-worker.ts posts back: the loaded document, or the ConfigError message. */
3
3
  export type ConfigWorkerResult = {
4
4
  value: LoadedDocument;
@@ -11,11 +11,29 @@ export interface ConfigWorkerData {
11
11
  export declare const MAX_CONFIG_BYTES: number;
12
12
  export declare function parseYaml(text: string): unknown;
13
13
  export declare function validateDocument(data: unknown): ProjectDocument;
14
+ /** The input declaration a short-form function gets for each `{param}` it does not declare itself. */
15
+ export declare const SHORT_FORM_PATH_SCHEMA: {
16
+ readonly type: "string";
17
+ readonly minLength: 1;
18
+ readonly maxLength: 128;
19
+ };
20
+ /**
21
+ * Expands the YAML short forms into the canonical long form. `function: functions/x.mjs`
22
+ * becomes `{source, args}` with an argument per `{param}` in the path, declaring any
23
+ * parameter the route does not declare itself; a string middleware entry becomes `{source}`.
24
+ * Everything downstream (routes, audit, the compiled table) sees only the long form.
25
+ */
26
+ export declare function normalizeRoute(pattern: string, route: AuthoredRouteConfig | RouteConfig): RouteConfig;
14
27
  export declare function safeFile(root: string, file: unknown): Promise<string>;
15
- export declare const MAX_PROJECT_CONFIG_BYTES: number;
16
28
  export declare function loadDocument(project: string, { timeoutMs }?: {
17
29
  timeoutMs?: number;
18
30
  }): Promise<LoadedDocument>;
31
+ /**
32
+ * Expands the route-level `auth` short form into the canonical `policies.extensions.auth` requirement so every
33
+ * downstream consumer (compiler, routes, audit, explain, revision hash) sees one form. `auth: {required: false}`
34
+ * documents intent and emits nothing. Refuses routes that use both forms or lack an `extensions.auth` declaration.
35
+ */
36
+ export declare function normalizeRouteAuth(document: Pick<ProjectDocument, 'extensions'>, routes: Record<string, RouteConfig>): void;
19
37
  export declare function loadDocumentInWorker(project: string): Promise<LoadedDocument>;
20
38
  export declare function loadBindings(root: string, local?: boolean, environment?: Record<string, string | undefined>): Promise<Record<string, string | undefined>>;
21
39
  export declare function functionFile(root: string, file: string): Promise<string>;
@@ -0,0 +1,65 @@
1
+ export interface ContextOptions {
2
+ /** Restrict the target table to one capability target. */
3
+ target?: string | undefined;
4
+ /** Absolute path to a trusted operator host module outside the project; its extensions and plugins are counted, never run. */
5
+ hostFile?: string | undefined;
6
+ /** Estimated token budget; sections are dropped in a fixed order until the YAML rendering fits. */
7
+ budget?: number | undefined;
8
+ /** What `--project` should say in the emitted commands; defaults to the project argument itself. */
9
+ projectFlag?: string | undefined;
10
+ }
11
+ export type ContextSection = 'routes' | 'targets' | 'constraintNotes' | 'files' | 'commands' | 'summary';
12
+ export interface ProjectContext {
13
+ urlcode: string;
14
+ schema: '1';
15
+ project: {
16
+ entry: string;
17
+ routes: number;
18
+ handlers: Record<string, number>;
19
+ extensions: string[];
20
+ policies: {
21
+ project: string[];
22
+ routes: Record<string, number>;
23
+ };
24
+ bindings: {
25
+ env: string[];
26
+ secrets: string[];
27
+ };
28
+ dynamicLinks: boolean;
29
+ site: string[];
30
+ files?: {
31
+ includes: string[];
32
+ functions: string[];
33
+ middleware: string[];
34
+ };
35
+ host?: {
36
+ extensions: string[];
37
+ plugins: number;
38
+ };
39
+ };
40
+ routes?: {
41
+ path: string;
42
+ methods: string[];
43
+ handler: string;
44
+ }[];
45
+ constraints: Record<string, boolean | string | {
46
+ value: boolean | string;
47
+ note: string;
48
+ }>;
49
+ targets?: Record<string, {
50
+ deployment: string;
51
+ supported: string[];
52
+ conditional: string[];
53
+ refused: string[];
54
+ unknown: string[];
55
+ }>;
56
+ commands?: Record<string, string>;
57
+ omitted?: ContextSection[];
58
+ }
59
+ /** Characters divided by four, rounded up: an estimate, not a tokenizer. */
60
+ export declare function estimateTokens(text: string): number;
61
+ export declare function renderContext(context: ProjectContext): string;
62
+ /** Derived only from the compiled project and the capability catalog, never from prose. Key order is fixed. */
63
+ export declare function buildContext(project: string, options?: ContextOptions): Promise<ProjectContext>;
64
+ /** Estimated size of the shipped documentation (docs/*.md and llms.txt), for comparison with an emitted context. */
65
+ export declare function documentationTokens(): Promise<number>;
@@ -0,0 +1,17 @@
1
+ interface Options {
2
+ json?: boolean | undefined;
3
+ project: string;
4
+ out?: string | undefined;
5
+ format?: string | undefined;
6
+ input?: string | undefined;
7
+ target?: string | undefined;
8
+ origin?: string | undefined;
9
+ 'dry-run'?: boolean | undefined;
10
+ 'timeout-ms'?: string | undefined;
11
+ release?: string | undefined;
12
+ 'git-commit'?: string | undefined;
13
+ 'allow-authoring'?: boolean | undefined;
14
+ 'host-file'?: string | undefined;
15
+ }
16
+ export declare function runEcosystemCommand(command: string, args: string[], options: Options, print: (value: unknown) => unknown): Promise<void>;
17
+ export {};
@@ -0,0 +1,46 @@
1
+ import { request } from 'node:https';
2
+ export declare const EGRESS_DNS_LIMIT = 64;
3
+ export interface EgressRequest {
4
+ url: string;
5
+ method: string;
6
+ headers?: Record<string, string>;
7
+ body?: Uint8Array;
8
+ signal?: AbortSignal;
9
+ }
10
+ export interface EgressResponse {
11
+ status: number;
12
+ headers: Record<string, string>;
13
+ body: Buffer;
14
+ }
15
+ export interface EgressOptions {
16
+ grantOrigins: string[];
17
+ timeoutMs?: number;
18
+ maxRequestBytes?: number;
19
+ maxResponseBytes?: number;
20
+ maxHeaderBytes?: number;
21
+ concurrency?: number;
22
+ }
23
+ type EgressErrorCode = 'denied' | 'busy' | 'closed' | 'aborted' | 'timeout' | 'limit' | 'upstream';
24
+ export declare class EgressError extends Error {
25
+ readonly code: EgressErrorCode;
26
+ constructor(code: EgressErrorCode);
27
+ }
28
+ /** Conservative public-unicast filter. IPv4-mapped IPv6 and transition mechanisms are denied. */
29
+ export declare function isPublicAddress(address: string): boolean;
30
+ export declare function egressUrl(value: string): URL;
31
+ export declare function safeEgressHeaders(headers: Record<string, string>, maxBytes?: number): Record<string, string>;
32
+ /** Operator-owned transport. Never exposed to guests. Each request has its own nonpooled socket. */
33
+ export interface EgressDependencies {
34
+ resolve?: (hostname: string) => Promise<{
35
+ address: string;
36
+ family: number;
37
+ }[]>;
38
+ request?: typeof request;
39
+ }
40
+ export declare class EgressClient {
41
+ #private;
42
+ constructor(options: EgressOptions, dependencies?: EgressDependencies);
43
+ request(input: EgressRequest): Promise<EgressResponse>;
44
+ close(): Promise<void>;
45
+ }
46
+ export {};
@@ -0,0 +1,50 @@
1
+ import type { CatalogMetadata } from './catalog.ts';
2
+ /** example.yaml, the same schema as recipe.yaml; `name` repeats `id`. */
3
+ export interface ExampleSummary extends CatalogMetadata {
4
+ name: string;
5
+ }
6
+ /** One cookbook route in the generated tag index (examples/cookbook/route-index.json). */
7
+ export interface RouteIndexEntry {
8
+ path: string;
9
+ file: string;
10
+ handler: string;
11
+ methods: string[];
12
+ tags: string[];
13
+ description: string;
14
+ }
15
+ export interface RouteIndex {
16
+ format: 1;
17
+ project: string;
18
+ routes: number;
19
+ entries: RouteIndexEntry[];
20
+ }
21
+ export interface ExampleSearchResult {
22
+ query: string;
23
+ count: number;
24
+ /** The smallest matching runnable example, and its best matching cookbook route when the cookbook is that example. */
25
+ best: (ExampleSummary & {
26
+ route?: RouteIndexEntry;
27
+ }) | null;
28
+ results: (ExampleSummary & {
29
+ score: number;
30
+ matched: string[];
31
+ matchedRoutes: RouteIndexEntry[];
32
+ })[];
33
+ }
34
+ export declare const exampleNames: readonly ["assets", "aws", "cloudflare", "compliance", "conditions", "cookbook", "egress", "extensions", "live-links", "monitoring", "prerender", "provider-conformance", "tunnel", "vercel"];
35
+ export declare const routeIndexFile = "route-index.json";
36
+ export declare function listExamples(): Promise<ExampleSummary[]>;
37
+ /**
38
+ * Derives the per-route tag index of one project from its loaded routes: handler,
39
+ * methods, capabilities, policy names and middleware module names. The file each
40
+ * route comes from is read from the entry and its includes; routes that neither
41
+ * declares were generated by `site`.
42
+ */
43
+ export declare function buildRouteIndex(project: string, label: string): Promise<RouteIndex>;
44
+ export declare function readRouteIndex(name: string): Promise<RouteIndex>;
45
+ /**
46
+ * Searches example.yaml files and the cookbook's per-route index locally. Results
47
+ * are ordered smallest runnable example first, so `best` is the least code that
48
+ * demonstrates the match; cookbook hits carry their matching routes.
49
+ */
50
+ export declare function searchExamples(text: string): Promise<ExampleSearchResult>;