@trayai/helix-sdk 0.63.0
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/CHANGELOG.md +49 -0
- package/LICENSE.md +178 -0
- package/README.md +230 -0
- package/dist/broker/index.d.ts +59 -0
- package/dist/broker/index.js +1 -0
- package/dist/chunk-J5OA4RGR.js +1 -0
- package/dist/chunk-L6J5L3JQ.js +1 -0
- package/dist/chunk-V63DM4MB.js +1 -0
- package/dist/chunk-W5TFZBQD.js +1 -0
- package/dist/index.d.ts +117 -0
- package/dist/index.js +9 -0
- package/dist/internal/index.d.ts +128 -0
- package/dist/internal/index.js +1 -0
- package/dist/sdk-config-B-Vfaig8.d.ts +184 -0
- package/dist/testing/index.d.ts +13 -0
- package/dist/testing/index.js +1 -0
- package/dist/types-BxQmQx3V.d.ts +173 -0
- package/package.json +76 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as h3 from 'h3';
|
|
2
|
+
import { ZodType, z } from 'zod';
|
|
3
|
+
import { c as FunctionHandler, b as DefineFunctionOptions, T as TrayContext } from './types-BxQmQx3V.js';
|
|
4
|
+
export { D as DbCallParameters, a as DbClient, F as FileSystemClient, H as HttpClient, K as KeyValueStore, L as Logger, S as SqlBuilder, U as UnvalidatedInput } from './types-BxQmQx3V.js';
|
|
5
|
+
import { T as TrayConfig, L as LoadedTrayConfig, b as WatchErrorPhase } from './sdk-config-B-Vfaig8.js';
|
|
6
|
+
export { P as ProvisionedTrayConfig, a as SdkRuntimeConfig, U as UnprovisionedTrayConfig, W as WORKSPACE_ID_REQUIRED_CODE, c as WorkspaceIdRequiredError, g as getSdkConfig, l as loadConfig, d as loadedTrayConfigSchema, p as projectIdSchema, r as requireWorkspaceId, e as resolveConfigFile, w as workspaceIdSchema } from './sdk-config-B-Vfaig8.js';
|
|
7
|
+
import 'ky';
|
|
8
|
+
import 'unstorage';
|
|
9
|
+
|
|
10
|
+
declare function defineFunction<TInput extends ZodType | undefined = undefined, TOutput extends ZodType | undefined = undefined>(handler: FunctionHandler<TInput extends ZodType ? ReturnType<TInput["parse"]> : Record<string, unknown>>, schemaOrOptions?: ZodType | DefineFunctionOptions<TInput, TOutput>): h3.EventHandler<h3.EventHandlerRequest, Promise<unknown>>;
|
|
11
|
+
|
|
12
|
+
interface RunWithinAppSpanArgs {
|
|
13
|
+
executionId: string;
|
|
14
|
+
deploymentId: string | null;
|
|
15
|
+
userId: string | null;
|
|
16
|
+
/** HTTP method, e.g. "GET" — span `method` attribute. */
|
|
17
|
+
method: string;
|
|
18
|
+
/** Request path, e.g. "/" — span `route` attribute and summary routeOrJob suffix. */
|
|
19
|
+
route: string;
|
|
20
|
+
/** ISO timestamp captured when the invocation began. */
|
|
21
|
+
startedAt: string;
|
|
22
|
+
/**
|
|
23
|
+
* Monotonic-ish start captured via Date.now() at the earliest point of invocation.
|
|
24
|
+
* Drives durationMs without an ISO round-trip parse. When omitted, Date.now() is
|
|
25
|
+
* sampled at runWithinAppSpan entry — slightly late but still correct.
|
|
26
|
+
*/
|
|
27
|
+
startMs?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Top-level "App" root span + paired summary for the SPA/static serve path.
|
|
31
|
+
*
|
|
32
|
+
* Brings the prod router-shim SPA branch to parity with the function path:
|
|
33
|
+
* the function path emits a root "function" span + summary inside
|
|
34
|
+
* defineFunction; the SPA branch never enters defineFunction, so it emitted
|
|
35
|
+
* nothing. This helper wraps the static-serve call so a single SPA invocation
|
|
36
|
+
* produces exactly one root span (parentSpanId "") plus one summary, written
|
|
37
|
+
* via the same StdoutJsonSpanExporter / emitSummary as functions.
|
|
38
|
+
*
|
|
39
|
+
* - ensures initOtel() ran (SPA path does not init via defineFunction);
|
|
40
|
+
* - runs inside executionIdStore.run(executionId, …) so the executionId stays
|
|
41
|
+
* available as ambient context (the static-serve path self-roots with a
|
|
42
|
+
* random traceId — it does not join an inbound distributed trace);
|
|
43
|
+
* - starts an "App" SERVER span, sets method/route/http.response.status_code/
|
|
44
|
+
* helix.status, ends it (StdoutJsonSpanExporter emits the span line);
|
|
45
|
+
* - emits the summary (triggerType "http") in finally, errored when the serve
|
|
46
|
+
* throws or yields a >=400 status.
|
|
47
|
+
*/
|
|
48
|
+
declare function runWithinAppSpan<T extends {
|
|
49
|
+
httpResponse?: {
|
|
50
|
+
status?: number;
|
|
51
|
+
};
|
|
52
|
+
} | null>(args: RunWithinAppSpanArgs, serve: () => Promise<T>): Promise<T>;
|
|
53
|
+
|
|
54
|
+
declare function getContext(): TrayContext;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Type-level helper for helix.config.ts — provides autocomplete in the editor.
|
|
58
|
+
* Validation happens at load time in loadConfig(), not here.
|
|
59
|
+
*/
|
|
60
|
+
declare function defineConfig(config: TrayConfig): TrayConfig;
|
|
61
|
+
|
|
62
|
+
declare const ENVIRONMENT_VALUES: readonly ["production"];
|
|
63
|
+
type Environment = (typeof ENVIRONMENT_VALUES)[number];
|
|
64
|
+
declare const environmentSchema: z.ZodEnum<["production"]>;
|
|
65
|
+
|
|
66
|
+
interface CreateConfigServiceOptions {
|
|
67
|
+
/** Directory containing `helix.config.ts`. */
|
|
68
|
+
cwd: string;
|
|
69
|
+
/** If true, attach a c12 watcher and emit subscribers on each change. */
|
|
70
|
+
watch?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Invoked when the watcher fails to attach, a reload throws, or a payload
|
|
73
|
+
* fails zod validation. Defaults to a single stderr line per error.
|
|
74
|
+
* The held config is NEVER replaced on error — last good config stays live.
|
|
75
|
+
* `phase` identifies which watch lifecycle step failed.
|
|
76
|
+
*/
|
|
77
|
+
onError?: (error: unknown, context: {
|
|
78
|
+
phase: WatchErrorPhase;
|
|
79
|
+
}) => void;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Composition-root config handle. ONE instance per process.
|
|
83
|
+
* Boot at CLI/MCP entrypoints; pass via DI — replaces module-level singleton.
|
|
84
|
+
*
|
|
85
|
+
* Worker bridge: parent seeds the initial snapshot via runtimeConfig, then
|
|
86
|
+
* republishes updates on BroadcastChannel("tray-config-bridge"). The worker
|
|
87
|
+
* plugin reseeds the active-config slot via `setActiveConfig`; disk edits
|
|
88
|
+
* hot-reload without restart.
|
|
89
|
+
*/
|
|
90
|
+
interface ConfigService {
|
|
91
|
+
/** Returns the last resolved config. Throws if construction failed. */
|
|
92
|
+
get(): LoadedTrayConfig;
|
|
93
|
+
/** Force a fresh disk read; updates `get()` and notifies subscribers. */
|
|
94
|
+
reload(): Promise<LoadedTrayConfig>;
|
|
95
|
+
/** Register a change listener. Returns an unsubscribe handle. */
|
|
96
|
+
subscribe(listener: (newConfig: LoadedTrayConfig) => void): () => void;
|
|
97
|
+
/** Detach the watcher (if any) and release subscribers. */
|
|
98
|
+
stop(): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* Resolves once the underlying file watcher is attached and ready to receive
|
|
101
|
+
* filesystem events. Resolves immediately when `watch` was not requested.
|
|
102
|
+
* Use before write-then-expect-fire sequences to eliminate the chokidar
|
|
103
|
+
* attach-race without resorting to fixed-delay timers.
|
|
104
|
+
*/
|
|
105
|
+
ready(): Promise<void>;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Build a {@link ConfigService}. Awaiting guarantees get() is safe immediately.
|
|
109
|
+
*
|
|
110
|
+
* Absent helix.config.ts: exposes unprovisioned default + (watch:true) watches parent dir
|
|
111
|
+
* for file creation; c12 file-watcher takes over once file appears (MCP boots before `helix init`).
|
|
112
|
+
*
|
|
113
|
+
* watch:true: rapid file events serialized via updateChain — no out-of-order subscriber calls.
|
|
114
|
+
*/
|
|
115
|
+
declare function createConfigService(options: CreateConfigServiceOptions): Promise<ConfigService>;
|
|
116
|
+
|
|
117
|
+
export { type ConfigService, type CreateConfigServiceOptions, DefineFunctionOptions, ENVIRONMENT_VALUES, type Environment, FunctionHandler, LoadedTrayConfig, type RunWithinAppSpanArgs, TrayConfig, TrayContext, WatchErrorPhase, createConfigService, defineConfig, defineFunction, environmentSchema, getContext, runWithinAppSpan };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{a as pt,b as $r}from"./chunk-L6J5L3JQ.js";import{a as T,b as O,d as y,e as D,f as I,g as ft,j as b,l as V,m as P,n as Ae,o as _e,p as ht,q as F,r as ie,s as ae,t as ce,u as wt}from"./chunk-J5OA4RGR.js";import{a as q,b as se,c as gt,d as yt}from"./chunk-V63DM4MB.js";import{a as u,b as mt}from"./chunk-W5TFZBQD.js";import{randomUUID as jo}from"crypto";import{SpanStatusCode as Ar,SpanKind as No}from"@opentelemetry/api";import{AsyncLocalStorage as Bt}from"async_hooks";import{trace as nn,SpanKind as on,SpanStatusCode as Fe}from"@opentelemetry/api";import{ExportResultCode as sn,W3CTraceContextPropagator as an}from"@opentelemetry/core";import{NodeTracerProvider as cn,SimpleSpanProcessor as un,BatchSpanProcessor as dn}from"@opentelemetry/sdk-trace-node";import{OTLPTraceExporter as qr}from"@opentelemetry/exporter-trace-otlp-proto";import{OTLPLogExporter as Vr}from"@opentelemetry/exporter-logs-otlp-proto";var Kr={production:"https://api.tray.io/private/v1/helix/otlp"};function Oe(e){return Kr[e]}function Wr(){return I()??""}function bt(){return{[T]:Wr()}}function vt(){let e=Oe(b().env);return new qr({url:`${e}/v1/traces`,headers:()=>Promise.resolve(bt())})}function St(){let e=Oe(b().env);return new Vr({url:`${e}/v1/logs`,headers:()=>Promise.resolve(bt())})}import{logs as Ct,SeverityNumber as ue}from"@opentelemetry/api-logs";import{LoggerProvider as Yr,BatchLogRecordProcessor as Gr}from"@opentelemetry/sdk-logs";function W(e){try{return JSON.stringify(e)}catch(t){return JSON.stringify({_serialization_error:t instanceof Error?t.message:String(t)})}}function zr(e){return new TextEncoder().encode(e).length}var Et="\u2026[truncated]",Jr=zr(Et),L=4096;function A(e,t=L){let r=new TextEncoder().encode(e);if(r.length<=t)return e;let n=r.subarray(0,t-Jr);return new TextDecoder("utf-8").decode(n).replace(/�$/,"")+Et}function v(e,t=L){return A(W(e),t)}var Xr="@trayai/helix-sdk",z,xt={debug:{number:ue.DEBUG,text:"DEBUG"},info:{number:ue.INFO,text:"INFO"},warn:{number:ue.WARN,text:"WARN"},error:{number:ue.ERROR,text:"ERROR"}};function Zr(){return y().mode==="lambda"?[new Gr({exporter:St()})]:[]}function kt(){if(z!==void 0)return;let e=Zr();e.length!==0&&(z=new Yr({processors:e}),Ct.setGlobalLoggerProvider(z))}function Qr(e,t,r){let n=xt[e]??xt.info;return{severityNumber:n.number,severityText:n.text,body:t,...r?{attributes:{"tray.log.meta":v(r)}}:{}}}function Rt(e,t,r){Ct.getLogger(Xr).emit(Qr(e,t,r))}async function Tt(e=2e3){if(z===void 0)return;let t;try{await Promise.race([z.forceFlush(),new Promise(r=>{t=setTimeout(r,e)})])}catch(r){process.stderr.write(`[helix-sdk] otel log flush failed: ${r instanceof Error?r.message:String(r)}
|
|
2
|
+
`)}finally{t!==void 0&&clearTimeout(t)}}function De(){let e=process.env.TRAY_PRETTY_LOGS;return e==="1"||e==="true"}function en(){if(process.env.NO_COLOR!==void 0)return!1;let e=process.env.FORCE_COLOR;return e!==void 0&&e!=="0"&&e!=="false"?!0:!!process.stdout.isTTY&&process.env.TERM!=="dumb"}function R(e,t){return en()?`\x1B[${e}m${t}\x1B[0m`:t}var tn=5,rn={FN:"1;35",INFO:"34",AUTH:"35",API:"36",WARN:"33",ERROR:"31",DEBUG:"90"},It="32",Pt="31",de="2",At="1";function le(e){return R(rn[e]??"0",e.padEnd(tn))}function _t(e,t){return`${le("FN")} ${R(At,`${e} ${t}`.trim())}`}function Ot(e,t,r,n){let o=e.toUpperCase(),i=`${n?`${R(de,n)} `:""}${le(o)} ${t}`;return r&&Object.keys(r).length>0&&(i+=` ${R(de,W(r))}`),i}function Dt(e){return new Date(e[0]*1e3).toTimeString().slice(0,8)}function Ft(e){return`${le("AUTH")} ${e}`}function Lt(e,t,r,n,o){let s=r===void 0?"ERR":String(r),i=R(o==="error"?Pt:It,s);return`${le("API")} ${e} ${t} \u2192 ${i} ${R(de,`${n}ms`)}`}function jt(e,t,r){let n=t?Pt:It,o=R(n,"\u25CF"),s=R(n,t?"error":"success");return`${o} ${R(At,e)} ${s} ${R(de,`${r}ms`)}`}function j(e){try{process.stdout.write(e+`
|
|
3
|
+
`)}catch{}}var fe=new Bt,pe=new Bt;function C(e){let t=pe.getStore();t&&(t[e]=!0)}var ln=/^[0-9a-f]{32}$/;function fn(e){let t=e.replace(/-/g,"").toLowerCase();return ln.test(t)?t:null}var pn={0:"STATUS_CODE_UNSET",1:"STATUS_CODE_OK",2:"STATUS_CODE_ERROR"},N=new Map;function x(e,t,r){let n=N.get(e);n?n[t]=r:N.set(e,{[t]:r})}var J;function Nt(e){return`${e[0]}${String(e[1]).padStart(9,"0")}`}function mn(e){return Math.round(e[0]*1e3+e[1]/1e6)}function Mt(e){try{process.stdout.write(W(e)+`
|
|
4
|
+
`)}catch{}}var Le=class{export(t,r){for(let n of t){let o=n.spanContext().spanId,s=N.get(o),i={...n.attributes};if(s!==void 0){for(let[d,f]of Object.entries(s))typeof f=="string"?i[d]=A(f):typeof f=="object"&&f!==null?i[d]=v(f):i[d]=f;N.delete(o)}let a=fe.getStore(),c=a?fn(a):null;Mt({_otel:"span",traceId:c??n.spanContext().traceId,spanId:o,parentSpanId:n.parentSpanContext?.spanId??"",name:n.name,kind:n.kind,startTimeUnixNano:Nt(n.startTime),endTimeUnixNano:Nt(n.endTime),attributes:i,status:{code:pn[n.status.code]??"STATUS_CODE_UNSET",...n.status.message?{message:A(n.status.message)}:{}}})}r({code:sn.SUCCESS})}forceFlush(){return Promise.resolve()}shutdown(){return Promise.resolve()}},je=class{onStart(t,r){}onEnd(t){N.delete(t.spanContext().spanId)}forceFlush(){return Promise.resolve()}shutdown(){return Promise.resolve()}},Ne=class{onStart(t){let r=t;(r.name==="function"||r.name==="App")&&j(`
|
|
5
|
+
`+_t(String(r.attributes.method??""),String(r.attributes.route??"")))}onEnd(t){let r=t.attributes;switch(t.name){case"log":{let n=t.spanContext().spanId,o=N.get(n)?.properties;j(Ot(String(r.level??"info"),String(r.message??""),o,Dt(t.startTime)));break}case"auth":j(Ft(String(r.alias??"")));break;case"externalApi":{let n=typeof r.statusCode=="number"?r.statusCode:void 0;j(Lt(String(r.method??""),String(r.host??""),n,mn(t.duration),r.status==="error"?"error":"success"));break}}}forceFlush(){return Promise.resolve()}shutdown(){return Promise.resolve()}};function gn(){let t=[De()?new Ne:new un(new Le)];return y().mode==="lambda"&&t.push(new dn(vt())),t.push(new je),t}function Be(){J===void 0&&(J=new cn({spanProcessors:gn()}),J.register({propagator:new an}),kt())}async function Me(e=2e3){let t=[Tt(e)];J!==void 0&&t.push((async()=>{let r;try{await Promise.race([J.forceFlush(),new Promise(n=>{r=setTimeout(n,e)})])}catch(n){process.stderr.write(`[helix-sdk] otel flush failed: ${n instanceof Error?n.message:String(n)}
|
|
6
|
+
`)}finally{r!==void 0&&clearTimeout(r)}})()),await Promise.all(t)}var k=nn.getTracer("@trayai/helix-sdk");function Ue({executionId:e,deploymentId:t,routeOrJob:r,startedAt:n,startMs:o,errored:s,errorMessage:i,userId:a,flags:c}){let d=new Date().toISOString(),f=Date.now()-o;if(De()){j(`
|
|
7
|
+
`+jt(r,s,f));return}Mt({_otel:"summary",executionId:e,deploymentId:t,triggerType:"http",routeOrJob:r,status:s?"error":"success",startedAt:n,finishedAt:d,durationMs:f,userId:a,hasError:s||c.hasError,hasAuth:c.hasAuth,hasExternal:c.hasExternal,hasDb:c.hasDb,errorSummary:s&&i!==null?A(i):null})}async function yn(e,t){let r=e.startMs??Date.now();Be();let n=!1,o=null;try{return await fe.run(e.executionId,()=>k.startActiveSpan("App",{kind:on.SERVER,attributes:{method:e.method,route:e.route,...e.deploymentId?{deploymentId:e.deploymentId}:{}}},async s=>{try{let i=await t(),a=i?.httpResponse?.status??404;return n=a>=400,s.setAttribute("http.response.status_code",a),s.setAttribute("helix.status",n?"error":"success"),s.setStatus({code:n?Fe.ERROR:Fe.OK}),i}catch(i){throw n=!0,o=i instanceof Error?i.message:String(i),s.setAttribute("http.response.status_code",500),s.setAttribute("helix.status","error"),s.setStatus({code:Fe.ERROR,message:o}),i}finally{s.end()}}))}finally{Ue({executionId:e.executionId,deploymentId:e.deploymentId,routeOrJob:`${e.method} ${e.route}`,startedAt:e.startedAt,startMs:r,errored:n,errorMessage:o,userId:e.userId,flags:{hasDb:!1,hasExternal:!1,hasAuth:!1,hasError:!1}}),await Me()}}import{defineEventHandler as Bo,getMethod as Mo,getRequestURL as Uo,getHeaders as Or,getHeader as _r}from"h3";import{readBody as hn,getQuery as wn,getRouterParams as bn}from"h3";async function Ut(e,t){let r=await vn(e),n=wn(e),o=bn(e)??{},s={...n,...r,...o};return t?Sn(s,t):s}async function vn(e){try{let t=await hn(e);return t&&typeof t=="object"?t:(t!=null&&t!==""&&console.warn("[helix-sdk] Request body present but not a JSON object \u2014 ignored"),{})}catch(t){if(t instanceof Error&&"statusCode"in t&&t.statusCode===400){let n=new Error("Malformed request body");throw n.statusCode=400,n.data={message:"Request body is not valid JSON"},n}let r=e.method?.toUpperCase();if(r==="GET"||r==="HEAD"||r==="DELETE")return{};throw t}}function Sn(e,t){let r=t.safeParse(e);if(!r.success){let n=new Error("Input validation failed");throw n.statusCode=400,n.data=r.error.flatten(),n}return r.data}import{SpanKind as En}from"@opentelemetry/api";function me(e,t,r){let n=k.startSpan("log",{kind:En.INTERNAL});n.setAttribute("message",t),n.setAttribute("level",e),r&&x(n.spanContext().spanId,"properties",r),n.end(),Rt(e,t,r)}function Ht(){return{info:(e,t)=>me("info",e,t),warn:(e,t)=>me("warn",e,t),error:(e,t)=>me("error",e,t),debug:(e,t)=>me("debug",e,t)}}var Y=class extends Error{statusCode;constructor(t,r){super(r),this.statusCode=t,this.name="HttpError"}};function $t(e){return t=>{e.node.res.statusCode=t}}function Kt(){return(e,t)=>{throw new Y(e,t)}}import kn from"ky";import{context as He,trace as Rn,SpanKind as ye,SpanStatusCode as Wt}from"@opentelemetry/api";import xn from"ky";async function qt(e,t={}){let r=D(),n=I(),o=!!(r&&r.trim().length>0),s=!!(n&&n.trim().length>0);if(!o&&!s)throw u.missingExecutionCredentials();let{env:i}=b(),a=se(i),c=t.timeout??6e4,d={Accept:"application/json"};o&&(d[O]=r),s&&(d[T]=n);let f=y().deploymentId,m=f?{...e,deploymentId:f}:e,l=await xn.post(`${a}/broker/http`,{json:m,headers:d,throwHttpErrors:!1,timeout:c}),p;return(l.headers.get("content-type")??"").includes("application/json")?p=await l.json():p=await l.text(),{status:l.status,body:p}}import Cn from"ky";async function Vt(e,t={}){let r=ft();if(!r)throw u.missingTrayToken();let{env:n}=b(),o=se(n),s=t.timeout??6e4,i=await Cn.post(`${o}/broker/http/dev`,{json:e,headers:{Authorization:`Bearer ${r}`,Accept:"application/json"},throwHttpErrors:!1,timeout:s}),a;return(i.headers.get("content-type")??"").includes("application/json")?a=await i.json():a=await i.text(),{status:i.status,body:a}}async function ge(e,t={}){let r=y().mode==="lambda"?qt:Vt,n;try{n=await r(e,t)}catch(a){if(a instanceof u)throw a;let c=a instanceof Error?a.message??String(a):String(a);throw u.brokerError(0,c)}let{status:o,body:s}=n;if(o<200||o>=300){let a;if(s!==null&&typeof s=="object"){let c=s;typeof c.message=="string"?a=c.message:typeof c.error=="string"?a=c.error:a=String(s)}else a=String(s);throw u.brokerError(o,a,v(s))}let i=gt.safeParse(s);if(!i.success)throw u.brokerError(o,"broker returned malformed response",v(s));return yt(i.data)}var Tn=["get","post","put","patch","delete","head","options"],zt="[stream body omitted]";function $e(e){try{return new URL(e).hostname}catch{return e}}function In(e,t,r,n){let o=$e(t),s="externalApi",i={kind:ye.CLIENT};return k.startActiveSpan(s,i,async a=>{let c=a.spanContext().spanId;return a.setAttributes({method:e,host:o}),x(c,"request",{url:t,method:e,...r!==void 0?{body:r instanceof ReadableStream?zt:r}:{}}),n(a,c)})}function Ke(e,t,r){e.setAttribute("status",t),e.setStatus(t==="success"?{code:Wt.OK}:{code:Wt.ERROR,message:r}),e.end()}var Pn=16;async function An(e,t){let r=e.clone().body;return r?Jt(r,t):new Uint8Array(0)}async function Jt(e,t){let r=e.getReader(),n=[],o=0,s=0;try{for(;;){let{done:c,value:d}=await r.read();if(c)break;if(!d||d.byteLength===0){if(s+=1,s>=Pn)break;continue}s=0;let f=t+1-o;if(d.byteLength>=f){n.push(d.slice(0,f)),o+=f;break}n.push(d),o+=d.byteLength}}finally{r.cancel().catch(()=>{}),r.releaseLock()}let i=new Uint8Array(o),a=0;for(let c of n)i.set(c,a),a+=c.byteLength;return i}async function Yt(e,t,r){if("kyResponse"in r)try{let n=await An(r.kyResponse,L),o=new TextDecoder("utf-8").decode(n,{stream:!0}),s;if(n.length<=L)try{s=JSON.parse(o)}catch{s=o}else s=o;x(e,"response",s)}catch{x(e,"response",{status:t})}else x(e,"response",r.bodyValue)}async function _n(e,t){if(t instanceof ReadableStream){let r=e.body??t;try{let[n,o]=r.tee(),s=new Request(e,{body:n,duplex:"half"}),i=await Jt(o,L);return{body:new TextDecoder("utf-8").decode(i,{stream:!0}),request:s}}catch{return{body:zt}}}return typeof t=="string"?{body:t}:{}}function Gt(){let e=kn.create({});function t(n){return(o,s)=>{let i=He.active(),a,c="",d=!1,f=(l,p)=>{a&&!d&&(d=!0,Ke(a,l,p))},m=e.extend({hooks:{beforeRequest:[async(l,p)=>{let g=await _n(l,p.body),h=g.body;if(a||(a=k.startSpan("externalApi",{kind:ye.CLIENT},i),c=a.spanContext().spanId),a.setAttributes({method:l.method.toUpperCase(),host:$e(l.url)}),x(c,"request",{url:l.url,method:l.method.toUpperCase(),...h!==void 0?{body:h}:{}}),d=!1,C("hasExternal"),g.request)return g.request}],beforeRetry:[l=>{f("error","retry"),a=void 0,c="",d=!1}],afterResponse:[async(l,p,g)=>{a&&(a.setAttribute("statusCode",g.status),await Yt(c,g.status,{kyResponse:g}),g.ok?f("success"):s?.throwHttpErrors===!1&&(C("hasError"),f("error",`HTTP ${g.status}`)))}],beforeError:[l=>(C("hasError"),f("error",l.message),l)]}});return a=k.startSpan("externalApi",{kind:ye.CLIENT},i),c=a.spanContext().spanId,a.setAttributes({method:n.toUpperCase(),host:$e(String(o))}),He.with(Rn.setSpan(He.active(),a),()=>{let l=n==="options"?m(o,{...s,method:"OPTIONS"}):m[n](o,s);return l.catch(p=>{C("hasError"),f("error",p instanceof Error?p.message:String(p))}),l})}}let r=Object.fromEntries(Tn.map(n=>[n,t(n)]));return{...e,...r,authed(n){return On(n)}}}function On(e){let r=b().authentications??{};if(!r[e])throw u.unknownAlias(e,Object.keys(r));let n=r[e];function o(s){return(i,a={})=>{let c=s.toUpperCase();return In(c,i,a.body,async(d,f)=>{C("hasAuth");let m=k.startSpan("auth",{kind:ye.INTERNAL});m.setAttribute("alias",e),m.setAttribute("id",n),m.end();try{let l=q({authenticationId:n,method:c,url:i,body:a.body,headers:a.headers,query:a.query}),p=await ge(l,{timeout:a.timeout});return d.setAttribute("statusCode",p.status),await Yt(f,p.status,{bodyValue:p.body}),Ke(d,"success"),p}catch(l){throw C("hasError"),l instanceof u&&l.detail.kind==="broker_error"&&l.detail.status>0&&d.setAttribute("statusCode",l.detail.status),Ke(d,"error",l instanceof Error?l.message:String(l)),l}})}}return{get:o("get"),post:o("post"),put:o("put"),patch:o("patch"),delete:o("delete"),head:o("head"),options:o("options")}}import{SpanKind as Hn,SpanStatusCode as er}from"@opentelemetry/api";function G(e){let t=e.trimStart().match(/^([A-Za-z]+)/);return t?t[1].toUpperCase():"QUERY"}var Dn=18e4,Xt=Dn-1e4,Fn=2e3;async function Zt(e,t,r){let n=new Set(["FINISHED","FAILED","ABORTED"]),o=Date.now(),s=0;for(;Date.now()-o<Xt;){let i=await e(t,"DescribeStatement",{Id:r}),a=i.Status;if(n.has(a))return i;let c=Math.min(Fn,200*2**s),d=c/2+Math.random()*(c/2),f=Xt-(Date.now()-o);await new Promise(m=>setTimeout(m,Math.min(d,f))),s++}throw u.dbCallFailed(`statement polling exceeded budget after ${Date.now()-o}ms`)}var Ln=new Set(["SELECT","WITH","SHOW"]),jn=new Set(["INSERT","UPDATE","DELETE","MERGE"]);function Nn(e){if(!e.clusterIdentifier&&!e.workgroupName)throw u.dbInvalidParameters("either clusterIdentifier or workgroupName is required");if(e.clusterIdentifier&&e.workgroupName)throw u.dbInvalidParameters("clusterIdentifier and workgroupName are mutually exclusive (Provisioned vs Serverless)");if(!e.database)throw u.dbInvalidParameters("database is required");if(e.clusterIdentifier&&!e.dbUser)throw u.dbInvalidParameters("dbUser is required when using clusterIdentifier (Provisioned)");if(!e.region)throw u.dbInvalidParameters("region is required")}function Bn(e,t){let r=null;if(typeof t=="string")try{r=JSON.parse(t)}catch{}else t!==null&&typeof t=="object"&&(r=t);let n=typeof r?.__type=="string"?r.__type:void 0,o=typeof r?.message=="string"?r.message:void 0;if(n&&o)return u.dbQueryFailed(`${n}: ${o}`);let s=typeof t=="string"?A(t):v(t);return u.dbCallFailed(s)}function Mn(e){if(e==null||typeof e!="string")return e;try{return JSON.parse(e)}catch{throw u.dbCallFailed("upstream body not JSON: "+e.slice(0,200))}}function Un(e,t){return typeof t!="number"||t<0?{}:Ln.has(e)?{rowsRead:t}:jn.has(e)?{rowsWritten:t}:{}}function Qt(e){async function t(r,n,o){let s=q({authenticationId:e,method:"POST",url:`https://redshift-data.${r}.amazonaws.com/`,body:o,headers:{"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":`RedshiftData.${n}`}});try{let{status:i,body:a}=await ge(s);if(i>=400)throw Bn(i,a);return Mn(a)}catch(i){if(i instanceof u)throw i;let a=i instanceof Error?i.message??String(i):String(i);throw u.dbCallFailed(a,i instanceof Error?i:void 0)}}return{system:"redshift",validate:Nn,async execute(r,n){let o=G(n),s={Sql:n,Database:r.database,...r.clusterIdentifier&&{ClusterIdentifier:r.clusterIdentifier,DbUser:r.dbUser},...r.workgroupName&&{WorkgroupName:r.workgroupName},...r.statementName&&{StatementName:r.statementName}},i=await t(r.region,"ExecuteStatement",s),a=i,c=typeof a?.Id=="string"?a.Id:void 0;if(!c){let p=v(i);throw u.dbCallFailed(`ExecuteStatement response missing Id; got: ${p}`)}let d=await Zt(t,r.region,c),f=d.Status;if(f==="FAILED"){let p=typeof d.Error=="string"?d.Error:"statement failed";throw u.dbQueryFailed(`${p} (statement: ${c})`)}if(f==="ABORTED")throw u.dbQueryFailed(`statement aborted (statement: ${c})`);let m=Un(o,d.ResultRows);return d.HasResultSet===!1?{result:{rowsAffected:d.ResultRows??0},metadata:m}:{result:await t(r.region,"GetStatementResult",{Id:c}),metadata:m}}}}var qe=64*1024;function $n(e){return e.length>qe?`${e.slice(0,qe)}...[truncated]`:e}function Kn(e,t,r,n,o){e.setAttributes({system:t.system,statement:o,namespace:r.database,operation:n})}function qn(e,t,r,n){let o=typeof r=="string"?r:JSON.stringify(r);return o.length>qe?x(t,"result",{truncated:!0,size:o.length}):x(t,"result",r),n.rowsRead!==void 0&&e.setAttribute("rowsRead",n.rowsRead),n.rowsWritten!==void 0&&e.setAttribute("rowsWritten",n.rowsWritten),o}async function Vn(e,t,r){let n=G(r),o=$n(r);return k.startActiveSpan("database",{kind:Hn.CLIENT},async s=>{let i=s.spanContext().spanId;Kn(s,e,t,n,o);try{C("hasDb");let{result:a,metadata:c}=await e.execute(t,r),d=qn(s,i,a,c);return s.setAttribute("status","success"),s.setStatus({code:er.OK}),d}catch(a){C("hasError");let c=a instanceof Error?a.message:String(a);throw s.setAttribute("status","error"),s.setStatus({code:er.ERROR,message:c}),a}finally{s.end()}})}function Ve(e){let r=b().authentications??{};if(!r[e])throw u.unknownAlias(e,Object.keys(r));let n=r[e],o=Qt(n);function s(i,a){return o.validate(i),Vn(o,i,a)}return{parameters(i){return{sql(a){return s(i,a)}}},sql(i){return s({},i)}}}import{createStorage as Gn}from"unstorage";var tr=1024,We=250*1024,Wn=new TextEncoder,zn=/(^|\/)\.\.(\/|$)/,Jn=/[?#]/,Yn=/[\u0000-\u001F\u007F]/;function rr(e){if(e.length===0)throw u.kvKeyInvalid("Key must be a non-empty string");if(zn.test(e))throw u.kvKeyInvalid("Key contains path traversal segment");if(Jn.test(e)||Yn.test(e))throw u.kvKeyInvalid("Key contains illegal characters");if(e.startsWith("/")||e.endsWith("/")||e.split("/").some(r=>r===""))throw u.kvKeyInvalid("Key must not contain empty path segments");let t=Wn.encode(e).length;if(t<1||t>tr)throw u.kvKeyInvalid(`Key must be between 1 and ${tr} UTF-8 bytes (got ${t})`)}function nr(e){let t;try{t=JSON.stringify(e)}catch{throw u.kvValueInvalid("Value must be JSON-serializable")}if(t===void 0)throw u.kvValueInvalid("Value must be JSON-serializable");let r=Buffer.byteLength(t,"utf8");if(r>We)throw u.kvValueTooLarge(`Value exceeds maximum size of ${We} bytes (got ${r})`,We)}function X(e){rr(e)}function he(e,t){let r=e[t];if(typeof r!="function")throw new Error(`KV driver is missing ${t}`);return r}function or(e){let t=he(e,"getItem"),r=he(e,"setItem"),n=he(e,"removeItem"),o=he(e,"hasItem"),s=e.getKeys;return{...e,getItem(i,a){return X(i),t(i,a)},setItem(i,a,c){return X(i),r(i,a,c)},removeItem(i,a){return X(i),n(i,a)},hasItem(i,a){return X(i),o(i,a)},getKeys(i,a){return i.length>0&&X(i),s(i,a)}}}function we(e){return Gn({driver:or(e)})}import{defineDriver as Xn}from"unstorage";function Zn(e){try{return JSON.parse(e)}catch{return e}}var Qn=Xn(e=>{let{client:t}=e;return{name:"helix-kv",async getItem(r){let n=await t.get(r);return n===null?null:JSON.stringify(n)},async setItem(r,n){await t.set(r,Zn(n))},async removeItem(r){await t.delete(r)},async hasItem(r){return await t.has(r)},async getKeys(){throw new Error("KV key listing is not supported")}}});function sr(e){return Qn({client:e})}import no from"ky";import{z as w}from"zod";async function B(e){if(!(e.headers.get("content-type")??"").includes("application/json")){let r=await e.text();return r.length>0?r:void 0}return e.json()}var eo={production:"https://api.tray.io"};function ir(e){return eo[e]}function to(e){return`/private/v1/helix/projects/${encodeURIComponent(e)}/storage/kv`}function ro(e){return e.split("/").map(encodeURIComponent).join("/")}function Z(e,t,r){return`${e}${to(t)}/${ro(r)}`}var oo=6e4,ze=w.lazy(()=>w.union([w.string(),w.number(),w.boolean(),w.null(),w.array(ze),w.record(ze)])),so=w.object({projectId:w.string(),key:w.string(),value:ze,type:w.enum(["string","number","boolean","null","array","object"]),organizationId:w.string(),scope:w.string(),createdBy:w.string(),createdAt:w.number(),updatedBy:w.string(),updatedAt:w.number()});function io(){let e=D(),t=I(),r=!!(e&&e.trim().length>0),n=!!(t&&t.trim().length>0);if(!r&&!n)throw u.missingExecutionCredentials();let o={Accept:"application/json"};return r&&(o[O]=e),n&&(o[T]=t),o}function ao(e){if(e!==null&&typeof e=="object"){let t=e;if(typeof t.message=="string")return t.message;if(typeof t.error=="string")return t.error}return String(e??"unknown error")}function be(e,t){throw u.kvCallFailed(e,ao(t),v(t))}async function ve(e,t,r={}){try{let n=await no(t,{method:e,headers:io(),...r.json!==void 0?{json:r.json}:{},throwHttpErrors:!1,timeout:oo}),o=e==="head"?void 0:await B(n);return{status:n.status,body:o}}catch(n){if(n instanceof u)throw n;let o=n instanceof Error?n.message??String(n):String(n);throw u.kvCallFailed(0,o)}}function ar(e){let t=ir(e.env),{projectId:r}=e;return{async get(n){let{status:o,body:s}=await ve("get",Z(t,r,n));if(o===404)return null;(o<200||o>=300)&&be(o,s);let i=so.safeParse(s);if(!i.success)throw u.kvCallFailed(o,"platform returned malformed KeyValueEntry",v(s));return i.data.value},async set(n,o){let{status:s,body:i}=await ve("put",Z(t,r,n),{json:{value:o}});(s<200||s>=300)&&be(s,i)},async delete(n){let{status:o,body:s}=await ve("delete",Z(t,r,n));o!==204&&be(o,s)},async has(n){let{status:o,body:s}=await ve("head",Z(t,r,n));if(o===200)return!0;if(o===404)return!1;be(o,s)}}}function Se(e){return{getItem:(t,r)=>e.getItem(t,r),removeItem:(t,r)=>e.removeItem(t,r),hasItem:(t,r)=>e.hasItem(t,r),setItem:async(t,r,n)=>{nr(r),await e.setItem(t,r,n)}}}function co(){let e=b();if(e.kind!=="provisioned")throw u.kvRequiresProvisioning();return{projectId:e.projectId,env:e.env}}function cr(e){let t=co(),r=e??ar(t),n=we(sr(r));return Se(n)}import uo from"unstorage/drivers/memory";var Je;function lo(){return Je||(Je=we(uo())),Je}function ur(){return Se(lo())}function fo(){return typeof __TRAY_SDK_MODE__<"u"?__TRAY_SDK_MODE__==="lambda":y().mode==="lambda"}function dr(){return fo()?cr():ur()}import{createHash as go}from"crypto";import{mkdir as yo,readFile as gr,readdir as yr,rm as fr,unlink as ho,writeFile as pr}from"fs/promises";import{dirname as wo}from"path";async function po(e){let t=e.getReader(),r=[],n=0;for(;;){let{done:o,value:s}=await t.read();if(o)break;if(s){if(n+=s.byteLength,n>V)throw await t.cancel(),u.filesValueTooLarge(`File exceeds maximum size of ${V} bytes (got more than ${V})`,V);r.push(s)}}return Buffer.concat(r)}async function M(e){return Buffer.isBuffer(e)?e:typeof e=="string"?Buffer.from(e,"utf-8"):e instanceof ReadableStream?po(e):Buffer.from(e)}var mo={pdf:"application/pdf",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",json:"application/json",txt:"text/plain",html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",xml:"application/xml",zip:"application/zip"},lr="application/octet-stream";function Ee(e){let t=e.lastIndexOf(".");if(t===-1||t===e.length-1)return lr;let r=e.slice(t+1).toLowerCase();return mo[r]??lr}function H(){let e=y().projectRoot;if(!e)throw u.filesNotAvailable();return e}async function U(e){try{return await e()}catch(t){if(t instanceof u)throw t;let r=t?.code;throw r?u.filesCallFailed(0,`Local file storage operation failed: ${r}`):u.filesCallFailed(0,"Local file storage operation failed: unknown error")}}function xe(e,t){return{path:e,size:t.size,contentType:t.contentType,lastModified:new Date(t.lastModified),metadata:t.metadata,etag:t.etag}}async function Ye(e){try{let t=await gr(ae(H(),e),"utf-8");return JSON.parse(t)}catch(t){if(t.code==="ENOENT")return null;throw t}}async function mr(e){await yo(wo(e),{recursive:!0})}async function bo(e,t){let r=ce(e,t),n;try{n=await yr(r,{withFileTypes:!0})}catch(o){if(o.code==="ENOENT")return[];throw o}return n.filter(o=>o.isFile()).map(o=>t.length===0?o.name:`${t}/${o.name}`)}async function hr(e,t){let r=ce(e,t),n;try{n=await yr(r,{withFileTypes:!0})}catch(s){if(s.code==="ENOENT")return[];throw s}let o=[];for(let s of n){let i=t.length===0?s.name:`${t}/${s.name}`;s.isDirectory()?o.push(...await hr(e,i)):s.isFile()&&o.push(i)}return o}function wr(){return{async put(e,t,r){return U(async()=>{let n=H(),o=await M(t),s=r?.contentType??Ee(e),i=go("sha1").update(o).digest("hex"),a=new Date,c=ie(n,e);await mr(c),await pr(c,o);let d={size:o.byteLength,contentType:s,lastModified:a.toISOString(),metadata:r?.metadata??{},etag:i},f=ae(n,e);return await mr(f),await pr(f,JSON.stringify(d)),xe(e,d)})},async get(e){return U(async()=>{let t=await Ye(e);return t?{data:await gr(ie(H(),e)),metadata:xe(e,t)}:null})},async head(e){return U(async()=>{let t=await Ye(e);return t?xe(e,t):null})},async delete(e){return U(async()=>{let t=H();await Promise.all([ie(t,e),ae(t,e)].map(async r=>{try{await ho(r)}catch(n){if(n.code!=="ENOENT")throw n}}))})},async deleteMany(e){return U(async()=>{let t=H(),r=await hr(t,e);return await Promise.all([fr(ce(t,e),{recursive:!0,force:!0}),fr(wt(t,e),{recursive:!0,force:!0})]),{deleted:r.length}})},async list(e,t){return U(async()=>{let r=H(),n=t?.limit??100,s=(await bo(r,e??"")).slice(0,n);return{files:(await Promise.all(s.map(async a=>{let c=await Ye(a);return c?xe(a,c):null}))).filter(a=>a!==null),cursor:null}})},async getUploadUrl(e,t){let r=y().devServerUrl;if(!r)throw u.filesNotAvailable();return{url:`${r}/_helix/files/${e}`,expiresAt:F(t?.expiresIn)}},async getDownloadUrl(e,t){let r=y().devServerUrl;if(!r)throw u.filesNotAvailable();return{url:`${r}/_helix/files/${e}`,expiresAt:F(t?.expiresIn)}}}}import{createHash as Ro}from"crypto";var vo={production:"https://api.tray.io"};function Ce(e){return vo[e]}function So(e){return`/private/v1/helix/files/projects/${encodeURIComponent(e)}`}function Q(e,t){return`${e}${So(t)}`}function ee(e,t,r){return`${Q(e,t)}/${encodeURIComponent(r)}`}function ke(e,t,r){return`${ee(e,t,r)}/upload`}function Re(e,t,r){return`${ee(e,t,r)}/download`}function br(e,t,r,n){let o=new URLSearchParams({name:n});return r&&o.set("parentFolder",r),`${Q(e,t)}/file?${o.toString()}`}function vr(e,t,r,n){let o=new URLSearchParams({limit:String(n)});return r&&o.set("id",r),`${Q(e,t)}?${o.toString()}`}import Xe from"ky";import{z as S}from"zod";var Ze=6e4,Sr=S.object({id:S.string(),workspaceId:S.string(),projectId:S.string(),parentFolder:S.string().nullable().optional(),name:S.string(),size:S.number().nullable().optional(),objectType:S.enum(["Folder","File"]),contentType:S.string().nullable().optional(),createdAt:S.string(),updatedAt:S.string()}),Eo=S.object({path:S.array(S.object({id:S.string(),name:S.string()})),elements:S.array(Sr)});function Qe(){let e=D(),t=I(),r=!!(e&&e.trim().length>0),n=!!(t&&t.trim().length>0);if(!r&&!n)throw u.missingExecutionCredentials();let o={Accept:"application/json"};return r&&(o[O]=e),n&&(o[T]=t),o}function Er(e){if(e!==null&&typeof e=="object"){let t=e;if(typeof t.message=="string")return t.message;if(typeof t.error=="string")return t.error}return String(e??"unknown error")}function _(e,t){throw u.filesCallFailed(e,Er(t),v(t))}function xo(e,t){return e===400&&Er(t).toLowerCase()==="resource not found"}async function Co(e){let t=new Response(e),r=t.headers.get("content-type")??"multipart/form-data",n=await t.arrayBuffer();return{body:Buffer.from(n),contentType:r}}async function te(e,t,r={}){try{let n=await Xe(t,{method:e,headers:Qe(),...r.json!==void 0?{json:r.json}:{},throwHttpErrors:!1,timeout:Ze}),o=await B(n);return{status:n.status,body:o}}catch(n){if(n instanceof u)throw n;let o=n instanceof Error?n.message:String(n);throw u.filesCallFailed(0,o)}}function Ge(e,t){let r=Sr.safeParse(t);if(!r.success)throw u.filesCallFailed(e,"platform returned malformed ObjectMetadata",v(t));return r.data}function xr(e){let t=Ce(e.env),{projectId:r}=e;return{async createMetadata(n){let{status:o,body:s}=await te("post",Q(t,r),{json:n});return(o<200||o>=300)&&_(o,s),Ge(o,s)},async getByName(n,o){let{status:s,body:i}=await te("get",br(t,r,n,o));return s===404||xo(s,i)?null:((s<200||s>=300)&&_(s,i),Ge(s,i))},async getById(n){let{status:o,body:s}=await te("get",ee(t,r,n));return o===404?null:((o<200||o>=300)&&_(o,s),Ge(o,s))},async listChildren(n,o){let{status:s,body:i}=await te("get",vr(t,r,n,o));(s<200||s>=300)&&_(s,i);let a=Eo.safeParse(i);if(!a.success)throw u.filesCallFailed(s,"platform returned malformed listing",v(i));return a.data},async uploadContent(n,o,s,i){let a=new FormData;a.append("fileUploadContentInput",new Blob([new Uint8Array(o)],{type:i}),s);let{body:c,contentType:d}=await Co(a),f;try{f=await Xe(ke(t,r,n),{method:"post",headers:{...Qe(),"content-type":d},body:new Uint8Array(c),throwHttpErrors:!1,timeout:Ze})}catch(l){if(l instanceof u)throw l;let p=l instanceof Error?l.message:String(l);throw u.filesCallFailed(0,p)}let m=await B(f);(f.status<200||f.status>=300)&&_(f.status,m)},async downloadContent(n){let o;try{o=await Xe(Re(t,r,n),{method:"get",headers:Qe(),throwHttpErrors:!1,timeout:Ze})}catch(i){if(i instanceof u)throw i;let a=i instanceof Error?i.message:String(i);throw u.filesCallFailed(0,a)}if(o.status<200||o.status>=300){let i=await B(o);_(o.status,i)}let s=await o.arrayBuffer();return Buffer.from(s)},async deleteById(n){let{status:o,body:s}=await te("delete",ee(t,r,n));o===204||o===404||(o<200||o>=300)&&_(o,s)}}}function et(e){return e.split("/").filter(t=>t.length>0)}function tt(e){return e instanceof u&&e.detail.kind==="files_call_failed"&&e.detail.status===409}async function ko(e,t,r){let n=await e.getByName(t,r);if(n)return n;try{return await e.createMetadata({parentFolder:t,objectType:"Folder",name:r})}catch(o){if(tt(o)){let s=await e.getByName(t,r);if(s)return s}throw o}}async function rt(e,t){let r=et(t),n=r[r.length-1],o;for(let s of r.slice(0,-1))o=(await ko(e,o,s)).id;return{parentFolder:o,name:n}}async function re(e,t){let r=et(t),n=r[r.length-1],o;for(let s of r.slice(0,-1)){let i=await e.getByName(o,s);if(!i||i.objectType!=="Folder")return null;o=i.id}return{parentFolder:o,name:n}}async function nt(e,t){if(t.length===0)return;let r=et(t),n;for(let o of r){let s=await e.getByName(n,o);if(!s||s.objectType!=="Folder")return null;n=s.id}return n}var To=500,Io=8;async function Po(e,t,r){let n=new Array(e.length),o=0;async function s(){for(;o<e.length;){let i=o++;n[i]=await r(e[i])}}return await Promise.all(Array.from({length:Math.min(t,e.length)},s)),n}function Ao(){let e=b();if(e.kind!=="provisioned")throw u.filesRequiresProvisioning();return{projectId:e.projectId,env:e.env}}function _o(e){return Ro("sha1").update(`${e.id}:${e.updatedAt}:${e.size??0}`).digest("hex")}function Te(e,t,r){return{path:e,size:t.size??0,contentType:t.contentType??r??"application/octet-stream",lastModified:new Date(t.updatedAt),metadata:{},etag:_o(t)}}async function Cr(e,t,r,n){try{return await e.createMetadata({parentFolder:t,objectType:"File",contentType:n,name:r})}catch(o){if(tt(o)){let s=await e.getByName(t,r);if(s)return s}throw o}}async function kr(e,t){let{elements:r}=await e.listChildren(t,To);return(await Po(r,Io,async o=>{let s=o.objectType==="Folder"?await kr(e,o.id):1;return await e.deleteById(o.id),s})).reduce((o,s)=>o+s,0)}function Rr(e){let t=Ao(),r=e??xr(t),n=Ce(t.env),{projectId:o}=t;return{async put(s,i,a){let{parentFolder:c,name:d}=await rt(r,s),f=await M(i),m=a?.contentType??Ee(s),l=await r.getByName(c,d);if(l&&l.objectType!=="File")throw u.filesCallFailed(409,`A folder already exists at "${s}"`);let p=l??await Cr(r,c,d,m);await r.uploadContent(p.id,f,d,m);let g=await r.getById(p.id);return Te(s,g??p,m)},async get(s){let i=await re(r,s);if(!i)return null;let a=await r.getByName(i.parentFolder,i.name);return!a||a.objectType!=="File"?null:{data:await r.downloadContent(a.id),metadata:Te(s,a)}},async head(s){let i=await re(r,s);if(!i)return null;let a=await r.getByName(i.parentFolder,i.name);return!a||a.objectType!=="File"?null:Te(s,a)},async delete(s){let i=await re(r,s);if(!i)return;let a=await r.getByName(i.parentFolder,i.name);a&&await r.deleteById(a.id)},async deleteMany(s){let i=await nt(r,s);if(i===null)return{deleted:0};let a=await kr(r,i);return s.length>0&&i!==void 0&&await r.deleteById(i),{deleted:a}},async list(s,i){let a=await nt(r,s??"");if(a===null)return{files:[],cursor:null};let c=i?.limit??100,{elements:d}=await r.listChildren(a,c);return{files:d.filter(m=>m.objectType==="File").map(m=>Te(s?`${s}/${m.name}`:m.name,m)),cursor:null}},async getUploadUrl(s,i){let{parentFolder:a,name:c}=await rt(r,s),f=await r.getByName(a,c)??await Cr(r,a,c,i?.contentType);return{url:ke(n,o,f.id),expiresAt:F(i?.expiresIn)}},async getDownloadUrl(s,i){let a=await re(r,s),c=a?await r.getByName(a.parentFolder,a.name):null;if(!c||c.objectType!=="File")throw u.filesCallFailed(404,`File not found: ${s}`);return{url:Re(n,o,c.id),expiresAt:F(i?.expiresIn)}}}}function Tr(e){return{async put(t,r,n){P(t);let o=await M(r);return ht(o.byteLength),e.put(t,o,n)},async get(t){return P(t),e.get(t)},async head(t){return P(t),e.head(t)},async delete(t){return P(t),e.delete(t)},async deleteMany(t){let r=Ae(t);return _e(r),e.deleteMany(r)},async list(t,r){let n=Ae(t??"");return _e(n),e.list(n,r)},async getUploadUrl(t,r){return P(t),e.getUploadUrl(t,r)},async getDownloadUrl(t,r){return P(t),e.getDownloadUrl(t,r)}}}function Oo(){return typeof __TRAY_SDK_MODE__<"u"?__TRAY_SDK_MODE__==="lambda":y().mode==="lambda"}function Ir(){let e=Oo()?Rr():wr();return Tr(e)}function Pr(e,t){let{statusCode:r,message:n}=Do(t.detail);return e.node.res.statusCode=r,{error:n,statusCode:r}}function Do(e){switch(e.kind){case"unknown_alias":return{statusCode:400,message:"Unknown authentication alias"};case"input_validation_failed":return{statusCode:400,message:"Input validation failed"};case"output_validation_failed":return{statusCode:500,message:"Internal server error"};case"config_load_failed":return{statusCode:500,message:"Configuration error"};case"broker_error":return{statusCode:502,message:"Broker error"};case"unsupported_body_type":return{statusCode:400,message:"Unsupported request body type"};case"unsupported_scheme":return{statusCode:400,message:"Unsupported URL scheme"};case"missing_execution_credentials":return{statusCode:401,message:"Missing execution credentials"};case"missing_tray_token":return{statusCode:500,message:"Missing Tray token"};case"db_call_failed":return{statusCode:502,message:e.message};case"db_query_failed":return{statusCode:502,message:`Database query failed: ${e.message}`};case"db_invalid_parameters":return{statusCode:400,message:e.message};case"kv_key_invalid":return{statusCode:400,message:e.message};case"kv_value_invalid":return{statusCode:400,message:e.message};case"kv_value_too_large":return{statusCode:400,message:e.message};case"kv_not_available":return{statusCode:501,message:"Key-value store is not available in this environment"};case"kv_call_failed":return{statusCode:502,message:"Key-value store request failed"};case"kv_requires_provisioning":return{statusCode:500,message:"Internal server error"};case"files_path_invalid":return{statusCode:400,message:e.message};case"files_value_invalid":return{statusCode:400,message:e.message};case"files_value_too_large":return{statusCode:400,message:e.message};case"files_not_available":return{statusCode:501,message:"File storage is not available in this environment"};case"files_call_failed":return{statusCode:502,message:"File storage request failed"};case"files_requires_provisioning":return{statusCode:500,message:"Internal server error"};default:return{statusCode:500,message:`Unhandled error kind: ${e.kind}`}}}var Fo=["authorization","x-tray-token","set-cookie","x-kong-request-id","traceparent","x-real-ip","cookie"];function Lo(e){return e.toLowerCase().includes("tray_lid")}function ot(e){let t={};for(let[r,n]of Object.entries(e))if(!Fo.includes(r.toLowerCase())){if(r.toLowerCase()==="cookie"&&n){let o=n.split(";").map(s=>s.trim()).filter(s=>{let i=s.split("=")[0].trim();return!Lo(i)}).join("; ");o&&(t[r]=o);continue}t[r]=n}return t}function Ho(e,t){let{inputSchema:r,outputSchema:n}=zo(t),o=e;return Bo(async s=>{let i=y(),{executionId:a,userId:c,deploymentId:d}=Jo(i,s),f=Date.now(),m=new Date().toISOString(),l=Mo(s),p=Uo(s).pathname,g=Yo(),h=Ht(),$=`${l} ${p}`;Be();let K={hasDb:!1,hasExternal:!1,hasAuth:!1,hasError:!1};return $o(()=>pe.run(K,()=>fe.run(a,async()=>{let oe=await Ko(s,r);if(!oe.ok)return{response:oe.response,errored:!1,errorMessage:null};let Hr=Xo(s,oe.input,g,h,l,p,a,d,c);return qo(o,Hr,n,s,h,a,d,{method:l,path:p,rawInput:oe.input})})),{executionId:a,deploymentId:d,routeOrJob:$,startedAt:m,startMs:f,userId:c,flags:K})})}async function $o(e,t){let r=!1,n=null;try{let o=await e();return r=o.errored,n=o.errorMessage,o.response}finally{Ue({...t,errored:r,errorMessage:n}),await Me()}}async function Ko(e,t){try{return{ok:!0,input:await Ut(e,t)}}catch(r){let n=Go(e,r);if(n)return{ok:!1,response:n};throw r}}async function qo(e,t,r,n,o,s,i,a){return k.startActiveSpan("function",{root:!0,kind:No.SERVER,attributes:{method:a.method,route:a.path,executionId:s,...i?{deploymentId:i}:{}}},async c=>{t.traceId=c.spanContext().traceId;let d=ot(Or(n)),f=c.spanContext().spanId;x(f,"input",a.rawInput),x(f,"request",{method:a.method,path:a.path,headers:d,body:a.rawInput});let m=!1,l=null,p,g;try{let h=await pt.run(t,()=>e(t));if(p=h,h==null)n.node.res.statusCode=204,g="";else if(h instanceof Response)g=h;else if(r){let $=r.safeParse(h);if(!$.success){let K=Object.keys($.error.flatten().fieldErrors);throw o.error("Output validation failed",{fields:K,executionId:s}),u.outputValidationFailed(K)}g=$.data}else g=h}catch(h){m=!0,l=h instanceof Error?h.message:String(h),C("hasError"),g=Vo(h,n,o,s)}finally{Wo(c,n,{errored:m,errorMessage:l,handlerResult:p,response:g})}return{response:g,errored:m,errorMessage:l}})}function Vo(e,t,r,n){if(e instanceof Y)return t.node.res.statusCode=e.statusCode,{error:e.message,statusCode:e.statusCode};if(mt(e))return Pr(t,e);r.error("Unhandled error in handler",{error:e instanceof Error?e.message:String(e),executionId:n}),t.node.res.statusCode=500;let o=process.env.NODE_ENV==="development";return{error:o&&e instanceof Error?e.message:"Internal server error",statusCode:500,...o&&e instanceof Error&&e.stack?{stack:e.stack}:{}}}function Wo(e,t,r){let n=e.spanContext().spanId;e.setAttribute("statusCode",t.node.res.statusCode),!r.errored&&r.handlerResult!==void 0&&x(n,"output",r.handlerResult),x(n,"response",r.response);let o=pe.getStore();e.setAttribute("hasAuth",o?.hasAuth??!1),e.setAttribute("hasExternal",o?.hasExternal??!1),e.setAttribute("hasDb",o?.hasDb??!1),e.setAttribute("status",r.errored?"error":"success");let s=r.errored||(o?.hasError??!1);e.setStatus({code:s?Ar.ERROR:Ar.OK,...r.errorMessage?{message:r.errorMessage}:{}}),e.end()}function zo(e){if(!e)return{inputSchema:void 0,outputSchema:void 0};if(e instanceof Object&&"_def"in e)return{inputSchema:e,outputSchema:void 0};if(typeof e=="object"&&("input"in e||"output"in e)){let t=e;return{inputSchema:t.input,outputSchema:t.output}}return{inputSchema:e,outputSchema:void 0}}function Jo(e,t){let r=e.mode==="lambda",n=(r?e.executionId:_r(t,"x-tray-execution-id"))??jo(),o=(r?e.userId:_r(t,"x-tray-user-id"))??null,s=r?e.deploymentId??null:null;return{executionId:n,userId:o,deploymentId:s}}function Yo(){try{return b().config??{}}catch(e){return console.warn(`[helix-sdk] Config not loaded: ${e instanceof Error?e.message:String(e)}. Using empty config.`),{}}}function Go(e,t){if(!(t instanceof Error)||!("statusCode"in t)||!("data"in t))return null;let r=t.statusCode,n=t.data;e.node.res.statusCode=r;let o=n&&typeof n=="object"&&"fieldErrors"in n?n.fieldErrors:void 0;return{error:"Input validation failed",statusCode:r,...o?{fields:Object.keys(o)}:{}}}function Xo(e,t,r,n,o,s,i,a,c){return{input:t,method:o,path:s,headers:ot(Or(e)),http:Gt(),db:d=>Ve(d),kv:()=>dr(),files:()=>Ir(),log:n,config:r,status:$t(e),error:Kt(),state:{},request:e,executionId:i,deploymentId:a,userId:c,identity:c!==null?{user:{id:c}}:null,traceId:""}}function Zo(e){return e}import{resolve as st}from"path";import{existsSync as Lr}from"fs";import{loadConfig as es}from"c12";import{z as E}from"zod";import{z as Qo}from"zod";var Dr=["production"],Ie=Qo.enum(Dr);var it=E.string().uuid("projectId must be a valid UUID"),at=E.string().min(1,"workspaceId must be a non-empty string"),ts=E.object({name:E.string().min(1,"name is required"),projectId:it.optional(),workspaceId:at.optional(),env:Ie.default("production"),authentications:E.record(E.string()).optional().default({}),config:E.record(E.unknown()).optional().default({})}),Fr=E.object({name:E.string().min(1,"name is required"),workspaceId:at.optional(),env:Ie,authentications:E.record(E.string()),config:E.record(E.unknown())}),rs=E.discriminatedUnion("kind",[Fr.extend({kind:E.literal("provisioned"),projectId:it}),Fr.extend({kind:E.literal("unprovisioned")})]),jr=["helix","tray"],Nr=["ts","mts","cts","js","mjs","cjs"];function Pe(e){for(let t of jr)for(let r of Nr){let n=st(e,`${t}.config.${r}`);if(Lr(n))return n}}function ns(e){for(let t of jr)if(Nr.some(r=>Lr(st(e,`${t}.config.${r}`))))return t;return"helix"}function ct(e){return{name:ns(e),cwd:e,rcFile:!1,globalRc:!1,packageJson:!1,dotenv:!1,extend:!1}}function ut(e,t){if(e!==null&&typeof e=="object"&&"extends"in e)throw u.configLoadFailed(`helix.config.ts at ${t}: 'extends' is not supported \u2014 remove the field`);let r=ts.safeParse(e);if(!r.success){let a=r.error.issues.map(c=>c.message).join("; ");throw u.configLoadFailed(`Invalid helix.config.ts at ${t}: ${a}`)}let{projectId:n,workspaceId:o,...s}=r.data,i=o!==void 0?{workspaceId:o}:{};return n!==void 0?{kind:"provisioned",projectId:n,...s,...i}:{kind:"unprovisioned",...s,...i}}async function ne(e){let t=e??process.cwd(),r;try{r=await es(ct(t))}catch(o){throw u.configLoadFailed(`Failed to load helix.config.ts: ${o instanceof Error?o.message:String(o)}`)}let n=r._configFile??Pe(t);if(!n)throw u.configLoadFailed(`helix.config.ts not found at ${st(t,"helix.config.ts")}`);return ut(r.config,n)}var Br="WORKSPACE_ID_REQUIRED";function os(e){if(e.workspaceId===void 0)throw Object.assign(new Error("No workspaceId found in helix.config.ts. Discover & choose one \u2014 self-serve fix: run `helix workspace select`; agent-driven fix: call the `tray_list_workspaces` MCP tool. Already know the id? Run `helix workspace set <id>` or call the `tray_set_workspace_id` MCP tool. deploy cannot proceed without a workspace."),{code:Br});return e.workspaceId}import{existsSync as ss,watch as is,writeSync as as}from"fs";import{join as cs,resolve as us}from"path";import{watchConfig as ds}from"c12";function ls(e,t){let r=e instanceof Error?e.message:String(e);as(2,`[helix-watch] ${t.phase} error: ${r}
|
|
8
|
+
`)}function dt(){return{kind:"unprovisioned",name:"",authentications:{},config:{},env:"production"}}var fs=/^(?:helix|tray)\.config\.(?:m|c)?[jt]s$/,Mr=new Set;function Ur(e){return Pe(e)!==void 0}async function ps(e,t){if(Ur(e.cwd))try{return{current:await ne(e.cwd),initialLoadSucceeded:!0}}catch(r){return t(r,{phase:"reload"}),{current:dt(),initialLoadSucceeded:!1}}if(e.watch){let r=us(e.cwd);Mr.has(r)||(process.stderr.write(`warning: no helix.config.ts found at ${e.cwd}; tray running with default config \u2014 create one via \`helix init\`
|
|
9
|
+
`),Mr.add(r))}return{current:dt(),initialLoadSucceeded:!1}}var lt=class{constructor(t,r,n){this.cwd=t;this.onError=r;this.emit=n}cwd;onError;emit;stopped=!1;directoryWatcher=null;c12Unwatch=null;c12AttachPromise=null;updateChain=Promise.resolve();start(t){t?this.attachC12Watcher():this.attachCreationWatcher()}watcherReady(){return this.c12AttachPromise===null?Promise.resolve():this.c12AttachPromise.catch(()=>{})}async stop(){this.stopped=!0,this.directoryWatcher&&(this.directoryWatcher.close(),this.directoryWatcher=null),this.c12AttachPromise&&await this.c12AttachPromise.catch(t=>this.onError(t,{phase:"attach"})),this.c12Unwatch&&(await this.c12Unwatch(),this.c12Unwatch=null)}attachC12Watcher(){this.c12AttachPromise===null&&(this.c12AttachPromise=ds({...ct(this.cwd),onUpdate:({newConfig:t})=>{this.stopped||(this.updateChain=this.updateChain.then(async()=>{if(this.stopped)return;let r;try{r=ut(t.config,this.cwd)}catch(n){this.onError(n,{phase:"validation"});return}try{this.emit(r)}catch(n){this.onError(n,{phase:"reload"})}}))}}).then(async t=>{if(this.stopped){t.unwatch();return}this.c12Unwatch=t.unwatch;let{watch:r}=await import("chokidar"),n=r(this.cwd,{persistent:!1,depth:0});try{await new Promise((o,s)=>{n.once("ready",o),n.once("error",s)})}finally{await n.close()}}).catch(t=>{this.onError(t,{phase:"attach"})}))}attachCreationWatcher(){try{this.directoryWatcher=is(this.cwd,{persistent:!1},(t,r)=>{if(this.stopped||!r)return;let n=r.toString();fs.test(n)&&ss(cs(this.cwd,n))&&(this.updateChain=this.updateChain.then(async()=>{if(this.stopped)return;let o;try{o=await ne(this.cwd)}catch(i){this.onError(i,{phase:"reload"});return}if(this.stopped)return;this.emit(o);let s=this.directoryWatcher;s&&(this.directoryWatcher=null,s.close()),this.attachC12Watcher()}))}),this.directoryWatcher.on("error",t=>{this.onError(t,{phase:"attach"})})}catch(t){this.onError(t,{phase:"attach"})}}};async function ms(e){let t=e.onError??ls,r=new Set,n=await ps(e,t),o=n.current;function s(a){o=a;for(let c of[...r])try{c(a)}catch(d){t(d,{phase:"reload"})}}let i=new lt(e.cwd,t,s);return e.watch&&i.start(n.initialLoadSucceeded),{get(){return o},async reload(){if(!Ur(e.cwd)){let a=dt();return s(a),a}try{let a=await ne(e.cwd);return s(a),a}catch(a){return t(a,{phase:"reload"}),o}},subscribe(a){return r.add(a),()=>{r.delete(a)}},async stop(){r.clear(),await i.stop()},ready(){return i.watcherReady()}}}export{Dr as ENVIRONMENT_VALUES,Br as WORKSPACE_ID_REQUIRED_CODE,ms as createConfigService,Zo as defineConfig,Ho as defineFunction,Ie as environmentSchema,$r as getContext,y as getSdkConfig,ne as loadConfig,rs as loadedTrayConfigSchema,it as projectIdSchema,os as requireWorkspaceId,Pe as resolveConfigFile,yn as runWithinAppSpan,at as workspaceIdSchema};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { L as LoadedTrayConfig } from '../sdk-config-B-Vfaig8.js';
|
|
2
|
+
export { S as SdkConfigInput, s as setSdkConfig } from '../sdk-config-B-Vfaig8.js';
|
|
3
|
+
import 'zod';
|
|
4
|
+
|
|
5
|
+
/** BroadcastChannel name for parent→worker config updates. */
|
|
6
|
+
declare const CONFIG_BRIDGE_CHANNEL = "tray-config-bridge";
|
|
7
|
+
/** Worker-bootstrap setter — called by the dev-server worker plugin. */
|
|
8
|
+
declare function setActiveConfig(config: LoadedTrayConfig): void;
|
|
9
|
+
/** SDK runtime accessor. Throws if slot unseeded — surfaces missing worker bootstrap. */
|
|
10
|
+
declare function getActiveConfig(): LoadedTrayConfig;
|
|
11
|
+
/** Test-only cleanup hook to drop worker-local state between cases. */
|
|
12
|
+
declare function clearActiveConfig(): void;
|
|
13
|
+
|
|
14
|
+
declare function assertValidPath(path: string): void;
|
|
15
|
+
|
|
16
|
+
type SdkErrorDetail = {
|
|
17
|
+
readonly kind: "unknown_alias";
|
|
18
|
+
alias: string;
|
|
19
|
+
available: string[];
|
|
20
|
+
} | {
|
|
21
|
+
readonly kind: "input_validation_failed";
|
|
22
|
+
fields: string[];
|
|
23
|
+
} | {
|
|
24
|
+
readonly kind: "output_validation_failed";
|
|
25
|
+
fields: string[];
|
|
26
|
+
} | {
|
|
27
|
+
readonly kind: "config_load_failed";
|
|
28
|
+
cause: string;
|
|
29
|
+
} | {
|
|
30
|
+
readonly kind: "broker_error";
|
|
31
|
+
status: number;
|
|
32
|
+
message: string;
|
|
33
|
+
body?: string;
|
|
34
|
+
} | {
|
|
35
|
+
readonly kind: "unsupported_body_type";
|
|
36
|
+
actualType: string;
|
|
37
|
+
} | {
|
|
38
|
+
readonly kind: "unsupported_scheme";
|
|
39
|
+
scheme: string;
|
|
40
|
+
} | {
|
|
41
|
+
readonly kind: "missing_execution_credentials";
|
|
42
|
+
} | {
|
|
43
|
+
readonly kind: "missing_tray_token";
|
|
44
|
+
} | {
|
|
45
|
+
readonly kind: "db_call_failed";
|
|
46
|
+
message: string;
|
|
47
|
+
cause?: unknown;
|
|
48
|
+
} | {
|
|
49
|
+
readonly kind: "db_query_failed";
|
|
50
|
+
message: string;
|
|
51
|
+
} | {
|
|
52
|
+
readonly kind: "db_invalid_parameters";
|
|
53
|
+
message: string;
|
|
54
|
+
} | {
|
|
55
|
+
readonly kind: "kv_key_invalid";
|
|
56
|
+
message: string;
|
|
57
|
+
} | {
|
|
58
|
+
readonly kind: "kv_value_invalid";
|
|
59
|
+
message: string;
|
|
60
|
+
} | {
|
|
61
|
+
readonly kind: "kv_value_too_large";
|
|
62
|
+
message: string;
|
|
63
|
+
maxBytes: number;
|
|
64
|
+
} | {
|
|
65
|
+
readonly kind: "kv_not_available";
|
|
66
|
+
} | {
|
|
67
|
+
readonly kind: "kv_call_failed";
|
|
68
|
+
status: number;
|
|
69
|
+
message: string;
|
|
70
|
+
body?: string;
|
|
71
|
+
} | {
|
|
72
|
+
readonly kind: "kv_requires_provisioning";
|
|
73
|
+
} | {
|
|
74
|
+
readonly kind: "files_path_invalid";
|
|
75
|
+
message: string;
|
|
76
|
+
} | {
|
|
77
|
+
readonly kind: "files_value_invalid";
|
|
78
|
+
message: string;
|
|
79
|
+
} | {
|
|
80
|
+
readonly kind: "files_value_too_large";
|
|
81
|
+
message: string;
|
|
82
|
+
maxBytes: number;
|
|
83
|
+
} | {
|
|
84
|
+
readonly kind: "files_not_available";
|
|
85
|
+
} | {
|
|
86
|
+
readonly kind: "files_call_failed";
|
|
87
|
+
status: number;
|
|
88
|
+
message: string;
|
|
89
|
+
body?: string;
|
|
90
|
+
} | {
|
|
91
|
+
readonly kind: "files_requires_provisioning";
|
|
92
|
+
};
|
|
93
|
+
declare class SdkError extends Error {
|
|
94
|
+
readonly detail: SdkErrorDetail;
|
|
95
|
+
constructor(detail: SdkErrorDetail);
|
|
96
|
+
get kind(): SdkErrorDetail["kind"];
|
|
97
|
+
static unknownAlias(alias: string, available: string[]): SdkError;
|
|
98
|
+
static inputValidationFailed(fields: string[]): SdkError;
|
|
99
|
+
static outputValidationFailed(fields: string[]): SdkError;
|
|
100
|
+
static configLoadFailed(cause: string): SdkError;
|
|
101
|
+
static brokerError(status: number, message: string, body?: string): SdkError;
|
|
102
|
+
static unsupportedBodyType(actualType: string): SdkError;
|
|
103
|
+
static unsupportedScheme(scheme: string): SdkError;
|
|
104
|
+
static missingExecutionCredentials(): SdkError;
|
|
105
|
+
static missingTrayToken(): SdkError;
|
|
106
|
+
static dbCallFailed(message: string, cause?: unknown): SdkError;
|
|
107
|
+
static dbQueryFailed(message: string): SdkError;
|
|
108
|
+
static dbInvalidParameters(message: string): SdkError;
|
|
109
|
+
static kvKeyInvalid(message: string): SdkError;
|
|
110
|
+
static kvValueInvalid(message: string): SdkError;
|
|
111
|
+
static kvValueTooLarge(message: string, maxBytes: number): SdkError;
|
|
112
|
+
static kvNotAvailable(): SdkError;
|
|
113
|
+
static kvCallFailed(status: number, message: string, body?: string): SdkError;
|
|
114
|
+
static kvRequiresProvisioning(): SdkError;
|
|
115
|
+
static filesPathInvalid(message: string): SdkError;
|
|
116
|
+
static filesValueInvalid(message: string): SdkError;
|
|
117
|
+
static filesValueTooLarge(message: string, maxBytes: number): SdkError;
|
|
118
|
+
static filesNotAvailable(): SdkError;
|
|
119
|
+
static filesCallFailed(status: number, message: string, body?: string): SdkError;
|
|
120
|
+
static filesRequiresProvisioning(): SdkError;
|
|
121
|
+
}
|
|
122
|
+
declare function isSdkError(err: unknown): err is SdkError;
|
|
123
|
+
|
|
124
|
+
/** `path` is already validated (no `..`, no empty segments) by the caller. */
|
|
125
|
+
declare function contentFilePath(projectRoot: string, path: string): string;
|
|
126
|
+
declare function metaFilePath(projectRoot: string, path: string): string;
|
|
127
|
+
|
|
128
|
+
export { CONFIG_BRIDGE_CHANNEL, assertValidPath, clearActiveConfig, contentFilePath, getActiveConfig, isSdkError, metaFilePath, setActiveConfig };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as o,h as t,i as e,j as r,k as i,m as n,r as g,s as p}from"../chunk-J5OA4RGR.js";import{b as f}from"../chunk-W5TFZBQD.js";export{t as CONFIG_BRIDGE_CHANNEL,n as assertValidPath,i as clearActiveConfig,g as contentFilePath,r as getActiveConfig,f as isSdkError,p as metaFilePath,e as setActiveConfig,o as setSdkConfig};
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const projectIdSchema: z.ZodString;
|
|
4
|
+
declare const workspaceIdSchema: z.ZodString;
|
|
5
|
+
declare const trayConfigSchema: z.ZodObject<{
|
|
6
|
+
name: z.ZodString;
|
|
7
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
8
|
+
workspaceId: z.ZodOptional<z.ZodString>;
|
|
9
|
+
env: z.ZodDefault<z.ZodEnum<["production"]>>;
|
|
10
|
+
authentications: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
11
|
+
config: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
name: string;
|
|
14
|
+
env: "production";
|
|
15
|
+
authentications: Record<string, string>;
|
|
16
|
+
config: Record<string, unknown>;
|
|
17
|
+
projectId?: string | undefined;
|
|
18
|
+
workspaceId?: string | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
name: string;
|
|
21
|
+
projectId?: string | undefined;
|
|
22
|
+
workspaceId?: string | undefined;
|
|
23
|
+
env?: "production" | undefined;
|
|
24
|
+
authentications?: Record<string, string> | undefined;
|
|
25
|
+
config?: Record<string, unknown> | undefined;
|
|
26
|
+
}>;
|
|
27
|
+
/** User-facing config type — auth/config optional; Zod defaults fill at load time. */
|
|
28
|
+
type TrayConfig = z.input<typeof trayConfigSchema>;
|
|
29
|
+
/**
|
|
30
|
+
* Runtime validator for the LoadedTrayConfig discriminated union.
|
|
31
|
+
* Used to validate BroadcastChannel payloads before calling setActiveConfig —
|
|
32
|
+
* prevents malformed cross-channel data from corrupting the worker-local
|
|
33
|
+
* config slot.
|
|
34
|
+
*/
|
|
35
|
+
declare const loadedTrayConfigSchema: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
|
|
36
|
+
name: z.ZodString;
|
|
37
|
+
workspaceId: z.ZodOptional<z.ZodString>;
|
|
38
|
+
env: z.ZodEnum<["production"]>;
|
|
39
|
+
authentications: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
40
|
+
config: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
41
|
+
} & {
|
|
42
|
+
kind: z.ZodLiteral<"provisioned">;
|
|
43
|
+
projectId: z.ZodString;
|
|
44
|
+
}, "strip", z.ZodTypeAny, {
|
|
45
|
+
kind: "provisioned";
|
|
46
|
+
name: string;
|
|
47
|
+
projectId: string;
|
|
48
|
+
env: "production";
|
|
49
|
+
authentications: Record<string, string>;
|
|
50
|
+
config: Record<string, unknown>;
|
|
51
|
+
workspaceId?: string | undefined;
|
|
52
|
+
}, {
|
|
53
|
+
kind: "provisioned";
|
|
54
|
+
name: string;
|
|
55
|
+
projectId: string;
|
|
56
|
+
env: "production";
|
|
57
|
+
authentications: Record<string, string>;
|
|
58
|
+
config: Record<string, unknown>;
|
|
59
|
+
workspaceId?: string | undefined;
|
|
60
|
+
}>, z.ZodObject<{
|
|
61
|
+
name: z.ZodString;
|
|
62
|
+
workspaceId: z.ZodOptional<z.ZodString>;
|
|
63
|
+
env: z.ZodEnum<["production"]>;
|
|
64
|
+
authentications: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
65
|
+
config: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
66
|
+
} & {
|
|
67
|
+
kind: z.ZodLiteral<"unprovisioned">;
|
|
68
|
+
}, "strip", z.ZodTypeAny, {
|
|
69
|
+
kind: "unprovisioned";
|
|
70
|
+
name: string;
|
|
71
|
+
env: "production";
|
|
72
|
+
authentications: Record<string, string>;
|
|
73
|
+
config: Record<string, unknown>;
|
|
74
|
+
workspaceId?: string | undefined;
|
|
75
|
+
}, {
|
|
76
|
+
kind: "unprovisioned";
|
|
77
|
+
name: string;
|
|
78
|
+
env: "production";
|
|
79
|
+
authentications: Record<string, string>;
|
|
80
|
+
config: Record<string, unknown>;
|
|
81
|
+
workspaceId?: string | undefined;
|
|
82
|
+
}>]>;
|
|
83
|
+
/** Base fields on all config variants — schema output minus projectId. */
|
|
84
|
+
type LoadedTrayConfigBase = Omit<z.output<typeof trayConfigSchema>, "projectId">;
|
|
85
|
+
/**
|
|
86
|
+
* Discriminated union returned by loadConfig / ConfigService#get.
|
|
87
|
+
* - "provisioned" — projectId present, no optional-chaining needed.
|
|
88
|
+
* - "unprovisioned" — `projectId?: never` structurally excludes it.
|
|
89
|
+
* workspaceId is optional on both variants — independent of provisioning.
|
|
90
|
+
*/
|
|
91
|
+
type LoadedTrayConfig = ({
|
|
92
|
+
kind: "provisioned";
|
|
93
|
+
projectId: string;
|
|
94
|
+
} & LoadedTrayConfigBase) | ({
|
|
95
|
+
kind: "unprovisioned";
|
|
96
|
+
projectId?: never;
|
|
97
|
+
} & LoadedTrayConfigBase);
|
|
98
|
+
type ProvisionedTrayConfig = Extract<LoadedTrayConfig, {
|
|
99
|
+
kind: "provisioned";
|
|
100
|
+
}>;
|
|
101
|
+
type UnprovisionedTrayConfig = Extract<LoadedTrayConfig, {
|
|
102
|
+
kind: "unprovisioned";
|
|
103
|
+
}>;
|
|
104
|
+
/**
|
|
105
|
+
* Absolute path of the project config file in `cwd`, preferring `helix.config.*`
|
|
106
|
+
* and falling back to a legacy `tray.config.*`. Returns undefined when neither exists.
|
|
107
|
+
*/
|
|
108
|
+
declare function resolveConfigFile(cwd: string): string | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* One-shot stateless read of `helix.config.ts`. NO caching — every call hits disk.
|
|
111
|
+
* For hot-reload or stable snapshot, use {@link createConfigService} instead.
|
|
112
|
+
*/
|
|
113
|
+
declare function loadConfig(cwd?: string): Promise<LoadedTrayConfig>;
|
|
114
|
+
/** Phase that surfaced an error inside ConfigService watcher. */
|
|
115
|
+
type WatchErrorPhase = "attach" | "reload" | "validation";
|
|
116
|
+
/** Stable code on errors thrown by {@link requireWorkspaceId}. Narrow by this, not instanceof. */
|
|
117
|
+
declare const WORKSPACE_ID_REQUIRED_CODE: "WORKSPACE_ID_REQUIRED";
|
|
118
|
+
/**
|
|
119
|
+
* Shape of errors thrown by {@link requireWorkspaceId}.
|
|
120
|
+
* Type alias — no class hierarchy; callers narrow via `error.code === WORKSPACE_ID_REQUIRED_CODE`.
|
|
121
|
+
*
|
|
122
|
+
* The thrown message references CLI (`helix workspace select` / `helix workspace set`)
|
|
123
|
+
* and MCP (`tray_list_workspaces` / `tray_set_workspace_id`) commands — keep those
|
|
124
|
+
* names in sync with the message literal in requireWorkspaceId.
|
|
125
|
+
*/
|
|
126
|
+
type WorkspaceIdRequiredError = Error & {
|
|
127
|
+
readonly code: typeof WORKSPACE_ID_REQUIRED_CODE;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Returns workspaceId from config, or throws a plain Error with code WORKSPACE_ID_REQUIRED.
|
|
131
|
+
* Pure, no I/O. workspaceId is independent of provisioning state.
|
|
132
|
+
*/
|
|
133
|
+
declare function requireWorkspaceId(config: LoadedTrayConfig): string;
|
|
134
|
+
|
|
135
|
+
interface SdkRuntimeConfig {
|
|
136
|
+
/**
|
|
137
|
+
* Execution mode. `"lambda"` is set via `setSdkConfig({ mode: "lambda", ... })`
|
|
138
|
+
* before the first handler invocation. `"dev"` is the default for `helix dev`
|
|
139
|
+
* and local invocations.
|
|
140
|
+
*/
|
|
141
|
+
mode: "lambda" | "dev";
|
|
142
|
+
/**
|
|
143
|
+
* Execution ID for the current invocation. Set via `setSdkConfig(...)` at
|
|
144
|
+
* handler entry in lambda mode. In `dev` mode, define-function falls back to
|
|
145
|
+
* the `x-tray-execution-id` header (or a random UUID).
|
|
146
|
+
*/
|
|
147
|
+
executionId?: string;
|
|
148
|
+
/**
|
|
149
|
+
* User ID for the current invocation. Set via `setSdkConfig(...)` at handler
|
|
150
|
+
* entry in lambda mode. In `dev` mode, define-function reads from the
|
|
151
|
+
* `x-tray-user-id` header.
|
|
152
|
+
*/
|
|
153
|
+
userId?: string;
|
|
154
|
+
/**
|
|
155
|
+
* Deployment ID for the current invocation. Set via `setSdkConfig(...)` at
|
|
156
|
+
* handler entry. Only meaningful in `lambda` mode; `dev` mode has no
|
|
157
|
+
* deployment concept yet.
|
|
158
|
+
*/
|
|
159
|
+
deploymentId?: string | null;
|
|
160
|
+
/**
|
|
161
|
+
* Running dev server's own base URL (e.g. `http://localhost:3000`). Set by
|
|
162
|
+
* the CLI's `sdk-context` Nitro plugin in `dev` mode so `ctx.files()` can
|
|
163
|
+
* build local signed URLs pointing at `/_helix/files/**`. Absent in `lambda`
|
|
164
|
+
* mode — production signed URLs point at the platform API host instead.
|
|
165
|
+
*/
|
|
166
|
+
devServerUrl?: string;
|
|
167
|
+
/**
|
|
168
|
+
* Absolute path to the project root in `dev` mode, set by the CLI's
|
|
169
|
+
* `sdk-context` Nitro plugin. Used by `ctx.files()`'s local dev store to
|
|
170
|
+
* resolve `.helix/files/` on disk. Absent in `lambda` mode.
|
|
171
|
+
*/
|
|
172
|
+
projectRoot?: string;
|
|
173
|
+
}
|
|
174
|
+
interface BrokerSecrets {
|
|
175
|
+
internalJwt?: string;
|
|
176
|
+
helixExecutionJwt?: string;
|
|
177
|
+
devToken?: string;
|
|
178
|
+
}
|
|
179
|
+
interface SdkConfigInput extends Partial<SdkRuntimeConfig>, BrokerSecrets {
|
|
180
|
+
}
|
|
181
|
+
declare function setSdkConfig(options: SdkConfigInput): void;
|
|
182
|
+
declare function getSdkConfig(): Readonly<SdkRuntimeConfig>;
|
|
183
|
+
|
|
184
|
+
export { type LoadedTrayConfig as L, type ProvisionedTrayConfig as P, type SdkConfigInput as S, type TrayConfig as T, type UnprovisionedTrayConfig as U, WORKSPACE_ID_REQUIRED_CODE as W, type SdkRuntimeConfig as a, type WatchErrorPhase as b, type WorkspaceIdRequiredError as c, loadedTrayConfigSchema as d, resolveConfigFile as e, getSdkConfig as g, loadConfig as l, projectIdSchema as p, requireWorkspaceId as r, setSdkConfig as s, workspaceIdSchema as w };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { T as TrayContext } from '../types-BxQmQx3V.js';
|
|
2
|
+
import 'h3';
|
|
3
|
+
import 'ky';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import 'unstorage';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Run code within a mock TrayContext — for unit testing shared code
|
|
9
|
+
* that calls getContext(). Unset fields throw on access via Proxy.
|
|
10
|
+
*/
|
|
11
|
+
declare function runWithContext<T>(partial: Partial<TrayContext>, fn: () => T | Promise<T>): Promise<T>;
|
|
12
|
+
|
|
13
|
+
export { runWithContext };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as r}from"../chunk-L6J5L3JQ.js";async function x(o,i){let s=new Proxy(o,{get(e,t,n){if(typeof t=="symbol"||t==="then"||t==="toJSON"||t in e)return Reflect.get(e,t,n);throw new Error(`Accessed unset context field "${String(t)}" in test. Provide it via runWithContext({ ${String(t)}: ... }, fn).`)}});return r.run(s,i)}export{x as runWithContext};
|