@xanots/sdk 0.0.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 (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +384 -0
  3. package/dist/agent-file-refresh-7XCACU34.js +95 -0
  4. package/dist/bin.d.ts +1 -0
  5. package/dist/bin.js +184 -0
  6. package/dist/capture-HUV5BNTC.js +32 -0
  7. package/dist/chunk-26CNBZE2.js +963 -0
  8. package/dist/chunk-33ND6LKO.js +78 -0
  9. package/dist/chunk-3DUAGYGP.js +1550 -0
  10. package/dist/chunk-3IGNIP6R.js +89 -0
  11. package/dist/chunk-47WDWMBJ.js +14 -0
  12. package/dist/chunk-4BXJGVZ3.js +318 -0
  13. package/dist/chunk-4HT3BNZ7.js +675 -0
  14. package/dist/chunk-4YMD2OOZ.js +23 -0
  15. package/dist/chunk-5WGEURVI.js +156 -0
  16. package/dist/chunk-5YTBTF25.js +29 -0
  17. package/dist/chunk-6DHBYBTO.js +166 -0
  18. package/dist/chunk-76QBEIGO.js +66 -0
  19. package/dist/chunk-7DKX2SPN.js +100 -0
  20. package/dist/chunk-7REDODS2.js +468 -0
  21. package/dist/chunk-C56BC2FY.js +254 -0
  22. package/dist/chunk-DGSF2Q5H.js +60 -0
  23. package/dist/chunk-EMCAWMHC.js +3982 -0
  24. package/dist/chunk-EZG76F7R.js +159 -0
  25. package/dist/chunk-FJ6ZS5KB.js +3607 -0
  26. package/dist/chunk-GNPVYOPB.js +17 -0
  27. package/dist/chunk-HJPTWBLH.js +38 -0
  28. package/dist/chunk-IZW6MK3U.js +248 -0
  29. package/dist/chunk-LH6Z6KFV.js +247 -0
  30. package/dist/chunk-MZUI3JNX.js +93 -0
  31. package/dist/chunk-NDZFBZHC.js +167 -0
  32. package/dist/chunk-NOO35BQ2.js +37 -0
  33. package/dist/chunk-NUQCEOKA.js +13 -0
  34. package/dist/chunk-QTNO2WD6.js +56 -0
  35. package/dist/chunk-RVB7ITKN.js +49 -0
  36. package/dist/chunk-TRU5OHQ5.js +6904 -0
  37. package/dist/chunk-VKFQJEMW.js +814 -0
  38. package/dist/chunk-VTIL47DT.js +125 -0
  39. package/dist/chunk-WHOJWOSV.js +112 -0
  40. package/dist/chunk-WKP4D5MO.js +1692 -0
  41. package/dist/chunk-X4DVXBFY.js +38 -0
  42. package/dist/chunk-XQ22GLYS.js +118 -0
  43. package/dist/chunk-YDZYMZBE.js +670 -0
  44. package/dist/chunk-YGPIY3WT.js +1146 -0
  45. package/dist/chunk-YYRDLFSJ.js +602 -0
  46. package/dist/chunk-ZUTSMMAG.js +46 -0
  47. package/dist/cli.d.ts +331 -0
  48. package/dist/cli.js +33 -0
  49. package/dist/codegen-command-OOKK6AZK.js +40 -0
  50. package/dist/codegen.d.ts +114 -0
  51. package/dist/codegen.js +71 -0
  52. package/dist/completion-TIPPZN7H.js +298 -0
  53. package/dist/config-NL33PN4D.js +84 -0
  54. package/dist/deploy-command-4EQ7XX5G.js +451 -0
  55. package/dist/env-target-IFJ5QDHC.js +16 -0
  56. package/dist/ephemeral-command-3X3I4ULC.js +242 -0
  57. package/dist/index.d.ts +4477 -0
  58. package/dist/index.js +300 -0
  59. package/dist/init-command-R6H7ZXW5.js +27 -0
  60. package/dist/internal.d.ts +74 -0
  61. package/dist/internal.js +2065 -0
  62. package/dist/io-AMIKRLPC.js +11 -0
  63. package/dist/live-diff-Y3AKETHE.js +196 -0
  64. package/dist/lock-3CVKALKT.js +37 -0
  65. package/dist/lock-commands-XTR2YKLY.js +232 -0
  66. package/dist/login-command-ACJF6KWQ.js +167 -0
  67. package/dist/logout-command-MX3MJS5U.js +68 -0
  68. package/dist/loop-OM3P2Z6O.js +93 -0
  69. package/dist/marketplace-command-RATXTKXN.js +379 -0
  70. package/dist/meta-client-OW5WKWW7.js +170 -0
  71. package/dist/node.d.ts +59 -0
  72. package/dist/node.js +442 -0
  73. package/dist/profile-command-SWJ3SPKR.js +77 -0
  74. package/dist/release-command-VV5UVZKL.js +427 -0
  75. package/dist/response-CVAE2kMj.d.ts +1915 -0
  76. package/dist/routes-manifest-SP3ZXLMR.js +244 -0
  77. package/dist/runtime-V4C3AC3A.js +13 -0
  78. package/dist/sandbox-details-command-HJE5SPVG.js +18 -0
  79. package/dist/sandbox-export-command-QCJY4GMV.js +24 -0
  80. package/dist/static-host-D6KS7X45.js +138 -0
  81. package/dist/store-BQ97nKIF.d.ts +7760 -0
  82. package/dist/test-command-TSPBQHBM.js +383 -0
  83. package/dist/validate-command-4ERHJSCO.js +122 -0
  84. package/dist/verify-rollout-FAVQ6EJY.js +40 -0
  85. package/dist/workspace-K72NP7SX.js +49 -0
  86. package/dist/workspace-command-OF23DPNI.js +156 -0
  87. package/dist/workspace-export-AJMGN3CQ.js +10 -0
  88. package/llms/fields.md +104 -0
  89. package/llms/filters.md +183 -0
  90. package/llms/kinds-agent-mcp.md +11 -0
  91. package/llms/kinds-core.md +68 -0
  92. package/llms/kinds-realtime.md +76 -0
  93. package/llms/lambda.md +111 -0
  94. package/llms/legacy.md +43 -0
  95. package/llms/object-kinds.md +31 -0
  96. package/llms/statements-calls.md +23 -0
  97. package/llms/statements-catalog.md +309 -0
  98. package/llms/statements-data.md +58 -0
  99. package/llms/statements-runtime.md +48 -0
  100. package/llms/tests.md +58 -0
  101. package/llms/triggers.md +22 -0
  102. package/llms/values.md +29 -0
  103. package/llms-full.txt +1672 -0
  104. package/llms.txt +483 -0
  105. package/manifest.json +9592 -0
  106. package/package.json +110 -0
@@ -0,0 +1,4477 @@
1
+ import { e1 as Condition, e2 as FilterResults, e3 as ElementResult, e4 as SameArrayResult, e5 as GroupedArrayResult, e6 as AgentResultOf, aZ as AddonDef, e7 as OutputPath, cO as TableDef, e8 as QualifiedCol, br as DbEval, cN as SortDirective, bt as DbWhere, e9 as OutputRoot, bG as InferRow, ea as AggregateRow, eb as EvalFields, ec as OutputAuthored, c0 as MicroserviceDef, ae as generated, F as FunctionDef, cd as QueryHandle } from './store-BQ97nKIF.js';
2
+ export { a_ as AddonXdo, A as AdoptChange, a as AdoptResult, a$ as AgentDef, b0 as AgentHandle, b1 as AgentOutput, b2 as AgentSettingsXdo, b3 as AgentXdo, b4 as AmbientBindings, b5 as AnthropicLlm, b6 as ApiGroupDef, b7 as ApiGroupXdo, b8 as AuthRef, b9 as Authored, B as Bundle, b as BundlePayload, c as BundleType, ba as Capturable, aW as CaptureRecord, aU as CaptureValue, bb as ChannelConversationDef, bc as ChannelDeliveryDef, bd as ChannelDeliveryGuarantee, be as ChannelPublishDef, bf as ChannelPublishWho, bg as ChannelRateLimitDef, bh as ColumnDef, bi as Comparison, bj as ContainerEnv, bk as ContainerPort, bl as ContainerResources, bm as ContainerVolume, bn as CorsConfig, bo as CorsMode, bp as DatabaseActions, bq as DatabaseInputs, bs as DbEvalFilter, bu as ErrorInputs, bv as ExceptionPolicy, bw as FieldAccessor, bx as FieldRule, by as GoogleGenAiLlm, bz as HistoryInput, bA as HttpVerb, bB as IndexDef, bC as IndexLang, bD as IndexOp, bE as IndexType, bF as IndexXdo, bH as InputDescriptor, bI as InputOptions, bJ as IteratingBindings, bK as LAMBDA_BINDINGS, bL as LAMBDA_CODE_FILTERS, bM as LAMBDA_GLOBALS, bN as LAMBDA_MODULE_GLOBALS, bO as LAMBDA_STATEMENTS, aX as LambdaBindings, bP as LambdaBody, aT as LambdaOptions, aV as LambdaSurface, bQ as LlmPrompt, bR as LlmProvider, bS as LlmSettings, f as LockEntry, g as LockExportContext, h as LockFile, M as Manifest, i as ManifestField, j as ManifestKind, k as ManifestStatement, bT as ManifestValue, bU as McpPathOptions, bV as McpServerDef, bW as McpServerHandle, bX as McpServerXdo, l as MergeResult, bY as MessageDeliverTo, bZ as MicroserviceChart, b_ as MicroserviceConfig, b$ as MicroserviceContainer, c1 as MicroserviceDeployment, c2 as MicroserviceIngress, c3 as MicroserviceRegistryAuth, c4 as MicroserviceVolume, c5 as MicroserviceXdo, c6 as MiddlewareAttach, c7 as MiddlewareAttachEntry, c8 as MiddlewareDef, c9 as MiddlewareXdo, O as ObjectKind, ca as OpenAiLlm, m as PayloadArrayKey, cb as QueryDef, cc as QueryFilterName, ce as QueryResponseType, cf as QueryXdo, cg as RealtimeActions, ch as RealtimeChannelActions, ci as RealtimeChannelDef, cj as RealtimeChannelHandle, ck as RealtimeChannelRef, cl as RealtimeChannelTriggerInputs, cm as RealtimeChannelXdo, cn as RealtimeClient, co as RealtimeInputs, cp as RealtimeMessageDef, cq as RealtimeMessageXdo, cr as RealtimeServerActions, cs as RealtimeServerDef, ct as RealtimeServerHandle, cu as RealtimeServerRef, cv as RealtimeServerTriggerInputs, cw as RealtimeServerXdo, cx as RealtimeUrlOptions, R as RenameResult, cy as ResultStrategy, cz as Route, cA as RowOf, cB as ScheduleDef, cC as SchemaCols, cD as SchemaDef, cE as SearchComparison, cF as SearchGroup, cG as SearchNode, cH as SearchOp, cI as SearchParamValue, cJ as SeedFileSource, cK as SeedRow, cL as SeedSource, cM as SortDir, S as StatementSpec, cP as TableXdo, cQ as TaskDef, cR as TaskXdo, cS as ToolDef, cT as ToolXdo, cU as ToolsetBaseDef, cV as ToolsetBaseXdo, cW as ToolsetInputs, cX as ToolsetToolEntry, cY as ToolsetToolRef, cZ as TriggerDef, c_ as TriggerObjType, c$ as TriggerXdo, d0 as ViewDef, d1 as ViewXdo, d2 as WorkflowTestDef, d3 as WorkflowTestXdo, d4 as WorkspaceActions, d5 as WorkspaceConfigDef, d6 as WorkspaceConfigXdo, d7 as WorkspaceHistoryDef, d8 as WorkspaceHistoryXdo, d9 as WorkspaceInputs, da as WorkspaceMiddlewareDef, db as WorkspaceMiddlewareXdo, aY as Xano, dc as XanoFreeLlm, dd as addon, de as agent, df as agentTrigger, dg as and, dh as apiGroup, di as assertLambdaBody, dj as bitwiseAnd, dk as bitwiseOr, dl as bitwiseXor, dm as cmp, dn as defineFunction, dp as emit, dq as emitBundle, dr as errorTrigger, ds as expr, dt as fl, du as input, ed as lam, dv as mathAdd, dw as mathDiv, dx as mathMul, dy as mathSub, dz as mcpServer, dA as mcpServerTrigger, dB as microservice, dC as middleware, dD as mixed, dE as objectEntries, dF as objectKeys, dG as objectValues, dH as or, dI as query, dJ as realtimeChannel, dK as realtimeChannelTrigger, dL as realtimeMessage, dM as realtimeServer, dN as realtimeServerTrigger, dO as realtimeTrigger, dP as resetLockOverrides, dQ as seedFile, dR as seedLockOverrides, dS as table, dT as tableTrigger, dU as task, dV as textAppend, dW as textPrepend, dX as toSearchParams, dY as tool, dZ as workflowTest, d_ as workspace, d$ as workspaceConfig, e0 as workspaceTrigger } from './store-BQ97nKIF.js';
3
+ import { a2 as StatementAnnotations, a1 as Statement, y as FromFieldMap, w as FilterXdo, V as Value, S as ObjValue, aH as Prettify, x as FilteredValue, X as RefValue, aM as AsShapeBrand, aj as XanoFileRef, a4 as StatementOptions, T as ObjectRef, P as ObjInput, F as FunctionXdo } from './response-CVAE2kMj.js';
4
+ export { B as BrandOpts, c as BrandValue, C as CacheXdo, f as CaughtField, h as ConditionalContext, j as ConditionalElifContext, D as DecimalMethod, E as EmailMethod, k as ExprGroup, l as ExprNode, m as ExprOperand, n as ExprStatement, o as FieldAccess, p as FieldDescriptor, q as FieldMap, s as FieldOpts, u as FieldStyleType, v as FieldXdo, H as HistoryXdo, I as InputXdo, z as IntMethod, L as ListBoundsXdo, M as MethodArg, A as MethodOpts, G as MethodSpec, J as MethodXdo, K as MockEntry, N as MockMap, O as MockXdo, Q as ObjMember, U as PasswordMethod, W as PersistedFunctionRow, Y as RegexValue, Z as ResponseDef, _ as ResultItemXdo, $ as RowFromFieldMap, a0 as StackItemXdo, a3 as StatementInputXdo, a5 as TAGS, a6 as TEST_EXPECT_TYPES, a7 as TableRefMethod, a8 as Tag, a9 as TaggedValue, aa as TestDef, ab as TestExpect, ac as TestExpectType, ad as TestXdo, ae as TextFormat, af as TextMethod, ag as TypeBrand, ah as ValueOf, ai as VectorMethod, ak as XanoGeoPosition, al as XanoGeoValue, am as annotate, an as auth, ao as c, ap as caught, aq as col, ar as env, as as expect, at as f, au as filter, av as inp, aw as obj, ax as out, ay as ref, az as resp, aA as setting, aB as statements, aC as sys, aD as test, aE as toolset, aF as withFilters } from './response-CVAE2kMj.js';
5
+
6
+ /** One `else if (when) { then }` branch of a {@link conditional}'s elif stack. */
7
+ interface ConditionalElifArgs extends StatementAnnotations {
8
+ when: Condition;
9
+ then: Statement[];
10
+ }
11
+ interface ConditionalArgs extends StatementAnnotations {
12
+ when: Condition;
13
+ then: Statement[];
14
+ /** Ordered `else if` branches, each `{ when, then }`. */
15
+ elif?: ConditionalElifArgs[];
16
+ else?: Statement[];
17
+ }
18
+ /** A branching statement: `if (when) { then } [else if …] else { else }`. */
19
+ declare function conditional(args: ConditionalArgs): Statement;
20
+
21
+ /**
22
+ * `InferInput<Q>` (U2) — the request-payload TS type for a query (or function)
23
+ * def's declared inputs, computed at compile time from the value brands added in
24
+ * U1. No codegen, no build step: the type is derived from the def, so it can
25
+ * never drift from what the endpoint actually accepts.
26
+ *
27
+ * ```ts
28
+ * const meQuery = query({ verb: "POST", apiGroup: auth, name: "me",
29
+ * input: { email: input.email({ required: true }), password: input.password({ required: true }) } });
30
+ *
31
+ * type MePayload = InferInput<typeof meQuery>; // { email: string; password: string }
32
+ * fetch(BASE + meQuery.getPath(), { body: JSON.stringify(payload satisfies MePayload) });
33
+ * ```
34
+ *
35
+ * Works for any def carrying an `input` map, so `defineFunction` handles infer
36
+ * the same way (functions share the input system) even though only queries have
37
+ * a URL path.
38
+ */
39
+
40
+ /**
41
+ * The `input` map of a def-like `{ input?: ... }`, or an empty map when absent.
42
+ * The empty case must be `Record<never, never>` (keyof `never`) — NOT
43
+ * `Record<string, never>`, whose string index signature would make
44
+ * {@link FromFieldMap} emit an index-signature payload instead of `{}`.
45
+ */
46
+ type InputMapOf<Q> = Q extends {
47
+ input?: infer M;
48
+ } ? [M] extends [undefined] ? Record<never, never> : NonNullable<M> : Record<never, never>;
49
+ /**
50
+ * Turn a query/function def's declared `input` map into its request-payload
51
+ * type: required inputs become required keys, the rest optional; `nullable`
52
+ * adds `| null`, `array`/`list` produce `T[]`, `enum` a literal union, and a
53
+ * nested `object` input recurses.
54
+ */
55
+ type InferInput<Q> = FromFieldMap<InputMapOf<Q>>;
56
+
57
+ /**
58
+ * Filter-aware result typing — what a value becomes after a filter chain runs.
59
+ *
60
+ * A filter changes the value at runtime, and until now the type system had no
61
+ * way to follow: `withFilters(ref("row"), fl.count())` typed as `unknown`, and a
62
+ * statement's `asFilters` chain did not change the bound variable's type at all
63
+ * (which was worse — the declared type was a confident lie).
64
+ *
65
+ * The engine's own filter catalog declares a `result` for 190 of the 225
66
+ * filters, and {@link FilterResults} turns those declarations into types. This
67
+ * module folds a chain over them, left to right, exactly as the engine applies
68
+ * them — confirmed live: `[fl.first(), fl.get("id")]` over `[{"id":1}]` returns
69
+ * `1`, so each filter genuinely sees the previous one's output.
70
+ *
71
+ * **What this does NOT do.** It does not check that a filter can *accept* the
72
+ * value it is given. A filter applied to an incompatible value returns `null` at
73
+ * runtime rather than erroring — `"ab" |trim|lower|count` is `null`, because
74
+ * `count` is an array filter — so a nonsensical chain still types as its
75
+ * declared result. Modelling filter INPUT types is separate work; this models
76
+ * output only.
77
+ */
78
+
79
+ /**
80
+ * The filter name a {@link FilterXdo} carries at the type level.
81
+ *
82
+ * `fl.upper()` is a `FilterXdo<"upper">`; the bare `filter(someString)` escape
83
+ * hatch and every decoded envelope are `FilterXdo<string>`, which widens to the
84
+ * `string` that {@link ApplyFilter} treats as "not statically known".
85
+ */
86
+ type NameOf<F> = F extends FilterXdo<infer N> ? N : string;
87
+ /**
88
+ * Apply ONE filter's declared result to `Shape`.
89
+ *
90
+ * Null propagates rather than being erased, matching `IndexShape`'s treatment of
91
+ * a nullable base (#105) and the engine's runtime, where a filter over a null
92
+ * binding yields null: a `db.get` row is `Row | null`, so counting it is
93
+ * `number | null`, not `number`.
94
+ *
95
+ * Anything not in {@link FilterResults} — the `any`-result filters (`get`,
96
+ * `set`, `transform`, `json_decode`, `lambda`, …) and a name that is not
97
+ * statically known — lands on `unknown`. That is the honest floor, and it is
98
+ * where this deliberately stops rather than guessing.
99
+ */
100
+ type ApplyFilter<Shape, N extends string> = string extends N ? unknown : null extends Shape ? ApplyFilter<Exclude<Shape, null>, N> | null : N extends keyof FilterResults ? FilterResults[N] extends ElementResult ? Shape extends readonly (infer E)[] ? E : unknown : FilterResults[N] extends SameArrayResult ? Shape extends readonly unknown[] ? Shape : unknown : FilterResults[N] extends GroupedArrayResult ? Shape extends readonly (infer E)[] ? Record<string, E[]> : unknown : FilterResults[N] : unknown;
101
+ /**
102
+ * Fold a whole chain over `Shape`, left to right.
103
+ *
104
+ * An empty chain leaves the shape untouched, so attaching no filters is exactly
105
+ * the same type as attaching none — `asFilters: []` does not degrade anything.
106
+ */
107
+ type ApplyFilters<Shape, Fs> = Fs extends readonly [infer Head, ...infer Tail] ? ApplyFilters<ApplyFilter<Shape, NameOf<Head>>, Tail> : Fs extends readonly [] ? Shape : unknown;
108
+
109
+ /**
110
+ * `InferResponse<Q>` (issue #5) — the response type for a query or function def,
111
+ * the read-side counterpart of `InferInput`. Closes the round trip: rename or
112
+ * retype what an endpoint returns and every consumer that types a response
113
+ * against `InferResponse` lights up at compile time.
114
+ *
115
+ * ```ts
116
+ * const listLinks = query({ verb: "GET", apiGroup: links, name: "list_links",
117
+ * stack: [s.db.query({ table: link, as: "rows" })], response: ref("rows"),
118
+ * responseShape: [] as InferRow<typeof link>[] });
119
+ *
120
+ * type Links = InferResponse<typeof listLinks>; // InferRow<typeof link>[]
121
+ * const res = await fetch(BASE + listLinks.getPath());
122
+ * const links: Links = await res.json(); // typed end to end
123
+ * ```
124
+ *
125
+ * **Hybrid resolution** (mirrors how the Xano engine derives its OpenAPI response
126
+ * schema — a static walk that degrades to `json` where truth isn't statically
127
+ * knowable):
128
+ * 1. A declared `responseShape` on the def always wins (the override).
129
+ * 2. Otherwise the shape is auto-derived from `response` + `stack`
130
+ * ({@link DeriveResponse}) — object-literal keys (U2) and a single variable
131
+ * traced to a typed `db.get`/`db.query` (U5). A dotted `ref("var.field")`
132
+ * traces the base variable, then indexes the subpath into its shape (#93).
133
+ * 3. Anything the walk can't resolve (filters, lambdas, control-flow vars,
134
+ * `set_var`, function-produced vars, streams) resolves to `unknown`, which
135
+ * the author narrows or overrides via `responseShape`.
136
+ */
137
+
138
+ /**
139
+ * The author-declared response shape, read from a def's `responseShape` field
140
+ * (captured by `query()`/`defineFunction()`), or `never` when undeclared.
141
+ *
142
+ * Read structurally rather than off the `Res` type argument: an undeclared def
143
+ * carries `responseShape?: never`, whose optional-collapsed field type is
144
+ * `undefined` — the `[R] extends [undefined]` gate maps that to `never` (→ route
145
+ * to derivation). A declared shape's field type is `T | undefined`; stripping the
146
+ * optional `undefined` with `Exclude` recovers `T` **while preserving a
147
+ * deliberate `| null`** (e.g. `InferRow<...> | null` stays nullable).
148
+ */
149
+ type DeclaredResponse<Q> = Q extends {
150
+ responseShape?: infer R;
151
+ } ? [R] extends [undefined] ? never : Exclude<R, undefined> : never;
152
+ /**
153
+ * Search a branded stack tuple `S` for the read statement that bound the
154
+ * variable `Name` (its phantom `__as`), returning that statement's `__shape`.
155
+ * Mirrors the engine's `findVarSchema`: a one-hop, top-level match. Statements
156
+ * without the `__as`/`__shape` brand (`set_var`, control flow, function calls)
157
+ * are skipped, so a ref into one of those falls through to `unknown` — exactly
158
+ * where the engine falls back to `json`. A widened (non-tuple) stack matches no
159
+ * head and yields `unknown` too.
160
+ */
161
+ /**
162
+ * What a response resolves to when the stack is a plain `Statement[]` rather
163
+ * than a tuple — the collapse issue #11 reported.
164
+ *
165
+ * A widened stack has no heads to walk, so EVERY `as` binding in it is invisible
166
+ * and every `ref()` bottoms out. Resolving that to `unknown` made the failure
167
+ * silent and moved the error downstream ("Property 'model_id' does not exist on
168
+ * type '{}'", in the page that consumes the response). Resolving it to this
169
+ * named type puts the cause and the two fixes in the error itself.
170
+ *
171
+ * The cause is almost always a shared helper typed `Statement[]` spread into the
172
+ * stack: `...assertOk("res")`. Return `statements(...)` from the helper to keep
173
+ * the tuple, or declare `responseShape` on this def.
174
+ */
175
+ interface StackTupleWidened {
176
+ readonly __xanots_response_not_inferred: "This stack is a `Statement[]`, not a tuple, so no `as` binding in it can be traced. A helper returning `Statement[]` and spread into the stack is the usual cause: return `statements(...)` from the helper (fixed arity), or declare `responseShape` on this def.";
177
+ }
178
+ /**
179
+ * Is `S` a widened array (not a fixed tuple)? A fixed tuple's `length` is a
180
+ * literal. A REST tuple (`[DbGet, ...Statement[]]` — what a stack with a helper
181
+ * spread at the END looks like) has a `number` length too, which is why the
182
+ * report below is gated on the trace actually failing rather than on this
183
+ * alone: a binding declared before the spread still traces perfectly.
184
+ */
185
+ type IsWidenedStack<S> = S extends readonly unknown[] ? number extends S["length"] ? true : false : false;
186
+ /**
187
+ * Report the collapse only where it actually happened: an unresolved value
188
+ * (`unknown`) against a stack whose tuple was widened. A ref that still traced —
189
+ * because it was bound before the spread, in a rest tuple — keeps its type, and
190
+ * an unresolvable ref in a proper tuple keeps the honest `unknown` floor (it is
191
+ * a filter/lambda/control-flow case, not a widening one).
192
+ */
193
+ type ReportWidened<T, S> = IsWidenedStack<S> extends true ? unknown extends T ? StackTupleWidened : T : T;
194
+ type TraceBinding<Name extends string, S> = S extends readonly [infer Head, ...infer Tail] ? Head extends AsShapeBrand<infer As, infer Shape> ? As extends Name ? Name extends As ? Shape : TraceBinding<Name, Tail> : TraceBinding<Name, Tail> : TraceBinding<Name, Tail> : unknown;
195
+ /**
196
+ * Walk a dotted subpath `Path` into an already-traced binding `Shape`, one
197
+ * segment at a time: `IndexShape<AgentRunResult<string>, "result">` → `string`.
198
+ *
199
+ * **Null-propagating** (#105): when the base is nullable (e.g. a `db.get` row,
200
+ * `Row | null`), the null flows *through* the projection rather than erasing it —
201
+ * `IndexShape<Row | null, "slug">` → `string | null`, mirroring the engine's
202
+ * runtime where `$row.slug` on a missed (null) row is itself null. Without this,
203
+ * `keyof (Row | null)` narrows to `never` and every dotted ref into a nullable
204
+ * base would bottom out at `unknown`, silently dropping the #93 projection.
205
+ *
206
+ * A segment that genuinely isn't a key of the (non-null) shape — including a
207
+ * shape that is already `unknown` (whose `keyof` is `never`) — still bottoms out
208
+ * at `unknown`, the same honest floor as an untraceable whole ref.
209
+ */
210
+ type IndexShape<Shape, Path extends string> = unknown extends Shape ? IndexStep<Shape, Path> : null extends Shape ? IndexShape<Exclude<Shape, null>, Path> | null : undefined extends Shape ? IndexShape<Exclude<Shape, undefined>, Path> | undefined : IndexStep<Shape, Path>;
211
+ /**
212
+ * One non-null indexing step for {@link IndexShape}: split the head segment off
213
+ * `Path` and project it into `Shape`, recursing (back through the null-aware
214
+ * {@link IndexShape}) for the tail. A segment that isn't a key bottoms out at
215
+ * `unknown`. Kept separate so the `unknown extends Shape` guard in `IndexShape`
216
+ * (true for exactly `unknown`/`any` — the bases where null-distribution can't
217
+ * terminate) routes straight here without looping.
218
+ */
219
+ type IndexStep<Shape, Path extends string> = Path extends `${infer Head}.${infer Rest}` ? Head extends keyof Shape ? IndexShape<Shape[Head], Rest> : unknown : Path extends keyof Shape ? Shape[Path] : unknown;
220
+ /**
221
+ * Resolve a `ref` name against the branded stack `S`. A **dotted** name projects
222
+ * a subpath (#93): the head names the bound variable (traced via
223
+ * {@link TraceBinding}) and the tail indexes into that variable's shape (via
224
+ * {@link IndexShape}), so `ref("generated.result")` types to the completion, not
225
+ * `unknown`. A bare name traces the whole binding. Stack-variable names are
226
+ * identifiers (no dots), so the first `.` always splits the variable from the
227
+ * subpath — matching how the engine resolves `$generated.result`.
228
+ */
229
+ type TraceVar<Name extends string, S> = Name extends `${infer Base}.${infer Path}` ? IndexShape<TraceBinding<Base, S>, Path> : TraceBinding<Name, S>;
230
+ /**
231
+ * Resolve one response {@link Value} to its type against the branded stack `S`.
232
+ *
233
+ * A FILTERED value resolves its base and then folds the chain over it
234
+ * ({@link ApplyFilters}), so `withFilters(ref("rows"), fl.count())` is `number`
235
+ * rather than `unknown`. It used to degrade to `unknown` outright, on the
236
+ * grounds that a filter reshapes a value with no static signal — true when
237
+ * written, but the catalog does declare a result for 190 of the 225 filters, and
238
+ * those declarations are live-verified. The remaining filters (`get`, `set`,
239
+ * `json_decode`, …) still land on `unknown` through the fold itself.
240
+ *
241
+ * Otherwise a branded `ref` traces to the statement that produced it
242
+ * ({@link TraceVar}); anything else (a non-ref value, an untraceable ref) is
243
+ * `unknown` — the honest floor.
244
+ *
245
+ * A CONSTANT is "anything else". `response: { success: c.bool(true) }` derives
246
+ * `{ success: unknown }`, not `{ success: boolean }` — `c.*` returns a bare
247
+ * `Value` carrying no tag brand, so there is nothing here to read the type off.
248
+ * That mirrors the engine's own static walk, which resolves references and not
249
+ * values, and it is deliberate rather than a gap: typing a constant's key would
250
+ * mean branding the return of every constant constructor, and `Value` is the
251
+ * currency of every statement field in the SDK. Declare `responseShape` when a
252
+ * client needs those keys typed (issue #79).
253
+ */
254
+ type ResolveValue<V, S> = V extends ObjValue<infer Members> ? ResolveObj<Members, S> : V extends FilteredValue<infer Base, infer Chain> ? ApplyFilters<ResolveValue<Base, S>, Chain> : V extends RefValue<infer Name> ? TraceVar<Name, S> : unknown;
255
+ /**
256
+ * Resolve every member of an {@link ObjValue}'s record (issue #118) — the same
257
+ * walk {@link DeriveResponse} runs over a top-level object literal, one level
258
+ * down. `obj()` is the SDK's answer for a nested response object, and it used to
259
+ * cost the caller its types: the members are ordinary {@link Value}s with
260
+ * ordinary bindings, so there was never a reason they could not trace.
261
+ *
262
+ * The widened-stack report ({@link ReportWidened}) is applied per MEMBER rather
263
+ * than to the record as a whole, so a collapsed tuple still names itself at the
264
+ * leaf that failed — `{ user: { id: StackTupleWidened } }` — instead of
265
+ * flattening back into a silent `unknown`.
266
+ *
267
+ * A dynamically-built `ObjInput` (no literal to read) maps its index signature
268
+ * and lands on `{ [key: string]: unknown }` — the honest floor, same as any other
269
+ * value the walk cannot see through.
270
+ */
271
+ type ResolveObj<Members, S> = Prettify<{
272
+ -readonly [K in keyof Members]: ReportWidened<ResolveMember<Members[K], S>, S>;
273
+ }>;
274
+ /**
275
+ * Resolve one {@link ObjMember} — the member grammar `obj()` accepts, which is
276
+ * wider than {@link Value}.
277
+ *
278
+ * The branch order is load-bearing:
279
+ * - a {@link Value} (including a nested `obj()`, a filtered value, or a `ref`)
280
+ * goes to {@link ResolveValue}, so `c.*` constants keep the `unknown` floor
281
+ * issue #79 documents;
282
+ * - a RAW SCALAR literal types itself — `obj({ count: 3 })` really is a number,
283
+ * and unlike `c.int(3)` the type is right there to read. A boolean is widened
284
+ * explicitly because inference does not treat it like its siblings: `3` and
285
+ * `"hi"` widen to `number`/`string` against the `ObjMember` contextual type,
286
+ * while `true` survives as the literal (it is a member of `boolean` itself).
287
+ * Uniform scalars beat one field inferring narrower than the rest for no
288
+ * reason the author can see; `responseShape` states a literal deliberately;
289
+ * - an ARRAY resolves element-wise (checked before the record branch, since an
290
+ * array is also an object);
291
+ * - a nested plain RECORD recurses. This is the spelling `response: { user: {
292
+ * id: ref(...) } }` uses — the #133 auto-wrap, which `encodeResponse` hands
293
+ * to `obj()` anyway, so the two spellings must and now do infer alike.
294
+ */
295
+ type ResolveMember<M, S> = M extends Value ? ResolveValue<M, S> : M extends boolean ? boolean : M extends string | number ? M : M extends readonly (infer Element)[] ? ResolveMember<Element, S>[] : M extends object ? ResolveObj<M, S> : unknown;
296
+ /**
297
+ * Best-effort automatic derivation of a response shape from the def's `response`
298
+ * field and branded `stack`. Mirrors the Xano engine's static walk:
299
+ * - a record response (object literal) → an object with **those keys** (each
300
+ * member resolved individually, recursing into a nested `obj()` or plain
301
+ * object literal — #118); keys are known regardless of traceability;
302
+ * - a single {@link Value} response → resolve it against the stack;
303
+ * - no response / an unresolvable shape → `unknown`.
304
+ * Kept separate from {@link DeclaredResponse} so the user override always wins.
305
+ */
306
+ type DeriveResponse<Q> = Q extends {
307
+ response?: infer Resp;
308
+ stack?: infer S;
309
+ } ? [Resp] extends [undefined] ? unknown : Resp extends Value ? ReportWidened<ResolveValue<Resp, S>, S> : Resp extends Record<string, unknown> ? Prettify<{
310
+ -readonly [K in keyof Resp]: ReportWidened<ResolveMember<Resp[K], S>, S>;
311
+ }> : unknown : unknown;
312
+ /**
313
+ * Recover a query/function's response type. A declared `responseShape` wins;
314
+ * otherwise fall back to automatic derivation (which itself bottoms out at
315
+ * `unknown` for anything the static walk can't resolve).
316
+ */
317
+ type InferResponse<Q> = [DeclaredResponse<Q>] extends [never] ? DeriveResponse<Q> : DeclaredResponse<Q>;
318
+
319
+ /**
320
+ * Addressing a stored file from a client (issue #31).
321
+ *
322
+ * A file column comes back as a {@link XanoFileRef}: a `path` into the vault
323
+ * plus metadata, and an absolute, authoritative-looking `url`. On a
324
+ * tenant-scoped environment — which is what `xanots deploy` provisions — that
325
+ * `url` addresses the instance host and OMITS the `/tenant/<name>` segment every
326
+ * other URL on that environment carries, so it 404s. The `path` is correct; only
327
+ * the host prefix is wrong.
328
+ *
329
+ * It fails as a broken `<img>` and nothing else: the API response is complete
330
+ * and every assertion about it passes, because the field IS present, with a real
331
+ * `size` and real `meta.width`/`meta.height`. Only fetching the URL reveals it.
332
+ *
333
+ * {@link fileUrl} joins `path` to the base URL the client already has, which is
334
+ * correct on a tenant-scoped environment and on an instance workspace alike.
335
+ * Use it instead of reading `url` directly.
336
+ */
337
+
338
+ /**
339
+ * The URL to fetch a stored file from, built against the base URL the client is
340
+ * already talking to.
341
+ *
342
+ * ```ts
343
+ * <img src={fileUrl(row.avatar, XANO_HOST) ?? ""} />
344
+ * ```
345
+ *
346
+ * `XANO_HOST` is the backend base URL `xanots deploy --static` injects (and
347
+ * `xanots sandbox details` prints) — on an ephemeral it already carries the
348
+ * `/tenant/<name>` segment, which is exactly the part the file's own `url` field
349
+ * drops.
350
+ *
351
+ * Returns `null` for an absent file, so it composes with an optional column.
352
+ * Falls back to the file's own `url` only when there is no `path` to join.
353
+ */
354
+ declare function fileUrl(file: XanoFileRef | null | undefined, baseUrl: string): string | null;
355
+
356
+ /**
357
+ * `setVar` / `updateVar` statements (U5/U10) — the `!var` family. Both carry
358
+ * their value in `context` (not `input[]`), a per-statement quirk confirmed by
359
+ * the golden fixtures. They differ in how the target variable is named:
360
+ *
361
+ * - `set_var` declares a *new* stack variable via the top-level `as` slot
362
+ * (`var $x1 { value = ... }`) and emits no `output` envelope.
363
+ * - `update_var` reassigns an *existing* stack variable named inside
364
+ * `context.name` (`update $x1 { value = ... }`), has no `as`, and carries a
365
+ * lean `output:{filters:[]}` envelope.
366
+ */
367
+
368
+ /** Assign `value` to stack variable `as` (`var $as { value = ... }`). */
369
+ declare function setVar(as: string, value: Value, a?: StatementOptions): Statement;
370
+ /** Reassign existing stack variable `name` to `value` (`update $name { value = ... }`). */
371
+ declare function updateVar(name: string, value: Value, a?: StatementAnnotations): Statement;
372
+
373
+ /**
374
+ * Hand-authored `!class` control-flow / terminal statements (U10). These carry
375
+ * PHP transforms in the engine, so they're authored by hand and validated
376
+ * against persisted fixtures rather than codegen'd. (`conditional` — also a
377
+ * `!class` special — already lives in `src/statements/conditional.ts`.)
378
+ *
379
+ * - `return` / `die` / `debug_log`: carry a single Value in `context`.
380
+ * - `foreach_break` / `foreach_continue` / `foreach_remove`: empty `context`.
381
+ */
382
+
383
+ /** Accept either a bare `Value` or the object form `{ value }` for ergonomics. */
384
+ type ValueArg = Value | {
385
+ value: Value;
386
+ };
387
+ /** `return <value>` — terminate and return a value. */
388
+ declare function returnValue(value: ValueArg, a?: StatementAnnotations): Statement;
389
+ /**
390
+ * `die <value>` — terminate the request with an error value.
391
+ *
392
+ * The same statement as `s.debug.stop` (both emit `mvp:die`), and the one flat
393
+ * alias whose name does not mirror its `s.*` path — there is no `s.die`. Despite
394
+ * living under `debug`, it is real control flow rather than a development aid.
395
+ * Compare `s.throw`, which raises a catchable named error.
396
+ */
397
+ declare function die(value: ValueArg, a?: StatementAnnotations): Statement;
398
+ /** `debug_log <value>` — emit a debug log entry. */
399
+ declare function debugLog(value: ValueArg, a?: StatementAnnotations): Statement;
400
+ /** `foreach_break` — break out of the enclosing loop. */
401
+ declare function foreachBreak(a?: StatementAnnotations): Statement;
402
+ /** `foreach_continue` — continue the enclosing loop. */
403
+ declare function foreachContinue(a?: StatementAnnotations): Statement;
404
+ /** `foreach_remove` — remove the current item from the iterated collection. */
405
+ declare function foreachRemove(a?: StatementAnnotations): Statement;
406
+
407
+ /**
408
+ * Hand-authored control-flow block statements (U10). These carry non-trivial
409
+ * transforms in the engine (for, foreach, while, group), so they're authored by
410
+ * hand — like `conditional` — rather than codegen'd. Each nests a `run[]` stack
411
+ * encoded through the shared statement encoder, and `while` reuses the
412
+ * conditional's `encodeComparison`.
413
+ *
414
+ * Stored shapes (from the Xano engine's persisted for/foreach/while shapes):
415
+ * for → context: { as, cnt:<Value>, run:[…] }
416
+ * foreach → context: { as, list:<Value>, run:[…] }
417
+ * while → context: { expr:<comparison>, run:[…] }
418
+ * group → context: { run:[…] }
419
+ *
420
+ * All four are golden-verified: `for`/`foreach` from vendored goldens, and
421
+ * `while`/`group` from live engine captures (see the conformance corpus). The
422
+ * `while` shape (`expr` comparison + `run[]`) and `group`'s bare `{run}` are
423
+ * confirmed byte-exact.
424
+ */
425
+
426
+ interface ForArgs extends StatementOptions {
427
+ /** Loop variable name (the index). */
428
+ as: string;
429
+ /** Iteration count. */
430
+ count: Value;
431
+ body: Statement[];
432
+ }
433
+ /** `for (as in 0..count) { body }` — count-bounded loop. */
434
+ declare function forLoop(args: ForArgs): Statement;
435
+ interface ForeachArgs extends StatementOptions {
436
+ /** Loop variable name (the current item). */
437
+ as: string;
438
+ /** The list to iterate. */
439
+ list: Value;
440
+ body: Statement[];
441
+ }
442
+ /** `foreach (as of list) { body }` — list iteration. */
443
+ declare function foreachLoop(args: ForeachArgs): Statement;
444
+ interface WhileArgs extends StatementAnnotations {
445
+ when: Condition;
446
+ body: Statement[];
447
+ }
448
+ /** `while (when) { body }` — condition-bounded loop. */
449
+ declare function whileLoop(args: WhileArgs): Statement;
450
+ /** `group { body }` — a labeled block grouping a sub-stack. */
451
+ declare function group(body: Statement[], a?: StatementAnnotations): Statement;
452
+
453
+ /**
454
+ * Hand-authored branching block statements (U10) — `switch` and `try_catch`.
455
+ * Both carry structural control-flow transforms in the engine, so
456
+ * (like `conditional` and the loops) they're authored by hand rather than
457
+ * codegen'd. Each nests `run[]` stacks encoded through the shared statement
458
+ * encoder.
459
+ *
460
+ * Stored shapes (from the Xano engine's persisted switch / try_catch shapes):
461
+ * switch → context: { value:<Value>, elif:{ run:[switch_case…] }, else:{ run:[…] } }
462
+ * switch_case → context: { value:<Value>, break?:bool, if:{ run:[…] } }
463
+ * try_catch → context: { if:{ run:[…try…] }, else:{ run:[…catch…] }, then:{ run:[…finally…] } }
464
+ *
465
+ * In `switch`, `value` is the subject being matched and each `switch_case`'s
466
+ * `value` is the literal a case compares against; `else.run` is the `default`
467
+ * block. `break` (fallthrough control) is omitted unless explicitly set, matching
468
+ * the golden fixture. In `try_catch`, the engine maps try→`if`, catch→`else`,
469
+ * finally→`then`; all three blocks are always emitted (engine `exportContext`
470
+ * normalizes each to `{ run: [] }`).
471
+ */
472
+
473
+ interface SwitchCaseArgs extends StatementAnnotations {
474
+ /** The literal this case matches against the switch subject. */
475
+ when: Value;
476
+ /** Statements run when this case matches. */
477
+ body: Statement[];
478
+ /**
479
+ * Whether to stop after this case (`true`) or fall through to the next
480
+ * (`false`). Omitted from the stored shape entirely when not set.
481
+ */
482
+ break?: boolean;
483
+ }
484
+ /** A single `case (when) { body }` clause of a `switch`. */
485
+ declare function switchCase(args: SwitchCaseArgs): Statement;
486
+ interface SwitchArgs extends StatementAnnotations {
487
+ /** The subject value being matched. */
488
+ on: Value;
489
+ /** Ordered `case` clauses. */
490
+ cases: SwitchCaseArgs[];
491
+ /** The `default` block, run when no case matches. */
492
+ default?: Statement[];
493
+ }
494
+ /** `switch (on) { case … default … }` — multi-way branch. */
495
+ declare function switchStatement(args: SwitchArgs): Statement;
496
+ interface TryCatchArgs extends StatementAnnotations {
497
+ /** The protected block (engine `if`). */
498
+ try: Statement[];
499
+ /** Error-handler block (engine `else`). */
500
+ catch?: Statement[];
501
+ /** Always-run block (engine `then`). */
502
+ finally?: Statement[];
503
+ }
504
+ /** `try_catch { try … catch … finally … }` — error handling block. */
505
+ declare function tryCatch(args: TryCatchArgs): Statement;
506
+
507
+ /**
508
+ * Shared coercion plumbing for the hand-authored statement wrappers — the units
509
+ * that turn an ergonomic, literal-friendly authored field into the `Value` the
510
+ * generated factory encodes, so the wrapper delegates for byte-parity.
511
+ *
512
+ * Two families live here. The HTTP-request fields (`api.request`,
513
+ * `stream.from_request`, `webflow.request`, `microservice.request`) were hoisted
514
+ * per the rule of three once the second wrapper landed. The DB row CELL joined
515
+ * them (issue #92): it is a self-contained coercion unit that landed in `db.ts`
516
+ * only because that is where its caller is, and its siblings — `coerceScalar`,
517
+ * `coerceObj`, `coerceHeaders` — were already here.
518
+ */
519
+
520
+ /**
521
+ * The HTTP verbs the engine's runtime input schema accepts. Enforced: the
522
+ * wrapper coerces to a `Value` and delegates to the generated factory, whose
523
+ * spec now carries the same set and rejects a constant outside it.
524
+ */
525
+ type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH";
526
+ /** A headers map: full header lines built from `Name: value` pairs (issue #72). */
527
+ type HeaderMap = Readonly<Record<string, string | Value>>;
528
+ /**
529
+ * A value acceptable in a call/agent `input` map — a raw scalar literal, a nested
530
+ * object/array, or a tagged {@link Value}. Widening the maps to this lets
531
+ * `input: { max_age_days: 3 }` compile without wrapping every literal in `c.int`.
532
+ */
533
+ type InputValue = string | number | boolean | object | Value;
534
+ /** The shared TLS/HTTP fields carried by `api.request` / `stream.from_request` / `webflow.request`. */
535
+ interface HttpRequestFields {
536
+ method?: HttpMethod | (string & {}) | Value;
537
+ params?: object | Value;
538
+ headers?: readonly string[] | HeaderMap | Value;
539
+ timeout?: number | Value;
540
+ follow_location?: boolean | Value;
541
+ verify_host?: boolean | Value;
542
+ verify_peer?: boolean | Value;
543
+ ca_certificate?: string | Value;
544
+ certificate?: string | Value;
545
+ certificate_pass?: string | Value;
546
+ private_key?: string | Value;
547
+ private_key_pass?: string | Value;
548
+ }
549
+ /**
550
+ * The bare JS literals a row cell accepts for a column whose row type is `V`,
551
+ * mirroring the `Scalar` union `fl.*` arguments and `seed` rows already take
552
+ * (issue #75).
553
+ *
554
+ * Keyed on the column's own inferred type, so the widening is STRICTER than the
555
+ * tagged spelling it replaces: `{ is_hidden: "yes" }` on an `f.bool()` column is
556
+ * a compile error here, where `{ is_hidden: c.text("yes") }` was always accepted.
557
+ * An `f.enum` column keeps its literal union, so a non-member is refused too.
558
+ *
559
+ * `null` is admitted on EVERY column, including the ones that refuse every other
560
+ * literal — an `obj`/`json`/list/`geo`/`vector` column has no bare-literal form
561
+ * and throws for a string, number or boolean, but takes `null`. That asymmetry
562
+ * is the decision, not an oversight (issue #90): nulling a cell is a legitimate
563
+ * write whatever the column reads back as, and it matches what a seed row does
564
+ * with a `null` (see `coerceScalarValue` — nullability is the engine's to
565
+ * enforce, and a column config this layer does not fully model is not something
566
+ * to guess at). Two consequences worth knowing, both stated on the grounding
567
+ * surface: on a column with no literal form, `null` is the ONLY literal the cell
568
+ * type offers; and an explicit `null` is not the same as omitting the key, which
569
+ * takes the type default in {@link defaultCell} instead.
570
+ *
571
+ * A column whose inferred value is `unknown` — a raw `ColumnDef[]` schema, or an
572
+ * `f.json()` column, which reads back as `unknown` by construction — has nothing
573
+ * to key on, so it falls back to the whole scalar union and leans on the
574
+ * encoder's own check. The escape hatch is not made stricter than it was.
575
+ */
576
+ type ScalarCell<V> = [unknown] extends [V] ? string | number | boolean | null : (V extends string | number | boolean ? V : never) | null;
577
+
578
+ /**
579
+ * Background execution for a call statement.
580
+ *
581
+ * Shared by `function.run` and `ai.agent.run`: the engine reads the SAME
582
+ * top-level `runtime` block for both, in one `switch` over `runtime.mode`.
583
+ * Keeping the model in one place is what stops the two surfaces drifting into
584
+ * different vocabularies — which is exactly what had happened before this
585
+ * module existed.
586
+ */
587
+ /**
588
+ * How a call executes: synchronously (the default), or in the background on
589
+ * shared or dedicated async workers.
590
+ *
591
+ * Stored as a TOP-LEVEL `runtime` block on the stack item — not inside
592
+ * `context`. The engine switches on `runtime.mode` and treats every value
593
+ * outside this union (including the absent block and the editor's explicit
594
+ * `"disabled"`) as synchronous.
595
+ *
596
+ * Async is not a performance knob — it changes what the statement returns.
597
+ * `mvp:function` is rewritten to `mvp:async_function`, so the call no longer
598
+ * yields the function's result; it dispatches and continues. Pair it with
599
+ * `s.await(...)` to collect results.
600
+ */
601
+ type AsyncMode = "async-shared" | "async-dedicated";
602
+ /** Background execution settings for a call. */
603
+ interface AsyncRuntime {
604
+ /**
605
+ * `"async-shared"` runs on the instance's pooled async workers and reads no
606
+ * other member here. `"async-dedicated"` reserves its own resources and is
607
+ * the only mode for which `cpu`/`memory`/`timeout`/`maxRetry` are read.
608
+ */
609
+ mode: AsyncMode;
610
+ /** Dedicated only. Kubernetes CPU request — e.g. `"100m"`, `"250m"`, `"500m"`. */
611
+ cpu?: string;
612
+ /** Dedicated only. Kubernetes memory request — e.g. `"256Mi"`, `"512Mi"`, `"1Gi"`. */
613
+ memory?: string;
614
+ /** Dedicated only. Seconds before the run is abandoned. */
615
+ timeout?: string | number;
616
+ /** Dedicated only. Retries after a failed run. */
617
+ maxRetry?: string | number;
618
+ }
619
+
620
+ /**
621
+ * Hand-authored call-family block statements (U10) — invoking another workspace
622
+ * object from a stack. These carry `!class` transforms in the engine
623
+ * (FunctionRun, FunctionCall, ApiCall, …) so they're authored by hand.
624
+ *
625
+ * Each stores a **cross-object reference** to its target. In a packageExport
626
+ * bundle that reference is the target's guid (the engine's exportTypeId maps a
627
+ * local id → guid on export); xanots resolves the authored target → its
628
+ * deterministic guid via `resolveRef` (see refs/guid.ts), so the emitted call
629
+ * and the target object's payload `guid` agree and the import remaps both.
630
+ *
631
+ * Stored shapes (from the Xano engine's persisted context shapes):
632
+ * function.run → mvp:function ctx { function: { id:<guid> } } [+input]
633
+ * function.call → mvp:workspace_run_function ctx { id:<guid> } [+input]
634
+ * api.call → mvp:workspace_run_endpoint ctx { id:<guid> } [+input]
635
+ * task.call → mvp:workspace_run_task ctx { id:<guid> }
636
+ * tool.call → mvp:workspace_run_tool ctx { id:<guid> } [+input]
637
+ * trigger.call → mvp:workspace_run_trigger ctx { id:<guid> } [+input]
638
+ * middleware.call → mvp:workspace_run_middleware ctx { id:<guid> } [+input]
639
+ * addon.call → mvp:workspace_run_addon ctx { id:<guid> } [+input]
640
+ *
641
+ * The target object's id resolves to a guid keyed by the engine's migrate
642
+ * *type*: function.run/call → "function", api.call → "query" (an API endpoint
643
+ * is a `query` object), and the rest map name-for-name.
644
+ *
645
+ * Scope: connected-service functions are OUT, permanently — they were never
646
+ * released in Xano, so no engine produces the shape and no workspace can hold
647
+ * one. `mvp:function` therefore has exactly one authoring surface, storing the
648
+ * default payload. Async execution IS modelled (see {@link AsyncRuntime});
649
+ * api.call emits the `headers`/`auth` blocks (verb/name/api_group are
650
+ * engine-derived, not stored).
651
+ *
652
+ * @TODO(byte-verify): `function.run` (mvp:function), `api.call` (context.token
653
+ * confirmed tagged), and — since the workflow-test capture — `function.call`
654
+ * (mvp:workspace_run_function) are golden-verified. Still modeled/unverified:
655
+ * - the remaining `workspace_run_*` (task/tool/trigger/middleware/addon) — no
656
+ * golden, but they share the single-key `id` context two goldens now pin.
657
+ * - `workflow_test` → context.{datasource,id} — decode-accurate, no golden.
658
+ * - action / action_package — EXCLUDED from byte-verify: they need an
659
+ * action-identity model first (action id currently resolves via the "function"
660
+ * migrate type, likely wrong; action_package is emitted empty). See their own
661
+ * @TODOs below — do not vendor/capture until the identity model exists.
662
+ */
663
+
664
+ /** A call/agent `{name: value}` input map — raw scalar literals coerce to constants. */
665
+ type CallInput = Record<string, InputValue>;
666
+ /**
667
+ * A call's target function — a def handle or name, or `null` for the engine's own
668
+ * empty binding (`context.function.id: ""`).
669
+ *
670
+ * ⚠ **Do not author `null`.** It is a BROKEN state in Xano, not a neutral one:
671
+ * the statement calls nothing. It exists so `codegen` can represent a broken
672
+ * statement faithfully rather than degrade it to `raw()` — a pulled `fn: null` is
673
+ * a defect to fix in the pulled workspace, not a shape to copy. Same contract as
674
+ * a db statement's `table` and an addon's, which is where the pattern comes from.
675
+ */
676
+ type FnRef = ObjectRef | null;
677
+ interface FunctionRunArgs<Fn extends FnRef = FnRef, As extends string = string> extends StatementOptions {
678
+ /** The target function (def handle or name), or `null` when unbound. */
679
+ fn: Fn;
680
+ /** Capture the result into this stack variable. */
681
+ as?: As;
682
+ /** Input bindings, keyed by the target's input names. */
683
+ input?: CallInput;
684
+ /**
685
+ * Run the function in the background instead of inline. Omit for a normal
686
+ * synchronous call. See {@link AsyncRuntime} — an async call does NOT return
687
+ * the function's result.
688
+ */
689
+ runtime?: AsyncRuntime;
690
+ }
691
+ /**
692
+ * `function.run <fn>` — run another function inline.
693
+ *
694
+ * Branded `AsShapeBrand<As, InferResponse<Fn>>` (issue #209): the bound variable
695
+ * carries the TARGET's response type, so `ref("<as>.field")` in the caller's
696
+ * response types to that field instead of `unknown`. See {@link functionCall}
697
+ * for what the propagation can and cannot see.
698
+ *
699
+ * An ASYNC run (`runtime`) is deliberately still branded with the function's
700
+ * shape: the engine binds a job handle rather than the result, but `runtime` is
701
+ * an authored value the type system reads as a whole `AsyncRuntime` regardless
702
+ * of what it holds, so narrowing on it would be a guess. Declare `responseShape`
703
+ * on the caller if an async run's binding reaches the response.
704
+ */
705
+ declare function functionRun<const Fn extends FnRef = FnRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: FunctionRunArgs<Fn, As> & {
706
+ asFilters?: Fs;
707
+ }): Statement & AsShapeBrand<As, ApplyFilters<InferResponse<Fn>, Fs>>;
708
+ interface FunctionCallArgs<Fn extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
709
+ fn: Fn;
710
+ as?: As;
711
+ input?: CallInput;
712
+ }
713
+ /**
714
+ * `function.call <fn>` — invoke a function as a workspace run.
715
+ *
716
+ * Branded `AsShapeBrand<As, InferResponse<Fn>>` (issue #209). `InferResponse` of
717
+ * the TARGET is exactly what a client would get back from it, so drilling into
718
+ * the binding now types:
719
+ *
720
+ * ```ts
721
+ * stack: [s.function.call({ fn: calculateDiscount, input: {…}, as: "discount" })],
722
+ * response: { cents: ref("discount.discount_cents") }, // number, was unknown
723
+ * ```
724
+ *
725
+ * What it can see is what `InferResponse` can see on the target: a declared
726
+ * `responseShape` always, and otherwise the target's own auto-derivation (object
727
+ * literal keys, a variable traced to a typed `db.*`). A target whose response
728
+ * bottoms out at `unknown` — or one named by STRING rather than by def handle,
729
+ * where there is no def to read — propagates that `unknown` unchanged. Declaring
730
+ * `responseShape` on the TARGET fixes every caller at once, which is why that
731
+ * remains the recommendation for a response the walk cannot resolve.
732
+ */
733
+ declare function functionCall<const Fn extends ObjectRef = ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: FunctionCallArgs<Fn, As> & {
734
+ asFilters?: Fs;
735
+ }): Statement & AsShapeBrand<As, ApplyFilters<InferResponse<Fn>, Fs>>;
736
+ interface ApiCallArgs<Api extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
737
+ /** The target API endpoint (a `query` object). */
738
+ api: Api;
739
+ as?: As;
740
+ input?: CallInput;
741
+ /**
742
+ * Replace the request headers the called endpoint sees. Same shape as
743
+ * `s.api.request`'s: a `{ "Name": value }` record (values may be tagged), a
744
+ * `string[]` of full `"Name: value"` lines, or one whole `Value`.
745
+ *
746
+ * ⚠ This is the ONLY slot that authenticates a call with a token computed
747
+ * during the run — an `Authorization` header is read and applied as the
748
+ * caller's token, while `auth.token` is a static string (see {@link ApiCallArgs.auth}):
749
+ *
750
+ * ```ts
751
+ * s.api.call({ api: signup, input: {…}, as: "signup" }),
752
+ * s.api.call({ api: checkout, headers: { Authorization: ref("signup.authToken") } }),
753
+ * ```
754
+ *
755
+ * Send `Authorization` only to an endpoint that declares `auth` — the engine
756
+ * enforces that the token's table matches the target's, and a target with no
757
+ * `auth` rejects any token as belonging to a different object type.
758
+ */
759
+ headers?: readonly string[] | HeaderMap | Value;
760
+ /**
761
+ * Authenticate the call with a STATIC token, and optionally ignore its expiry.
762
+ *
763
+ * ⚠ `token` is stored in a slot the engine declares as plain text and does NOT
764
+ * evaluate, so a tagged `Value` — `ref("signup.authToken")`, `env("TOKEN")` —
765
+ * is rejected at runtime with `Param: token - Text filter requires an integer,
766
+ * float, string or boolean value`, even though it deploys clean. Only a bare
767
+ * **string** runs. For a token minted during the run, use an `Authorization`
768
+ * entry in {@link ApiCallArgs.headers} instead.
769
+ *
770
+ * The `Value` spelling stays accepted so a pulled workspace holding one
771
+ * round-trips as itself (issue #139) — it is a shape to carry, not to author.
772
+ */
773
+ auth?: {
774
+ token: Value | string;
775
+ ignoreExpiration?: boolean;
776
+ };
777
+ }
778
+ /**
779
+ * `api.call <endpoint>` — invoke an API endpoint as a workspace run. The stored
780
+ * `context` is `{ id, headers?, token?, token_ignore_expiration? }` (the engine
781
+ * derives name/verb/api_group from the referenced query at encode time, so they
782
+ * are intentionally NOT stored). Shape modeled on the engine's stored api-call format.
783
+ *
784
+ * `context.headers` is a tagged value the engine EVALUATES, so it carries a
785
+ * runtime-computed `Authorization`. `context.token` is not: the engine declares
786
+ * that slot as plain text, so a tagged token round-trips byte-for-byte (the
787
+ * golden pins that) and is then rejected the moment the statement runs. See
788
+ * {@link ApiCallArgs.auth}.
789
+ */
790
+ declare function apiCall<const Api extends ObjectRef = ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: ApiCallArgs<Api, As> & {
791
+ asFilters?: Fs;
792
+ }): Statement & AsShapeBrand<As, ApplyFilters<InferResponse<Api>, Fs>>;
793
+ interface TaskCallArgs extends StatementOptions {
794
+ /** The target background task. */
795
+ task: ObjectRef;
796
+ as?: string;
797
+ }
798
+ /** `task.call <task>` — invoke a task as a workspace run (no input). */
799
+ declare function taskCall(args: TaskCallArgs): Statement;
800
+ interface ToolCallArgs<Tool extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
801
+ tool: Tool;
802
+ as?: As;
803
+ input?: CallInput;
804
+ }
805
+ /**
806
+ * `tool.call <tool>` — invoke a tool as a workspace run. Branded with the
807
+ * TARGET's `InferResponse` (issue #209), like {@link functionCall}.
808
+ */
809
+ declare function toolCall<const Tool extends ObjectRef = ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: ToolCallArgs<Tool, As> & {
810
+ asFilters?: Fs;
811
+ }): Statement & AsShapeBrand<As, ApplyFilters<InferResponse<Tool>, Fs>>;
812
+ interface TriggerCallArgs extends StatementOptions {
813
+ trigger: ObjectRef;
814
+ as?: string;
815
+ input?: CallInput;
816
+ }
817
+ /** `trigger.call <trigger>` — invoke a trigger as a workspace run. */
818
+ declare function triggerCall(args: TriggerCallArgs): Statement;
819
+ interface MiddlewareCallArgs extends StatementOptions {
820
+ middleware: ObjectRef;
821
+ as?: string;
822
+ input?: CallInput;
823
+ }
824
+ /** `middleware.call <middleware>` — invoke middleware as a workspace run. */
825
+ declare function middlewareCall(args: MiddlewareCallArgs): Statement;
826
+ interface AddonCallArgs extends StatementOptions {
827
+ addon: ObjectRef;
828
+ as?: string;
829
+ input?: CallInput;
830
+ }
831
+ /** `addon.call <addon>` — invoke an addon as a workspace run. */
832
+ declare function addonCall(args: AddonCallArgs): Statement;
833
+ interface ActionCallArgs extends StatementOptions {
834
+ /** The action's name. */
835
+ action: ObjectRef;
836
+ /** The action package identifier. */
837
+ package?: string;
838
+ as?: string;
839
+ input?: CallInput;
840
+ }
841
+ /**
842
+ * `action.call <action>` — invoke a marketplace/action operation (`mvp:action`).
843
+ * Stored shape from the engine's action-call format: `context.run_version.id` is the action
844
+ * id and `settings_registry` is always present.
845
+ *
846
+ * @TODO(byte-verify): xanots has no `action` kind, so the id resolves via the
847
+ * "function" migrate type — likely WRONG (actions are a distinct namespace,
848
+ * `mapActionNameToId`). input[] uses the lean shape; the engine uses
849
+ * `convertBlockToInput` (may be the rich form). No golden.
850
+ */
851
+ declare function actionCall(args: ActionCallArgs): Statement;
852
+ /**
853
+ * `action.package.call <action>` — invoke an action-package operation
854
+ * (`mvp:action_package`). Stored shape from the engine's action-package format:
855
+ * `context.{action:{trace_id}, package:{slug}, package_version:{id}}`.
856
+ *
857
+ * @TODO(byte-verify): MODELED skeleton only — xanots doesn't model marketplace
858
+ * action packages (trace_id / package slug / version id come from
859
+ * `mapActionPackageNameToId`), so these are emitted EMPTY. This statement is a
860
+ * reachable placeholder, NOT functional, until the action-package identity model
861
+ * exists. No golden.
862
+ */
863
+ declare function actionPackageCall(args: ActionCallArgs): Statement;
864
+ interface WorkflowTestCallArgs extends StatementOptions {
865
+ /** The target workflow test. */
866
+ workflowTest: ObjectRef;
867
+ as?: string;
868
+ /** Data source to run against. */
869
+ datasource?: string;
870
+ }
871
+ /**
872
+ * `workflow_test.call <test>` — run a workflow test
873
+ * (`mvp:workspace_run_workflow_test`). Stored shape from the engine's workflow-test format:
874
+ * `context.{datasource, id}` — `datasource` is ALWAYS present (default `""`).
875
+ */
876
+ declare function workflowTestCall(args: WorkflowTestCallArgs): Statement;
877
+
878
+ /**
879
+ * Hand-authored AI-agent and cloud-job specials (U10). All carry `!class`
880
+ * transforms in the engine (AgentRun, CloudJob, CloudJobAwait, CloudJobStatus).
881
+ * The stored shapes here are modeled on those transforms' `decode()` methods
882
+ * (authoritative for the persisted form), so they're grounded — but still have
883
+ * no golden fixture to deep-equal against.
884
+ *
885
+ * call_agent and cloud_job{,_await,_status} are golden-verified against live
886
+ * engine captures (see the conformance corpus): agent → context.toolset.id +
887
+ * top-level runtime + input[]; cloud jobs → everything in input[] with the
888
+ * captured entry order. `runtime` is omitted at the default "shared" mode, and
889
+ * `await` is passed through as authored.
890
+ */
891
+
892
+ /**
893
+ * The rich result object an agent run binds to its `as` variable — modeled on
894
+ * the engine's agent-run result envelope (issue #89). **The completion is at
895
+ * `.result`**, not the top level; the surrounding fields are run metadata.
896
+ *
897
+ * `R` is the completion type: `string` for a text agent (the default — including
898
+ * `xano-free`), or an object when structured outputs (a schema) are enabled. When
899
+ * the run targets an agent *handle* it is inferred from that agent's `output.schema`
900
+ * automatically; the `resultShape` witness on {@link AiAgentRunArgs} overrides it.
901
+ *
902
+ * `finishReasonCandidate`/`toolCalls`/`usage`/`totalUsage` are optional: they are
903
+ * absent or empty depending on the run (no tools, single provider, engine
904
+ * version), so a returned envelope may carry only a subset.
905
+ */
906
+ interface AgentRunResult<R = string> {
907
+ /** The model's completion — the field almost every caller wants. `string` unless structured outputs are enabled (then an object, inferred from the agent's `output.schema`). */
908
+ result: R;
909
+ /** Why generation stopped: `'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other' | 'unknown'`. */
910
+ finishReason: string;
911
+ /** Provider-specific metadata (e.g. usage counters, safety signals), keyed by provider. */
912
+ providerMetadata: Record<string, Record<string, unknown>>;
913
+ /** Reasoning parts emitted by the model; `[]` when none. */
914
+ reasoningDetails: unknown[];
915
+ /** Per-step records (each with e.g. `text`, `finishReason`, `usage`, `toolCalls`, `providerMetadata`). */
916
+ steps: unknown[];
917
+ /** Fallback finish reason, populated only when `finishReason` is `'unknown'`; otherwise empty/absent. */
918
+ finishReasonCandidate?: string;
919
+ /** Merged tool-call + result records; absent or empty when no tools ran. */
920
+ toolCalls?: unknown[];
921
+ /** Token usage for the final generation (`inputTokens`, `outputTokens`, `totalTokens`, …). */
922
+ usage?: Record<string, unknown>;
923
+ /** Token usage aggregated across all steps. */
924
+ totalUsage?: Record<string, unknown>;
925
+ }
926
+ interface AiAgentRunArgs<As extends string = "", A extends ObjectRef = ObjectRef, R = AgentResultOf<A>> extends StatementOptions {
927
+ /** The target agent (toolset of type agent — def handle or name). */
928
+ agent: A;
929
+ /** The stack variable this run binds. Captured literally so `InferResponse` can trace a `ref` back to the typed {@link AgentRunResult}. */
930
+ as?: As;
931
+ /**
932
+ * Run arguments passed to the agent. Pass a single {@link Value}, or an object
933
+ * literal of values (`{ question: inp("question") }`) which is built into a
934
+ * dynamic object via {@link obj}. This becomes the agent's `$args` Twig
935
+ * namespace: the agent's string settings (system prompt, prompt, model,
936
+ * provider config) reference these as `{{ $args.propertyName }}`, resolved per
937
+ * invocation before the LLM call. (Env vars are `{{ $env.NAME }}`.) See
938
+ * `kinds/agent.ts` for the full templating rules.
939
+ */
940
+ args?: Value | ObjInput;
941
+ /** Whether the agent may execute its tools. */
942
+ allowToolExecution?: Value;
943
+ /** Pinned agent version. */
944
+ version?: Value;
945
+ /**
946
+ * Run the agent in the background instead of inline. Omit for a normal
947
+ * synchronous call. Shares {@link AsyncRuntime} with `function.run` — the
948
+ * engine reads the same top-level block for both.
949
+ */
950
+ runtime?: AsyncRuntime;
951
+ /**
952
+ * Type-only override for the `.result` completion type. Usually unnecessary:
953
+ * when `agent` is a def handle from `agent({ output: { schema } })`, `.result`
954
+ * is inferred straight from that schema via {@link AgentResultOf} (issue
955
+ * #124.1). Pass a witness only to override that inference or to type the
956
+ * `.result` of an agent referenced by bare name (which carries no schema) —
957
+ * e.g. `resultShape: {} as { sentiment: string }`. Never emitted into the
958
+ * statement (phantom, like the response brand).
959
+ */
960
+ resultShape?: R;
961
+ }
962
+ /**
963
+ * `ai.agent.run <agent>` — invoke an AI agent (`mvp:call_agent`). Stored shape
964
+ * from the engine's agent-run format: the target is `context.toolset.id`, `runtime` is a
965
+ * TOP-LEVEL `{ mode }` block, and `args`/`allow_tool_execution`/`version` are
966
+ * `input[]` entries (NOT context). `runtime` is emitted only when a mode is set.
967
+ *
968
+ * Branded with `AsShapeBrand<As, AgentRunResult<R>>` (like the `db.*` producers)
969
+ * so `ref(as)` traces to the typed {@link AgentRunResult} envelope via
970
+ * `InferResponse` instead of `unknown` — the completion is at `.result` (#89).
971
+ * A dotted `ref("<as>.result")` now projects that completion directly (#93), so
972
+ * the common "return just the answer" endpoint no longer needs a `responseShape`.
973
+ * The brand is phantom; the emitted statement bytes are unchanged.
974
+ */
975
+ declare function aiAgentRun<const As extends string = "", const A extends ObjectRef = ObjectRef, R = AgentResultOf<A>, const Fs extends readonly FilterXdo[] = readonly []>(a: AiAgentRunArgs<As, A, R> & {
976
+ asFilters?: Fs;
977
+ }): Statement & AsShapeBrand<As, ApplyFilters<AgentRunResult<R>, Fs>>;
978
+ interface CloudJobArgs extends StatementOptions {
979
+ as?: string;
980
+ image?: Value;
981
+ command?: Value;
982
+ args?: Value;
983
+ secret?: Value;
984
+ template?: Value;
985
+ /** Seconds to await completion (default 60). */
986
+ await?: Value;
987
+ }
988
+ /**
989
+ * `cloud.job { … }` — launch a containerized cloud job (`mvp:cloud_job`). Stored
990
+ * shape from the engine's cloud-job format: every block (image/command/args/secret/template/
991
+ * await) is an `input[]` entry; `context` is empty.
992
+ *
993
+ * Golden-verified against a live capture: the input[] entry order
994
+ * (image→command→args→secret→template→await) matches the persisted shape.
995
+ */
996
+ declare function cloudJob(a: CloudJobArgs): Statement;
997
+ interface CloudJobAwaitArgs extends StatementOptions {
998
+ as?: string;
999
+ /** Job ids to await. */
1000
+ ids: Value;
1001
+ /** Timeout in seconds. */
1002
+ timeout: Value;
1003
+ }
1004
+ /**
1005
+ * `cloud.job.await { … }` — wait for cloud jobs to finish (`mvp:cloud_job_await`).
1006
+ * `ids`/`timeout` are `input[]` entries with empty context (per the engine's cloud-job-await format).
1007
+ */
1008
+ declare function cloudJobAwait(a: CloudJobAwaitArgs): Statement;
1009
+ interface CloudJobStatusArgs extends StatementOptions {
1010
+ as?: string;
1011
+ /** The job id to query. */
1012
+ id: Value;
1013
+ }
1014
+ /**
1015
+ * `cloud.job.status { … }` — read a cloud job's status (`mvp:cloud_job_status`).
1016
+ * `id` is an `input[]` entry with empty context (per the engine's cloud-job-status format).
1017
+ */
1018
+ declare function cloudJobStatus(a: CloudJobStatusArgs): Statement;
1019
+
1020
+ /**
1021
+ * Hand-authored miscellaneous specials (U10) — the remaining `!class` /
1022
+ * `!function` / declarative statements without a generated factory: array
1023
+ * map/union, the comment & placeholder nodes, raw-input access, post-process,
1024
+ * realtime events, auth-token creation, and the `expect.to_throw` test
1025
+ * assertion.
1026
+ *
1027
+ * `comment`, `realtime_event`, and `create_auth` have declarative transforms in
1028
+ * the engine schema and are encoded to match them; the rest are `!class` with no
1029
+ * persisted golden yet, so they are **structural** (reachable, byte-verified
1030
+ * later). Block fields map to same-named `context` entries unless the schema's
1031
+ * declarative transform says otherwise.
1032
+ *
1033
+ * array_map, array_union, get_input, and test_expect_to_throw are now
1034
+ * golden-verified against live engine captures (see the conformance corpus);
1035
+ * post_process is parser-verified. Remaining unverified spots:
1036
+ * (1) array_map — the scalar `transform_value` path is byte-exact. The
1037
+ * object-literal form (`transform_object` + `output_type:"object"`) is now
1038
+ * authorable and round-trips through codegen, but is modeled from the
1039
+ * engine's declared context schema rather than a capture: no golden yet.
1040
+ * (2) create_auth — input order is `id/dbtable/extras/expiration`, read from the
1041
+ * engine's own input schema; `extras`/`expiration` are `?=` optionals and
1042
+ * are omitted when unset. Only the `dbtable` const tag is unverified.
1043
+ * (3) realtime_event — context.{channel,data,auth.{dbo_id,row_id}} CONFIRMED by
1044
+ * the schema transform (auth_table via !map:dbo:constant → table guid).
1045
+ */
1046
+
1047
+ interface ArrayMapArgs extends StatementOptions {
1048
+ /** The source array → stored `collection`. */
1049
+ source: Value;
1050
+ as?: string;
1051
+ /**
1052
+ * How each item maps. Three forms, and the form picks the engine's `output_type`:
1053
+ * - a single {@link Value} → each item maps to that scalar expression
1054
+ * (`output_type:"value"`, stored `transform_value`);
1055
+ * - a record of values → each item maps to an OBJECT with those keys
1056
+ * (`output_type:"object"`, stored `transform_object[]`);
1057
+ * - a list of `{key, value}` pairs → the same object form, for the keys a
1058
+ * record cannot hold: one the engine COMPUTES per item, or two rows sharing
1059
+ * a key (see {@link ArrayMapAttribute}).
1060
+ *
1061
+ * Use `ref("$this")` for the current item and `ref("$index")` for its position.
1062
+ * An empty record is rejected — the engine's object branch iterates
1063
+ * `transform_object` and would map every item to `{}`.
1064
+ */
1065
+ transform?: Value | Record<string, Value> | ArrayMapAttribute[];
1066
+ }
1067
+ /**
1068
+ * One key/value pair of an object transform, for the shapes a record cannot
1069
+ * hold.
1070
+ *
1071
+ * The engine evaluates `attribute_key` per item exactly as it evaluates the
1072
+ * value, so a key can be a variable, an input, or a filtered expression — and
1073
+ * two rows may carry the SAME key, which a record would silently collapse to
1074
+ * the last one. Reach for the record form whenever the keys are plain literals;
1075
+ * it is what an ordinary object mapping should read like.
1076
+ */
1077
+ interface ArrayMapAttribute {
1078
+ /** The key this row contributes, evaluated per item. */
1079
+ key: Value;
1080
+ /** The value stored under it. */
1081
+ value: Value;
1082
+ }
1083
+ /**
1084
+ * `array.map <source>` — map each element through an expression (`mvp:array_map`).
1085
+ *
1086
+ * Both engine output modes are golden-verified against live captures. The object
1087
+ * path (`output_type:"object"` + `transform_object[]`) stores one
1088
+ * `{attribute_key, attribute_value}` entry per record key, in authored order,
1089
+ * and the key is a plain `const` text triple.
1090
+ *
1091
+ * Only the LIVE branch is emitted, and the capture confirms the engine agrees:
1092
+ * an imported object-mode statement stores NO `transform_value`, and a
1093
+ * value-mode one stores no `transform_object`. The EDITOR is the exception — it
1094
+ * builds its form from the whole context schema and saves every control, so an
1095
+ * editor-saved object-mode statement also carries `transform_value` at its
1096
+ * schema defaults. Both spellings are one state (the engine's object branch
1097
+ * never reads `transform_value`); `liveArrayMapContext` in validate/normalize.ts
1098
+ * is where that equivalence lives, so an editor-authored statement still reads
1099
+ * back to this factory instead of falling to `raw()`.
1100
+ *
1101
+ * ```ts
1102
+ * // scalar: ["a","b"] → ["A","B"]
1103
+ * s.array.map({ source: ref("names"), as: "upper", transform: withFilters(ref("$this"), fl.upper()) })
1104
+ * // object: [1,2] → [{id:1, pos:0}, {id:2, pos:1}]
1105
+ * s.array.map({ source: ref("ids"), as: "rows", transform: { id: ref("$this"), pos: ref("$index") } })
1106
+ * ```
1107
+ */
1108
+ declare function arrayMap(a: ArrayMapArgs): Statement;
1109
+ interface ArrayUnionArgs extends StatementOptions {
1110
+ /** The base array → stored `left`. */
1111
+ source: Value;
1112
+ /** The array to union in → stored `right`. */
1113
+ with?: Value;
1114
+ as?: string;
1115
+ /** Optional per-item transform → stored `transform_value`. */
1116
+ transform?: Value;
1117
+ }
1118
+ /**
1119
+ * `array.union <source>` — set-union of arrays (`mvp:array_union`).
1120
+ *
1121
+ * Golden-verified against a live capture: the field remap (source→left,
1122
+ * with→right, transform→transform_value) matches the engine's array-union format.
1123
+ */
1124
+ declare function arrayUnion(a: ArrayUnionArgs): Statement;
1125
+ /**
1126
+ * `comment` — a no-op annotation node (`mvp:comment`). The text IS this
1127
+ * statement's `description`, so `text` and `a.description` set the same member
1128
+ * and an explicit `a.description` wins; `a.disabled` applies as it does anywhere.
1129
+ */
1130
+ declare function comment(text?: string, a?: StatementAnnotations): Statement;
1131
+ interface GetRawInputArgs extends StatementOptions {
1132
+ as?: string;
1133
+ /** Body decoding (`json`, `raw`, …). */
1134
+ encoding?: Value;
1135
+ /** Skip middleware-applied transforms. */
1136
+ excludeMiddleware?: Value;
1137
+ }
1138
+ /**
1139
+ * `util.get_raw_input` / `util.get_input` — capture the raw request body
1140
+ * (`mvp:get_input`). Empty context, and up to two `input[]` entries — `encoding`
1141
+ * (`?=json`) and `exclude_middleware_modification` (note the full stored name;
1142
+ * `?=false`). Both are optional in the engine schema and are written only when
1143
+ * authored, matching what Xano's editor stores.
1144
+ */
1145
+ declare function getRawInput(a?: GetRawInputArgs): Statement;
1146
+ /**
1147
+ * `util.post_process { … }` — run a post-response sub-stack (`mvp:post_process`).
1148
+ * A pure block statement (engine schema `args: []`): no `as`, just the `run`
1149
+ * stack. Byte-verified (parser-minimal) against the engine's persisted shape.
1150
+ */
1151
+ declare function postProcess(body: Statement[], a?: StatementAnnotations): Statement;
1152
+ interface RealtimeEventArgs extends StatementAnnotations {
1153
+ /** The channel to publish on. */
1154
+ channel: Value;
1155
+ /** The event payload. */
1156
+ data: Value;
1157
+ /** Optional auth table whose row scopes the event. */
1158
+ authTable?: ObjectRef;
1159
+ /** The auth row id. */
1160
+ authId: Value;
1161
+ }
1162
+ /**
1163
+ * `api.realtime_event { … }` — publish a realtime event (`mvp:realtime_event`).
1164
+ *
1165
+ * @deprecated Superseded by {@link realtimePublish}. This publishes to Xano's older
1166
+ * workspace-global realtime layer, NOT to a `realtimeChannel()` — its `channel` is a
1167
+ * string against that layer, so pointing it at a current-layer channel path publishes
1168
+ * into the void.
1169
+ *
1170
+ * To originate an event on the current layer, use `s.realtime.publish`, which names the
1171
+ * owning `realtimeServer()` and so addresses a real `realtimeChannel()`.
1172
+ *
1173
+ * Still exported and still supported so `xanots codegen` can bring back a workspace
1174
+ * that holds one. Withheld from the `llms.txt` statement catalog and named only under
1175
+ * `llms/legacy.md`.
1176
+ */
1177
+ declare function realtimeEvent(a: RealtimeEventArgs): Statement;
1178
+ /**
1179
+ * The realtime server to publish onto: a `realtimeServer()` handle, its bare name, or
1180
+ * a `Value` when the name is computed at runtime.
1181
+ *
1182
+ * The engine resolves this server by NAME within the current workspace and branch —
1183
+ * not by guid — so a handle contributes its `name`, not its identity.
1184
+ */
1185
+ type RealtimePublishServer = string | {
1186
+ name: string;
1187
+ } | Value;
1188
+ interface RealtimePublishArgs extends StatementAnnotations {
1189
+ /**
1190
+ * The owning realtime server, by name. Required: a channel path is unique only
1191
+ * within its server, so the path alone cannot be addressed.
1192
+ */
1193
+ server: RealtimePublishServer;
1194
+ /**
1195
+ * The channel PATH to publish onto, already filled in — `c.text("rooms/42")`, not
1196
+ * the `rooms/{room_id}` template. Build it with `realtimeChannel().getChannel({…})`
1197
+ * rather than concatenating by hand.
1198
+ */
1199
+ channel: Value;
1200
+ /** The event payload delivered to subscribers. */
1201
+ data: Value;
1202
+ /**
1203
+ * Optional message TYPE stamped on the frame, so a client that switches on type can
1204
+ * route a server-originated event the same way it routes a `realtimeMessage()` one.
1205
+ * Naming a type does NOT invoke that message's handler — see the note on delivery below.
1206
+ */
1207
+ message?: Value;
1208
+ /**
1209
+ * Optional ASSERTED identity attributed to the event: name an auth **table** (a
1210
+ * `table({ auth: true })` def or its name) and it resolves to that table's guid.
1211
+ *
1212
+ * This is attribution carried on the frame, NOT a credential — nothing validates it
1213
+ * and no auth gate consumes it. Do not use it to grant a publish that a channel's
1214
+ * `publish.who` would otherwise refuse; this statement bypasses that gate entirely.
1215
+ */
1216
+ authTable?: ObjectRef;
1217
+ /** The asserted identity's row id. Attribution only — see {@link RealtimePublishArgs.authTable}. */
1218
+ authId?: Value;
1219
+ }
1220
+ /**
1221
+ * `realtime.publish { … }` — originate a server-authored event onto a realtime channel
1222
+ * from any function stack (`mvp:realtime_publish`).
1223
+ *
1224
+ * This is how a query, task, function, or trigger pushes to connected clients without a
1225
+ * client frame arriving first: "the auction closed", "the job finished", "row 42 changed".
1226
+ *
1227
+ * Three properties decide whether this is the right tool, and all three surprise people:
1228
+ *
1229
+ * - **Delivery-only.** The event is fanned out to subscribers as-is. It does NOT invoke
1230
+ * a `realtimeMessage()` handler, even when `message` names one, so no stack of yours
1231
+ * runs on the delivery side. A channel `deliver` trigger still applies (it belongs to
1232
+ * the channel, not to the message).
1233
+ * - **Server-authoritative.** It bypasses the channel's `publish.who` policy — that gate
1234
+ * governs CLIENTS. Any stack that can run this can publish, so guard it in your own
1235
+ * stack if that matters.
1236
+ * - **Fail-soft.** A missing or disabled server, a server with no minted canonical, or an
1237
+ * unreachable bus is logged engine-side and returns quietly. NOTHING throws into your
1238
+ * stack and there is no return value to check, so a mis-targeted publish is SILENT.
1239
+ * The two references this SDK can check — `server` and `channel` — throw here at author
1240
+ * time instead, because that is the only loud failure available.
1241
+ *
1242
+ * It does not rescue `deliverTo: "explicit"` on a `realtimeMessage()`: this originates an
1243
+ * event INTO a channel and never selects recipients from inside a handler.
1244
+ *
1245
+ * ```ts
1246
+ * const rooms = realtimeChannel({ name: "rooms/{room_id}", server: chat, input: { room_id: input.int() } });
1247
+ * s.realtime.publish({
1248
+ * server: chat,
1249
+ * channel: c.text(rooms.getChannel({ room_id: 42 })),
1250
+ * message: c.text("post"),
1251
+ * data: obj({ body: "the auction closed" }),
1252
+ * });
1253
+ * ```
1254
+ */
1255
+ declare function realtimePublish(a: RealtimePublishArgs): Statement;
1256
+ interface CreateAuthTokenArgs<As extends string = string> extends StatementOptions {
1257
+ /**
1258
+ * The auth table the token authenticates against.
1259
+ *
1260
+ * `null` is the UNBOUND table the engine stores as a blank guid — deleted, or
1261
+ * never bound. It exists so `codegen` can reproduce such a statement instead
1262
+ * of throwing, the same "no target" spelling `db.query`'s `table` carries.
1263
+ */
1264
+ table: ObjectRef | null;
1265
+ /** Token id (the authenticated row id). */
1266
+ id: Value;
1267
+ /** Extra claims embedded in the token. Defaults to `{}` (no extra claims). */
1268
+ extras?: Value;
1269
+ /** Expiry in seconds. Defaults to `86400` (24h); `0` never expires. */
1270
+ expiration?: Value;
1271
+ as?: As;
1272
+ }
1273
+ /**
1274
+ * `security.create_auth_token { … }` — mint an auth token (`mvp:create_auth`).
1275
+ *
1276
+ * Branded `AsShapeBrand<As, string>` (like the `db.*` producers) so a
1277
+ * `ref("<as>")` to the minted token traces to `string` via `InferResponse`
1278
+ * instead of `unknown` — the token is always a JWT string. The brand is phantom;
1279
+ * the emitted statement bytes are unchanged.
1280
+ */
1281
+ declare function createAuthToken<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(a: CreateAuthTokenArgs<As> & {
1282
+ asFilters?: Fs;
1283
+ }): Statement & AsShapeBrand<As, ApplyFilters<string, Fs>>;
1284
+ /**
1285
+ * `security.create_guid` — generate a GUID (`mvp:guid`).
1286
+ *
1287
+ * The engine's statement declares no context, input, or output schema at all
1288
+ * (`Generate GUID`): it takes nothing and binds the generated value, so `as` is
1289
+ * the only thing to author. Sibling of `security.create_uuid` (`mvp:uuid4`),
1290
+ * which is a different generator and a different stored statement — the SDK
1291
+ * models both rather than folding one into the other.
1292
+ *
1293
+ * Branded `AsShapeBrand<As, string>` so a `ref("<as>")` traces to `string`.
1294
+ */
1295
+ declare function createGuid<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(a?: {
1296
+ as?: As;
1297
+ } & StatementOptions & {
1298
+ asFilters?: Fs;
1299
+ }): Statement & AsShapeBrand<As, ApplyFilters<string, Fs>>;
1300
+ interface ExpectToThrowArgs extends StatementAnnotations {
1301
+ /** The statements expected to raise. */
1302
+ body: Statement[];
1303
+ /**
1304
+ * Text the raised error's message must CONTAIN (case-insensitive substring).
1305
+ * Omit to accept any error.
1306
+ */
1307
+ exception?: Value;
1308
+ }
1309
+ /**
1310
+ * `expect.to_throw { … }` — assert a sub-stack throws (`mvp:test_expect_to_throw`).
1311
+ *
1312
+ * The matcher is stored as `context.value1` — the numbered slot every
1313
+ * `expect.*` statement keeps its operands in. It was emitted as
1314
+ * `context.exception` through 2.0.21, a key the engine never reads, so a
1315
+ * to_throw carrying one accepted ANY error instead of the one named (issue #228).
1316
+ */
1317
+ declare function expectToThrow(a: ExpectToThrowArgs): Statement;
1318
+ interface ExpectToMatchArgs extends StatementAnnotations {
1319
+ /** The value under test — the SUBJECT the pattern is matched against. */
1320
+ expr?: Value;
1321
+ /** The regex PATTERN. Build it with `c.regex(...)`, not `c.text(...)`. */
1322
+ value?: Value;
1323
+ }
1324
+ /**
1325
+ * `expect.to_match` — assert a value matches a regex (`mvp:test_expect_to_match`).
1326
+ *
1327
+ * A typed, guarded pass-through to the generated factory: same bytes, same
1328
+ * fields. What it adds is the refusal that issue #211 asked for. The `value`
1329
+ * slot is a PHP `preg_*` PATTERN, so a `c.text("^XanoTS.*Engine$")` there is not
1330
+ * a stricter assertion — it is a pattern the engine cannot run, and the test
1331
+ * fails against the very string it was written for:
1332
+ *
1333
+ * ```
1334
+ * to_match failed - regex /"^XanoTS.*Engine$"/ not matched in "XanoTS Automated Testing Engine"
1335
+ * ```
1336
+ *
1337
+ * The refusal is build-time and inspects the value it was handed, exactly as the
1338
+ * `fl.regex_*` guard does (#128): a bare `const` is refused and pointed at
1339
+ * `c.regex`, while a `ref`/`inp`/`env` pattern — whose text is not visible here —
1340
+ * is passed through untouched.
1341
+ */
1342
+ declare function expectToMatch(a?: ExpectToMatchArgs): Statement;
1343
+
1344
+ /**
1345
+ * Hand-authored typed wrapper for `util.ip_lookup` (#226) — the geolocation
1346
+ * statement whose bound variable is a NESTED object that nothing in the
1347
+ * signature hints at.
1348
+ *
1349
+ * The generated factory types `value` and nothing else, so an author guessing a
1350
+ * flat `{ city, region, latitude, longitude }` gets `null` for every field, and
1351
+ * those nulls fail two steps later with errors that name a column rather than
1352
+ * the lookup. This wrapper delegates encoding to the generated factory (bytes
1353
+ * unchanged) and adds the shape brand, so `ref("geo.location.latitude")` traces
1354
+ * to `number | null` while `ref("geo.latitude")` bottoms out at `unknown`.
1355
+ */
1356
+
1357
+ /**
1358
+ * What `util.ip_lookup` binds to its `as` variable: a nested geolocation record,
1359
+ * **not** flat fields. Every leaf is nullable, and `region.*`/`city.name`/
1360
+ * `postal.code` are commonly null even for a well-known routable public address
1361
+ * — a populated `country`/`location` with an empty city is the normal result,
1362
+ * not a failed lookup.
1363
+ *
1364
+ * Read coordinates at `location.latitude`/`location.longitude` and place names
1365
+ * at `city.name`/`region.name`/`country.name`. Note that `city` itself is an
1366
+ * OBJECT: a `ref("geo.city")` written into a text column fails on the object,
1367
+ * and `{ safe: true }` does not help because the object is not null — drill to
1368
+ * `city.name` and supply a fallback.
1369
+ *
1370
+ * The whole variable is `null` when the address cannot be resolved at all
1371
+ * (a private/reserved range, an unroutable or malformed address), so guard the
1372
+ * top level before drilling.
1373
+ */
1374
+ interface IpLookupResult {
1375
+ /** Continent code (`"NA"`) and name (`"North America"`). */
1376
+ continent: {
1377
+ code: string | null;
1378
+ name: string | null;
1379
+ };
1380
+ /** ISO-3166 alpha-2 country code (`"US"`) and name (`"United States"`). */
1381
+ country: {
1382
+ code: string | null;
1383
+ name: string | null;
1384
+ };
1385
+ /** Most specific subdivision — state/province. Commonly null. */
1386
+ region: {
1387
+ code: string | null;
1388
+ name: string | null;
1389
+ };
1390
+ /** City name only; there is no city code. Commonly null. */
1391
+ city: {
1392
+ name: string | null;
1393
+ };
1394
+ /** Postal/ZIP code. Commonly null. */
1395
+ postal: {
1396
+ code: string | null;
1397
+ };
1398
+ /** Coordinates, IANA timezone (`"America/Chicago"`), and accuracy radius in KILOMETRES. */
1399
+ location: {
1400
+ latitude: number | null;
1401
+ longitude: number | null;
1402
+ tz: string | null;
1403
+ radius: number | null;
1404
+ };
1405
+ }
1406
+ interface IpLookupArgs<As extends string = string> extends StatementOptions {
1407
+ /** The IP address to geolocate. */
1408
+ value: Value;
1409
+ /** Bind the nested {@link IpLookupResult} (or `null`) to this stack variable. */
1410
+ as?: As;
1411
+ }
1412
+ /**
1413
+ * `s.util.ip_lookup({ value, as })` — geolocate an IP address
1414
+ * (`mvp:ipaddress_lookup`).
1415
+ *
1416
+ * Branded `AsShapeBrand<As, IpLookupResult | null>` so `InferResponse` resolves
1417
+ * a dotted `ref` into the real, nested shape instead of `unknown`. The brand is
1418
+ * phantom — the emitted statement is byte-identical to the generated factory's.
1419
+ */
1420
+ declare function ipLookup<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(a: IpLookupArgs<As> & {
1421
+ asFilters?: Fs;
1422
+ }): Statement & AsShapeBrand<As, ApplyFilters<IpLookupResult | null, Fs>>;
1423
+
1424
+ /**
1425
+ * Addon-authoring encoder — the one place that turns an authored {@link AddonSpec}
1426
+ * into the stored `addon[]` block a db statement carries (the shape the engine's
1427
+ * addon import/export walk reads).
1428
+ *
1429
+ * Xano addons graft related-table data onto the rows a `db.query`/`db.get` (and
1430
+ * the other row-returning db ops) return. Each attached addon references a
1431
+ * reusable addon object, maps some of its inputs, optionally restricts its
1432
+ * output columns, and lands its result on the row under a dotted destination
1433
+ * (`offset` + `as`). Addons nest recursively.
1434
+ *
1435
+ * The authoring surface mirrors XanoScript's `addon = [{ name, as, input, output,
1436
+ * addon }]`, with two deliberate divergences:
1437
+ *
1438
+ * - the reference field is named `addon` (an {@link ObjectRef}), so the nesting
1439
+ * field is named `children` to avoid the collision — which also matches the
1440
+ * stored/export key (KTD-3);
1441
+ * - the target is a guid-native `ObjectRef`, resolved to a guid and emitted under
1442
+ * the stored `id` key. In a packageExport bundle the engine matches addons by
1443
+ * guid (`importAddonId` → `guidMatch`), so emitting the guid as `id` is correct
1444
+ * — the same precedent `s.addon.call` uses (KTD-1).
1445
+ */
1446
+
1447
+ /**
1448
+ * One addon attached to a db statement.
1449
+ *
1450
+ * `as` is the dotted destination on the row (e.g. `"items._book"`); it splits at
1451
+ * the last dot into the stored `offset` (path prefix) + `as` (final segment).
1452
+ * `input` maps addon input names to values — bind parent-row columns with
1453
+ * {@link out} (`{ user_id: out("id") }`). `output` restricts the addon's returned
1454
+ * columns. `children` nests further addons (recursive).
1455
+ */
1456
+ interface AddonSpec<Graft = unknown> {
1457
+ /**
1458
+ * The target addon. A typed {@link AddonDef} handle (from {@link addon}) carries
1459
+ * its graft shape into the parent row's response type; a bare name/`ObjectRef`
1460
+ * resolves to a guid but grafts `unknown`.
1461
+ *
1462
+ * `null` is the UNBOUND attachment the engine stores as `id: ""` — an addon
1463
+ * that was deleted or never bound. It exists so `codegen` can reproduce such a
1464
+ * query faithfully instead of throwing and degrading the whole statement to
1465
+ * `raw()`; it grafts `unknown`, which is what an unbound target knows.
1466
+ */
1467
+ addon: ObjectRef | AddonDef<Graft> | null;
1468
+ /**
1469
+ * Dotted destination **relative to a returned row**, e.g. `"_book"` (a bare
1470
+ * alias) or `"obj._book"` (offset + alias). Splits at the last dot into the
1471
+ * stored `offset` (path prefix) + `as` (final segment). Do **not** hand-write
1472
+ * the `items[]` paging-envelope prefix — a `db.query` that returns a metadata
1473
+ * paging envelope adds it automatically (writing it explicitly is tolerated and
1474
+ * not double-prefixed).
1475
+ */
1476
+ as: string;
1477
+ /** Addon input bindings, name → value (use {@link out} for parent-row columns). */
1478
+ input?: Record<string, Value>;
1479
+ /** Restrict the addon's returned columns. Narrows the graft at runtime and in
1480
+ * the grafted type (to `output ∩ the addon's columns`). A dotted entry
1481
+ * (`"img.url"`) selects sub-keys of an object column; the graft narrows by the
1482
+ * root segment, since an object column's sub-keys are not declared. */
1483
+ output?: readonly string[];
1484
+ /** Nested addons (recursive). */
1485
+ children?: AddonSpec[];
1486
+ }
1487
+
1488
+ /**
1489
+ * Hand-authored database statements (U10) — the `!map:dbo` family: read/delete/
1490
+ * exists/patch/truncate/schema against a table. Codegen defers these because the
1491
+ * target table is a `!map:dbo context.dbo.id` reference; with the guid
1492
+ * foundation (refs/guid.ts) the table resolves to its deterministic guid.
1493
+ *
1494
+ * All six share one rich envelope (engine-class metadata, not in the transform
1495
+ * schema — confirmed against the Xano engine's persisted shape): `description:""`,
1496
+ * `settings_registry:[]`, an `output` block (`{customize:false,filters:[],items:[]}`
1497
+ * by default; a statement with column selection — `db.get`'s `output` arg — emits
1498
+ * `{customize:true, items:[{name,children:[]}]}` per the engine's persisted golden),
1499
+ * `addon:[]`, an always-present `as` (""-default), and `context:{dbo:{id:guid}}`.
1500
+ * Input entries are the rich form `{name,value,tag,filters,ignore,expand,children}`.
1501
+ *
1502
+ * The row-data writes (`db.add`/`db.edit`/`db.add_or_edit`) carry the row as
1503
+ * explicit input entries — one per field, each with an optional `ignore` flag
1504
+ * (system/readonly columns like `id` are stored with `ignore:true`). Authors can
1505
+ * either list the entries exactly (`data: DbField[]`) or pass a *partial* row
1506
+ * (`row: { … }`) and let {@link expandRow} fill it against the table's declared
1507
+ * columns with type defaults + a documented `ignore` heuristic. The latter is a
1508
+ * DX convenience, not a byte-clone of the engine's editor template (see
1509
+ * {@link expandRow} for why that template isn't reproducible — it's a frontend
1510
+ * artifact, and the engine's import path accepts whatever entries it's given).
1511
+ *
1512
+ * Scope: `db.add_or_edit` (extra `context.dbo.as` + inconsistent entries),
1513
+ * `db.bulk*` (array-of-rows), `db.query` (structural !function), and
1514
+ * `db.direct_query`/external SQL/`db.transaction` are deferred.
1515
+ */
1516
+
1517
+ /**
1518
+ * The column-name type for a db op's `table` argument: a typed `table()` handle
1519
+ * narrows to its declared columns (+ system columns); a bare name or an untyped
1520
+ * ref falls back to any `string`. Drives schema-aware typing of `fieldName`,
1521
+ * `output`, `sortBy`, and `row` keys.
1522
+ */
1523
+ type ColsOf<T> = T extends TableDef<infer C> ? C : string;
1524
+ /**
1525
+ * The aliases a query's own `eval` declares — computed columns that exist on the
1526
+ * result but on no table.
1527
+ *
1528
+ * `eval: [{name: "…$searchindex", as: "rank", filters: [{name: "search_rank"}]}]`
1529
+ * makes `rank` selectable and sortable in the SAME call, and the engine's docs
1530
+ * (and this SDK's) say so: each `as` grafts onto the row. Typed only against the
1531
+ * table's columns, `sortBy: "rank"` did not compile — six selections in one real
1532
+ * workspace, all of them valid.
1533
+ */
1534
+ type EvalAliases<E> = E extends readonly (infer Item)[] ? Item extends {
1535
+ as: infer A extends string;
1536
+ } ? A : never : never;
1537
+ /**
1538
+ * The single-row shape a db read yields, for `InferResponse`'s trace (U5): the
1539
+ * table's {@link InferRow}, narrowed to the selected `Cols` when an `output`
1540
+ * list is given, else the full row. A bare-name / raw-`ColumnDef[]` table has no
1541
+ * field brands, so `InferRow` is `never` → `unknown` (nothing to infer).
1542
+ */
1543
+ type RowShapeOf<T extends ObjectRef, Cols extends readonly string[]> = [
1544
+ InferRow<T>
1545
+ ] extends [never] ? unknown : Cols["length"] extends 0 ? InferRow<T> : Pick<InferRow<T>, Extract<OutputRoot<Cols[number]>, keyof InferRow<T>>>;
1546
+ /**
1547
+ * The full-row shape a write binds when it carries no column selection —
1548
+ * `db.add_or_edit` (upserted row, which has no `output` envelope at all in its
1549
+ * leaner serialization) and the bulk ops. The whole {@link InferRow}, or
1550
+ * `unknown` for an unbranded bare-name table. Expressed via {@link RowShapeOf}
1551
+ * with an empty `Cols` so the `never`→`unknown` guard is shared with the reads.
1552
+ * (`db.del` is deliberately *not* here — it binds `null`; see {@link dbDel}.)
1553
+ */
1554
+ type FullRowShapeOf<T extends ObjectRef> = RowShapeOf<T, readonly []>;
1555
+ /**
1556
+ * The alias segment of a dotted addon `as` — the part after the last dot
1557
+ * (`"items._book"` → `"_book"`, `"_book"` → `"_book"`). This is the key the addon
1558
+ * grafts onto the row.
1559
+ */
1560
+ type AddonAlias<S extends string> = S extends `${string}.${infer Rest}` ? AddonAlias<Rest> : S;
1561
+ /** True only for `unknown` (not `any`, not a concrete type) — guards the graft narrowing below. */
1562
+ type IsUnknown<T> = 0 extends 1 & T ? false : unknown extends T ? true : false;
1563
+ /**
1564
+ * Narrow a graft `G` to the attachment's `output` column whitelist `O`. The
1565
+ * runtime intersects the def's selected columns with the attachment whitelist
1566
+ * (`whitelistOutput`), so the type picks `O ∩ keyof G`. Applied to the element
1567
+ * of a list graft (`Shape[]`) or a single graft (`Shape`). An `unknown` graft
1568
+ * (bare-name reference, or a def with no typed `output`) stays `unknown` — never
1569
+ * collapse it to `{}`.
1570
+ */
1571
+ type NarrowGraft<G, O extends readonly string[]> = IsUnknown<G> extends true ? unknown : G extends readonly (infer E)[] ? Prettify<Pick<E, Extract<OutputRoot<O[number]>, keyof E>>>[] : G extends object ? Prettify<Pick<G, Extract<OutputRoot<O[number]>, keyof G>>> : G;
1572
+ /**
1573
+ * The graft shape one attached addon lands on the row. A typed
1574
+ * {@link AddonDef} handle carries its shape (`Pick<row, output>`, an object or
1575
+ * array per its cardinality); a bare name/`ObjectRef` reference carries none, so
1576
+ * it grafts `unknown` — the honest floor (narrow it at the call site). An
1577
+ * attachment-level `output` further restricts the graft to those columns
1578
+ * ({@link NarrowGraft}).
1579
+ */
1580
+ type GraftOf<H> = H extends {
1581
+ addon: AddonDef<infer G>;
1582
+ } ? H extends {
1583
+ output: infer O extends readonly string[];
1584
+ } ? NarrowGraft<G, O> : G : unknown;
1585
+ /**
1586
+ * The keys a set of attached addons graft onto each returned row. Each addon's
1587
+ * alias (the last segment of its `as`) becomes a key valued by {@link GraftOf}.
1588
+ *
1589
+ * Mirrors the engine's `applyAddOnSchema` placement — the alias always lands on
1590
+ * the *row element*. With paging the engine wraps rows under `items` (returnAs),
1591
+ * so `as:"items._book"` puts `_book` inside each `items[]` element = each row;
1592
+ * without paging `as:"_book"` puts it on each bare row. Both reduce to "the row
1593
+ * gains the alias key". Nested `children` addons enrich the addon's own result
1594
+ * (under the alias), so they add no parent-visible keys.
1595
+ */
1596
+ type AddonFields<A> = A extends readonly [infer H, ...infer Rest] ? (H extends {
1597
+ as: infer S extends string;
1598
+ } ? {
1599
+ [K in AddonAlias<S>]: GraftOf<H>;
1600
+ } : object) & AddonFields<Rest> : object;
1601
+ /**
1602
+ * A row shape augmented with any addon-grafted alias keys. With no addons
1603
+ * (`A = readonly []`) it is the row unchanged, so the non-addon path — and every
1604
+ * existing caller — keeps its exact shape.
1605
+ *
1606
+ * The graft **overrides** any base column of the same name rather than
1607
+ * intersecting with it (`Omit<Row, alias> & AddonFields`): the engine overwrites
1608
+ * the field with the addon result at runtime, so when an alias shadows an
1609
+ * existing column the honest type is the graft (`unknown`), not the base column.
1610
+ * An intersection would collapse `unknown & string` back to the base column and
1611
+ * silently desync the type from runtime (issue #61).
1612
+ */
1613
+ type WithAddons<Row, A> = [keyof AddonFields<A>] extends [never] ? Row : Prettify<Omit<Row, keyof AddonFields<A>> & AddonFields<A>>;
1614
+ /**
1615
+ * A row shape augmented with any `eval` alias keys. With no evals it is the row
1616
+ * unchanged. Like {@link WithAddons}, an eval alias **overrides** a base column of
1617
+ * the same name (the engine computes over it), so the honest type is the graft.
1618
+ */
1619
+ type WithEval<Row, E> = [keyof EvalFields<E>] extends [never] ? Row : Prettify<Omit<Row, keyof EvalFields<E>> & EvalFields<E>>;
1620
+ /**
1621
+ * The paging metadata envelope a `db.query` returns when `paging` is set with
1622
+ * metadata on — the engine's `packageListMeta` shape (issue #58). The result
1623
+ * list lives under `items`; `totals:true` adds `itemsTotal`/`pageTotal`. A query
1624
+ * with no `paging`, or `paging:{ metadata:false }`, returns the bare list instead.
1625
+ *
1626
+ * **Has-next signal (issue #66 bonus):** read `nextPage` — it is `number` when
1627
+ * another page exists and `null` on the last page (the engine fetches one extra
1628
+ * row to decide, so this needs no second scan). For a total count, set
1629
+ * `paging:{ totals:true }` and read `itemsTotal`/`pageTotal`. Both are typed on
1630
+ * this envelope by `InferResponse`, so a client can drive "load more" straight
1631
+ * off the typed response without hand-declaring the shape.
1632
+ */
1633
+ type PagingEnvelope<Items, Totals extends boolean> = Prettify<{
1634
+ items: Items;
1635
+ itemsReceived: number;
1636
+ curPage: number;
1637
+ nextPage: number | null;
1638
+ prevPage: number | null;
1639
+ offset: number;
1640
+ perPage: number;
1641
+ } & (Totals extends true ? {
1642
+ itemsTotal: number;
1643
+ pageTotal: number;
1644
+ } : object)>;
1645
+ /**
1646
+ * Whether a `paging` arg carries a page/per_page/offset field (static or a
1647
+ * `Value`) — the runtime gate that activates pagination. A `search`/`sort`-only
1648
+ * `paging` has no such field, so it does not produce the envelope.
1649
+ */
1650
+ type HasPageFieldT<P> = P extends {
1651
+ page: unknown;
1652
+ } ? true : P extends {
1653
+ per_page: unknown;
1654
+ } ? true : P extends {
1655
+ offset: unknown;
1656
+ } ? true : false;
1657
+ /**
1658
+ * Whether a `paging` arg produces the metadata envelope: it activates pagination
1659
+ * (a page/per_page/offset field is present) and is not explicitly `metadata:false`
1660
+ * (the engine default is `metadata:true`).
1661
+ */
1662
+ type HasPagingEnvelope<P> = P extends undefined ? false : P extends {
1663
+ metadata: false;
1664
+ } ? false : HasPageFieldT<P> extends true ? true : false;
1665
+ /** The `totals` flag of a `paging` arg — literal `true` only when set explicitly. */
1666
+ type PagingTotals<P> = P extends {
1667
+ totals: true;
1668
+ } ? true : false;
1669
+ /**
1670
+ * The engine's `context.return.type` for a `db.query` — the return-type
1671
+ * discriminant. `"list"` is the default (a row array or paging envelope);
1672
+ * `"single"` a first-match object; `"count"`/`"exists"` a scalar; `"stream"` a
1673
+ * (pageable) row array with no metadata envelope.
1674
+ */
1675
+ type DbReturnType = "list" | "single" | "count" | "exists" | "stream" | "aggregate";
1676
+ /** Distinct-row handling (`context.return.<list|stream>.distinct`): engine default `"auto"`. */
1677
+ type DbDistinct = "auto" | "yes" | "no";
1678
+ /** Aggregate paging (`context.return.aggregate.paging`) — no `offset`/`totals` (engine schema). */
1679
+ interface DbAggregatePaging {
1680
+ page?: number;
1681
+ per_page?: number;
1682
+ /** Wrap the result in the metadata envelope (engine default `true`). */
1683
+ metadata?: boolean;
1684
+ /**
1685
+ * The engine's gate. Every field here is read ONLY when this is on, so
1686
+ * `enabled:false` parks a configured block without applying it — the state the
1687
+ * editor leaves behind when pagination is switched back off. Defaults to `true`
1688
+ * (passing `paging` at all is the usual way to ask for it); set `false` only to
1689
+ * reproduce that parked state.
1690
+ */
1691
+ enabled?: boolean;
1692
+ }
1693
+ /**
1694
+ * Aggregate/group-by config for `returnType:"aggregate"` (`context.return.aggregate`).
1695
+ * `group` are the group-by columns and `eval` the aggregator columns (each
1696
+ * `{ name, as, filters }` — an aggregator like `sum`/`count` rides `filters`).
1697
+ * Both `as` sets graft onto the aggregate row (`unknown` values). Write `name` as
1698
+ * a bare column (`"status"`) — it is alias-qualified to `"<table>.status"` on emit
1699
+ * (the engine requires the qualified form) and the statement declares that alias
1700
+ * so the qualified name resolves; pass an already-dotted `name` for a
1701
+ * `bind`ed/joined column and it is left as-is (and declares nothing, which is
1702
+ * what keeps a pulled workspace byte-exact — see issue #213).
1703
+ */
1704
+ interface DbAggregate {
1705
+ group?: DbEval[];
1706
+ eval?: DbEval[];
1707
+ sort?: SortDirective[];
1708
+ paging?: DbAggregatePaging;
1709
+ }
1710
+ /** A join type for a {@link DbBind} — the engine's `bind[].join`. */
1711
+ type DbJoin = "inner" | "left" | "right";
1712
+ /**
1713
+ * A db statement's target table — a def handle or name, or `null` for the
1714
+ * engine's own empty binding (`context.dbo.id: ""`).
1715
+ *
1716
+ * ⚠ **Do not author `null`.** It is a BROKEN state in Xano, not a neutral one:
1717
+ * the statement is bound to no table and does nothing wherever it runs. It exists
1718
+ * on these types so `codegen` can represent a broken statement faithfully rather
1719
+ * than degrade the whole thing to `raw()` — a pulled `table: null` is a defect to
1720
+ * fix in the pulled workspace, not a shape to copy.
1721
+ *
1722
+ * It is what a statement degrades to when the table it referenced is deleted, and
1723
+ * also where a freshly-dropped one starts. The engine clears the id rather than
1724
+ * recording a tombstone, so those two are the same bytes: `null` means "unbound",
1725
+ * never "was deleted". The same contract as an addon's `table` (see
1726
+ * {@link addon}), which is where this pattern comes from.
1727
+ *
1728
+ * An unbound table has no schema, so `row:` (which expands the typed row against
1729
+ * the table's columns) is unavailable with it — use `data:`.
1730
+ */
1731
+ type DbTableRef<T extends ObjectRef = ObjectRef> = T | null;
1732
+ /**
1733
+ * A join (`context.bind[]`): join `table` (aliased by `as`) with `join` kind and
1734
+ * an optional `where` join condition (same search surface as the query). Joins
1735
+ * widen what `where`/`sort`/`eval` can address by dotted path (`"author.id"`);
1736
+ * they do not by themselves change the returned row shape.
1737
+ *
1738
+ * ⚠ **The two sides of a join condition are spelled differently** (issue #213).
1739
+ * The JOINED column takes the dotted alias path; the query's OWN column stays
1740
+ * BARE:
1741
+ *
1742
+ * ```ts
1743
+ * s.db.query({
1744
+ * table: doc, // columns of `doc` are bare
1745
+ * bind: [{ table: team, as: "team_row", join: "left",
1746
+ * where: expr(col("team"), "=", col("team_row.id")) }],
1747
+ * })
1748
+ * ```
1749
+ *
1750
+ * Qualifying your own column with the table's name (`col("doc.team")`) resolves
1751
+ * only when the query also sets {@link DbQueryArgs.tableAlias} — the engine
1752
+ * matches the qualifier against the alias the statement declares, and a query
1753
+ * without `tableAlias` declares none. Unqualified, the engine treats the operand
1754
+ * as a text literal and the request fails with `ParseError: Invalid value for
1755
+ * param:"…"` naming the OTHER operand. Both spellings are checked at export.
1756
+ */
1757
+ interface DbBind {
1758
+ /**
1759
+ * The table to join, or `null` when unbound — see {@link DbTableRef} for the
1760
+ * contract, which is the same one the query's own `table` holds. ⚠ Do not
1761
+ * author `null`; it exists so a join whose table was deleted round-trips
1762
+ * instead of taking the whole statement to `raw()`.
1763
+ */
1764
+ table: DbTableRef;
1765
+ /** SQL alias for the joined table — defaults to the table name. Two binds to the same table need distinct aliases. */
1766
+ as?: string;
1767
+ /** Join kind (default `"inner"`). */
1768
+ join?: DbJoin;
1769
+ /** Join condition — same `where`/`cmp`/`and`/`or` surface as the query. */
1770
+ where?: DbWhere;
1771
+ }
1772
+ /**
1773
+ * The full `db.query` result shape, discriminated by return type `RT`:
1774
+ * `count → number`, `exists → boolean`, `single → row | null`, `stream → row[]`,
1775
+ * and `list → row[]` or the {@link PagingEnvelope} when `paging` requests
1776
+ * metadata. The row is always the addon-augmented row.
1777
+ */
1778
+ type QueryResult<Row, A, P, RT extends DbReturnType, E = readonly [], AG = unknown> = RT extends "count" ? number : RT extends "exists" ? boolean : RT extends "aggregate" ? AggregateRow<AG>[] : WithAddons<WithEval<Row, E>, A> extends infer R ? RT extends "single" ? R | null : RT extends "stream" ? R[] : HasPagingEnvelope<P> extends true ? PagingEnvelope<R[], PagingTotals<P>> : R[] : never;
1779
+ /**
1780
+ * A db read statement branded — **at the type level only** — via the shared
1781
+ * {@link AsShapeBrand} contract (the stack variable it binds + the shape it
1782
+ * produces). The runtime statement is a plain {@link Statement}, so
1783
+ * `encodeStatement` is unchanged.
1784
+ */
1785
+ type DbResult<As extends string, Shape> = Statement & AsShapeBrand<As, Shape>;
1786
+ interface DbGetArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[]> extends StatementOptions {
1787
+ /**
1788
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
1789
+ * Absent unless set — Xano writes it on some statements and not others, so it
1790
+ * is authored rather than derived (see {@link dboBinding}).
1791
+ */
1792
+ tableAlias?: string;
1793
+ /** The target table (def handle or name). */
1794
+ table: DbTableRef<T>;
1795
+ /**
1796
+ * The lookup field (defaults to the primary key `id`). A dotted path reaches a
1797
+ * sub-key of an object column (`"google_oauth.id"`) or a joined table's column
1798
+ * — see {@link QualifiedCol}.
1799
+ */
1800
+ fieldName?: QualifiedCol<ColsOf<T>>;
1801
+ /** The value to match. */
1802
+ fieldValue: Value;
1803
+ /** Acquire a row lock for the transaction. */
1804
+ lock?: boolean;
1805
+ /**
1806
+ * Restrict the returned columns (XanoScript `output = [...]`). Encoded into
1807
+ * the customized output envelope — `{customize:true, items:[{name,children:[]}]}`
1808
+ * (byte shape per the engine's persisted golden). Omitting it
1809
+ * returns the full record (`customize:false`). Note: an explicit `output`
1810
+ * list overrides column visibility — listing an `internal` column (e.g. a
1811
+ * password hash) pulls it into the statement result. Captured literally so
1812
+ * `InferResponse` narrows a traced row to exactly these columns.
1813
+ */
1814
+ output?: Cols;
1815
+ /** Attach addons to enrich the returned row (see {@link AddonSpec}). Each
1816
+ * addon's alias (the last segment of its `as`) is merged onto the row shape in
1817
+ * `InferResponse` — typed from the addon's graft shape when it's a typed
1818
+ * `addon({ table, output })` handle, or `unknown` for a bare-name reference. */
1819
+ addon?: A;
1820
+ /** Capture the row into this stack variable. Captured literally so
1821
+ * `InferResponse` can trace a `ref` back to this statement. */
1822
+ as?: As;
1823
+ }
1824
+ /** `db.get <table>` — fetch a single record by a field match (`mvp:dbo_getby`).
1825
+ * Returns a {@link DbResult} branded with `as` + the (optionally narrowed) row
1826
+ * shape **`| null`** so `InferResponse` can type a response that returns this
1827
+ * variable. `dbo_getby` binds **`null` on a miss** (no row matched) rather than
1828
+ * throwing — confirmed live — so the honest shape is `Row | null`, matching
1829
+ * `db.query`'s `returnType:"single"` ({@link QueryResult}). Contrast the row
1830
+ * **writes** (`db.add`/`edit`/`patch`/`add_or_edit`), which bind the full
1831
+ * written row rather than null and so stay non-nullable — a genuine miss throws
1832
+ * instead of yielding null (`NotFound`/404 for `edit`/`patch`; a
1833
+ * unique-constraint error for `add`; `add_or_edit` upserts, so it never misses)
1834
+ * (issue #105). */
1835
+ declare function dbGet<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const Fs extends readonly FilterXdo[] = readonly []>(args: DbGetArgs<T, As, Cols, A> & {
1836
+ asFilters?: Fs;
1837
+ }): DbResult<As, ApplyFilters<WithAddons<RowShapeOf<T, Cols>, A> | null, Fs>>;
1838
+ interface DbGetByIdArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[]> extends StatementOptions {
1839
+ /**
1840
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
1841
+ * Absent unless set — Xano writes it on some statements and not others, so it
1842
+ * is authored rather than derived (see {@link dboBinding}).
1843
+ */
1844
+ tableAlias?: string;
1845
+ /** The target table (def handle or name). */
1846
+ table: DbTableRef<T>;
1847
+ /** The primary key to fetch. The engine types this `int|min(1)`. */
1848
+ id: Value;
1849
+ /** Restrict the returned columns — same envelope as {@link DbGetArgs.output}. */
1850
+ output?: Cols;
1851
+ /** Attach addons to enrich the returned row (see {@link AddonSpec}). */
1852
+ addon?: A;
1853
+ /** Capture the row into this stack variable. */
1854
+ as?: As;
1855
+ }
1856
+ /**
1857
+ * `db.get_by_id <table>` — fetch a single record by primary key (`mvp:dbo_get`).
1858
+ *
1859
+ * The narrow sibling of {@link dbGet}: where `db.get` matches any field
1860
+ * (`mvp:dbo_getby`, defaulting to `id`), this one is the engine's dedicated
1861
+ * get-by-primary-key statement and takes a single `id` input. Both are live in
1862
+ * real workspaces — which one the editor wrote is a matter of vintage and which
1863
+ * panel was used — so the SDK models both rather than rewriting one into the
1864
+ * other, which would change the stored bytes.
1865
+ *
1866
+ * Binds `Row | null` for the same reason `db.get` does: a miss yields null
1867
+ * rather than throwing.
1868
+ */
1869
+ declare function dbGetById<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const Fs extends readonly FilterXdo[] = readonly []>(args: DbGetByIdArgs<T, As, Cols, A> & {
1870
+ asFilters?: Fs;
1871
+ }): DbResult<As, ApplyFilters<WithAddons<RowShapeOf<T, Cols>, A> | null, Fs>>;
1872
+ interface DbDelArgs<T extends ObjectRef = ObjectRef> extends StatementOptions {
1873
+ /**
1874
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
1875
+ * Absent unless set — Xano writes it on some statements and not others, so it
1876
+ * is authored rather than derived (see {@link dboBinding}).
1877
+ */
1878
+ tableAlias?: string;
1879
+ table: DbTableRef<T>;
1880
+ /** The lookup field. A dotted path reaches an object column's sub-key or a joined table's column ({@link QualifiedCol}). */
1881
+ fieldName?: QualifiedCol<ColsOf<T>>;
1882
+ fieldValue: Value;
1883
+ as?: string;
1884
+ }
1885
+ /**
1886
+ * `db.del <table>` — delete a single record by a field match (`mvp:dbo_delby`);
1887
+ * throws `NotFound`/404 when nothing matches.
1888
+ *
1889
+ * Left **unbranded** (plain {@link Statement}), unlike the other single-record
1890
+ * writes: the engine declares no output schema for this statement and returns
1891
+ * nothing once the row is gone, so the bound `as` variable holds **`null`**, not
1892
+ * the deleted row. `InferResponse` therefore resolves a returned del var to
1893
+ * `unknown` — matching where the engine's own OpenAPI walk falls back to `json`.
1894
+ * (Contrast `db.add`/`edit`/`patch`/`add_or_edit`, which each return the written
1895
+ * row and so bind the full record.)
1896
+ */
1897
+ declare function dbDel<T extends ObjectRef>(args: DbDelArgs<T>): Statement;
1898
+ interface DbHasArgs<T extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
1899
+ /**
1900
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
1901
+ * Absent unless set — Xano writes it on some statements and not others, so it
1902
+ * is authored rather than derived (see {@link dboBinding}).
1903
+ */
1904
+ tableAlias?: string;
1905
+ table: DbTableRef<T>;
1906
+ /** The lookup field. A dotted path reaches an object column's sub-key or a joined table's column ({@link QualifiedCol}). */
1907
+ fieldName?: QualifiedCol<ColsOf<T>>;
1908
+ fieldValue: Value;
1909
+ /** Capture the existence boolean into this stack variable. Captured literally so
1910
+ * `InferResponse` can trace a `ref` back to this statement. */
1911
+ as?: As;
1912
+ }
1913
+ /** `db.has <table>` — test whether a record exists by a field match (`mvp:dbo_hasby`).
1914
+ * Binds a **boolean** (the engine's `__self: bool` output), so it's branded with
1915
+ * `as` + `boolean` for `InferResponse` — table-independent, unlike the row ops. */
1916
+ declare function dbHas<T extends ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: DbHasArgs<T, As> & {
1917
+ asFilters?: Fs;
1918
+ }): DbResult<As, ApplyFilters<boolean, Fs>>;
1919
+ interface DbPatchArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[]> extends StatementOptions {
1920
+ /**
1921
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
1922
+ * Absent unless set — Xano writes it on some statements and not others, so it
1923
+ * is authored rather than derived (see {@link dboBinding}).
1924
+ */
1925
+ tableAlias?: string;
1926
+ table: DbTableRef<T>;
1927
+ /** The lookup field. A dotted path reaches an object column's sub-key or a joined table's column ({@link QualifiedCol}). */
1928
+ fieldName?: QualifiedCol<ColsOf<T>>;
1929
+ fieldValue: Value;
1930
+ /** The partial row to merge (an object value). */
1931
+ data: Value;
1932
+ /**
1933
+ * Restrict the columns of the RETURNED row (XanoScript `output = [...]`) —
1934
+ * the confirmation response only; it does not change what is written. Same
1935
+ * customized envelope as {@link DbGetArgs.output}, and offered on exactly the
1936
+ * write ops whose result is a row rather than a scalar: the editor hides the
1937
+ * customize control when a statement's whole output is a single `bool`/`int`
1938
+ * scalar (`db.del`, `db.has`), which is why those take no `output`.
1939
+ */
1940
+ output?: Cols;
1941
+ /** Attach addons to enrich the returned row (see {@link AddonSpec}). Each
1942
+ * addon's alias (the last segment of its `as`) is merged onto the row shape in
1943
+ * `InferResponse` — typed from the addon's graft shape when it's a typed
1944
+ * `addon({ table, output })` handle, or `unknown` for a bare-name reference. */
1945
+ addon?: A;
1946
+ /** Capture the post-patch row into this stack variable. Captured literally so
1947
+ * `InferResponse` can trace a `ref` back to this statement. */
1948
+ as?: As;
1949
+ }
1950
+ /** `db.patch <table>` — partial-update a record by a field match (`mvp:dbo_patch`).
1951
+ * Binds the **full post-patch row** (`$updatedInst`), so it's branded with `as` +
1952
+ * the row shape for `InferResponse` (throws `NotFound`/404 when nothing matches). */
1953
+ declare function dbPatch<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const Fs extends readonly FilterXdo[] = readonly []>(args: DbPatchArgs<T, As, Cols, A> & {
1954
+ asFilters?: Fs;
1955
+ }): DbResult<As, ApplyFilters<WithAddons<RowShapeOf<T, Cols>, A>, Fs>>;
1956
+ interface DbTruncateArgs extends StatementOptions {
1957
+ /**
1958
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
1959
+ * Absent unless set — Xano writes it on some statements and not others, so it
1960
+ * is authored rather than derived (see {@link dboBinding}).
1961
+ */
1962
+ tableAlias?: string;
1963
+ table: DbTableRef;
1964
+ /** Reset auto-increment counters. */
1965
+ reset?: boolean;
1966
+ as?: string;
1967
+ }
1968
+ /** `db.truncate <table>` — empty a table (`mvp:dbo_truncate`). */
1969
+ declare function dbTruncate(args: DbTruncateArgs): Statement;
1970
+ /** One field of a row write: a column name, its value, and whether to skip it. */
1971
+ interface DbField {
1972
+ name: string;
1973
+ value: Value;
1974
+ /** Store with `ignore:true` (system/readonly column not written), e.g. `id`. */
1975
+ ignore?: boolean;
1976
+ /**
1977
+ * Sub-entries for an object column: the engine builds the column's value from
1978
+ * these, keyed by each child's name, recursively (stored `expand:true`). The
1979
+ * entry's own `value` is still written — real workspaces carry either an empty
1980
+ * constant or a reference to the object the children were derived from — so it
1981
+ * stays authored rather than derived.
1982
+ */
1983
+ children?: DbField[];
1984
+ }
1985
+ /**
1986
+ * A row cell: any authored {@link Value} **except** a `col()` reference. A `col()`
1987
+ * (bare or wrapped in `withFilters`) does not resolve to the row's stored value
1988
+ * inside a `db.edit`/`db.add` `row` — it evaluates to `null` at runtime and a
1989
+ * following `fl.add(1)` aborts the engine (issue #32). The `__col?: never` bound
1990
+ * turns that live-only failure into a compile error; read the row first and pipe
1991
+ * `ref("...")` through the filter instead.
1992
+ */
1993
+ type RowCell = Value & {
1994
+ readonly __col?: never;
1995
+ };
1996
+ /**
1997
+ * A nested cell: sub-keys written into an object column, keyed by name. Each
1998
+ * leaf is still a {@link RowCell}, so the `col()` guard above holds at every
1999
+ * depth — nesting adds a level, never an escape hatch.
2000
+ *
2001
+ * The column's own stored value is written as an empty constant, which is what
2002
+ * the overwhelming majority of real expanded entries carry. The one shape this
2003
+ * cannot express is an expanded column whose own value is a reference (the
2004
+ * editor seeds the children from it); author that through `data:` with explicit
2005
+ * `children`, which controls every byte.
2006
+ */
2007
+ type NestedCell<C extends string = string> = {
2008
+ readonly [K in C]?: RowCell | NestedCell;
2009
+ };
2010
+ /** Recover a table handle's inferred row type, falling back to `unknown` for a bare name. */
2011
+ type RowsOf<T> = T extends TableDef<string, infer Row> ? Row : unknown;
2012
+ /**
2013
+ * A partial row keyed by column name — the values to write. Unspecified columns
2014
+ * get a type default on `db.add`; on `db.edit` they are marked `ignore:true` and
2015
+ * keep their stored value instead (issue #33 — see `expandRow`).
2016
+ *
2017
+ * A cell is a tagged {@link Value}, a {@link NestedCell}, or — since #75 — a bare
2018
+ * JS literal typed against that column ({@link ScalarCell}), which `expandRow`
2019
+ * coerces to the constant the author would otherwise have written by hand.
2020
+ */
2021
+ type RowMap<C extends string = string, Row = unknown> = Partial<{
2022
+ [K in C]: RowCell | NestedCell | ScalarCell<K extends keyof Row ? Row[K] : unknown>;
2023
+ }>;
2024
+ interface DbAddArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[]> extends StatementOptions {
2025
+ /**
2026
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
2027
+ * Absent unless set — Xano writes it on some statements and not others, so it
2028
+ * is authored rather than derived (see {@link dboBinding}).
2029
+ */
2030
+ tableAlias?: string;
2031
+ /**
2032
+ * Refuse to auto-wire request inputs the endpoint did not explicitly bind.
2033
+ *
2034
+ * A row write auto-wires any column whose name matches an incoming request
2035
+ * input, which is convenient and is also how a caller can reach a column the
2036
+ * endpoint never meant to expose. With this on, the engine consults the
2037
+ * endpoint's declared inputs and skips auto-wiring anything outside them;
2038
+ * explicit `data`/`row` entries are unaffected, because those are bindings you
2039
+ * wrote.
2040
+ *
2041
+ * Off by default, matching the engine's own default — so leaving it unset
2042
+ * writes nothing and changes nothing. Reach for it on any write whose table
2043
+ * has a column a caller must not set (`role`, `is_admin`, `credits`).
2044
+ */
2045
+ enforceHiddenFields?: boolean;
2046
+ table: DbTableRef<T>;
2047
+ /** The row to insert as explicit entries (exact control over each field + `ignore`). */
2048
+ data?: DbField[];
2049
+ /** A partial row keyed by column name; expanded against the table's declared columns. */
2050
+ row?: RowMap<ColsOf<T>, RowsOf<T>>;
2051
+ /**
2052
+ * Restrict the columns of the RETURNED row (XanoScript `output = [...]`) —
2053
+ * the confirmation response only; it does not change what is written. Same
2054
+ * customized envelope as {@link DbGetArgs.output}, and offered on exactly the
2055
+ * write ops whose result is a row rather than a scalar: the editor hides the
2056
+ * customize control when a statement's whole output is a single `bool`/`int`
2057
+ * scalar (`db.del`, `db.has`), which is why those take no `output`.
2058
+ */
2059
+ output?: Cols;
2060
+ /** Attach addons to enrich the returned row (see {@link AddonSpec}). Each
2061
+ * addon's alias (the last segment of its `as`) is merged onto the row shape in
2062
+ * `InferResponse` — typed from the addon's graft shape when it's a typed
2063
+ * `addon({ table, output })` handle, or `unknown` for a bare-name reference. */
2064
+ addon?: A;
2065
+ /** Capture the inserted row into this stack variable. Captured literally so
2066
+ * `InferResponse` can trace a `ref` back to this statement. */
2067
+ as?: As;
2068
+ }
2069
+ /** `db.add <table>` — insert a record (`mvp:dbo_add`). Binds the **full inserted
2070
+ * row** (including the auto-assigned `id`/`created_at`), so it's branded with
2071
+ * `as` + the row shape for `InferResponse`. */
2072
+ declare function dbAdd<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const Fs extends readonly FilterXdo[] = readonly []>(args: DbAddArgs<T, As, Cols, A> & {
2073
+ asFilters?: Fs;
2074
+ }): DbResult<As, ApplyFilters<WithAddons<RowShapeOf<T, Cols>, A>, Fs>>;
2075
+ interface DbEditArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[]> extends StatementOptions {
2076
+ /**
2077
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
2078
+ * Absent unless set — Xano writes it on some statements and not others, so it
2079
+ * is authored rather than derived (see {@link dboBinding}).
2080
+ */
2081
+ tableAlias?: string;
2082
+ /**
2083
+ * Refuse to auto-wire request inputs the endpoint did not explicitly bind.
2084
+ *
2085
+ * A row write auto-wires any column whose name matches an incoming request
2086
+ * input, which is convenient and is also how a caller can reach a column the
2087
+ * endpoint never meant to expose. With this on, the engine consults the
2088
+ * endpoint's declared inputs and skips auto-wiring anything outside them;
2089
+ * explicit `data`/`row` entries are unaffected, because those are bindings you
2090
+ * wrote.
2091
+ *
2092
+ * Off by default, matching the engine's own default — so leaving it unset
2093
+ * writes nothing and changes nothing. Reach for it on any write whose table
2094
+ * has a column a caller must not set (`role`, `is_admin`, `credits`).
2095
+ */
2096
+ enforceHiddenFields?: boolean;
2097
+ table: DbTableRef<T>;
2098
+ /** The lookup field. A dotted path reaches an object column's sub-key or a joined table's column ({@link QualifiedCol}). */
2099
+ fieldName?: QualifiedCol<ColsOf<T>>;
2100
+ fieldValue: Value;
2101
+ /** The new field values as explicit entries (exact control over each field + `ignore`). */
2102
+ data?: DbField[];
2103
+ /**
2104
+ * A **partial** row keyed by column name: only the columns you list are
2105
+ * written. Columns you omit are emitted with `ignore:true` and keep their
2106
+ * stored value — a `{ votes }` edit updates `votes` alone and leaves every
2107
+ * other column intact (issue #33). Expanded against the table's declared
2108
+ * columns. Use `data` for byte-exact control over each entry's `ignore` flag.
2109
+ */
2110
+ row?: RowMap<ColsOf<T>, RowsOf<T>>;
2111
+ /**
2112
+ * Restrict the columns of the RETURNED row (XanoScript `output = [...]`) —
2113
+ * the confirmation response only; it does not change what is written. Same
2114
+ * customized envelope as {@link DbGetArgs.output}, and offered on exactly the
2115
+ * write ops whose result is a row rather than a scalar: the editor hides the
2116
+ * customize control when a statement's whole output is a single `bool`/`int`
2117
+ * scalar (`db.del`, `db.has`), which is why those take no `output`.
2118
+ */
2119
+ output?: Cols;
2120
+ /** Attach addons to enrich the returned row (see {@link AddonSpec}). Each
2121
+ * addon's alias (the last segment of its `as`) is merged onto the row shape in
2122
+ * `InferResponse` — typed from the addon's graft shape when it's a typed
2123
+ * `addon({ table, output })` handle, or `unknown` for a bare-name reference. */
2124
+ addon?: A;
2125
+ /** Capture the post-mutation row into this stack variable. Captured literally so
2126
+ * `InferResponse` can trace a `ref` back to this statement. */
2127
+ as?: As;
2128
+ }
2129
+ /** `db.edit <table>` — update a record matched by a field (`mvp:dbo_editby`).
2130
+ * Binds the **full post-mutation row** (the freshly-written values), so it's
2131
+ * branded with `as` + the row shape for `InferResponse` (throws `NotFound`/404
2132
+ * when nothing matches). */
2133
+ declare function dbEdit<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const Fs extends readonly FilterXdo[] = readonly []>(args: DbEditArgs<T, As, Cols, A> & {
2134
+ asFilters?: Fs;
2135
+ }): DbResult<As, ApplyFilters<WithAddons<RowShapeOf<T, Cols>, A>, Fs>>;
2136
+ /**
2137
+ * `db.add_or_edit` (`mvp:dbo_addoreditby`) — upsert: edit the row matched by
2138
+ * `fieldName`/`fieldValue` if it exists, else insert. Its persisted fixture is a
2139
+ * *leaner* serialization generation than the `dbo_add`/`dbo_editby` family:
2140
+ *
2141
+ * - input entries are the lean `{name,value,tag,filters}` form (no
2142
+ * `expand`/`children`), and only the row `data` entries carry an `ignore`
2143
+ * flag — the `field_name`/`field_value` lookup pair never do;
2144
+ * - `context.dbo` additionally carries the table's `as` (its name) beside `id`;
2145
+ * - there is no rich `description`/`settings_registry`/`output`/`addon` envelope.
2146
+ *
2147
+ * Matched correct-by-construction against the golden, same posture as the rest
2148
+ * of the db family.
2149
+ */
2150
+ interface DbAddOrEditArgs<T extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
2151
+ /**
2152
+ * Refuse to auto-wire request inputs the endpoint did not explicitly bind.
2153
+ *
2154
+ * A row write auto-wires any column whose name matches an incoming request
2155
+ * input, which is convenient and is also how a caller can reach a column the
2156
+ * endpoint never meant to expose. With this on, the engine consults the
2157
+ * endpoint's declared inputs and skips auto-wiring anything outside them;
2158
+ * explicit `data`/`row` entries are unaffected, because those are bindings you
2159
+ * wrote.
2160
+ *
2161
+ * Off by default, matching the engine's own default — so leaving it unset
2162
+ * writes nothing and changes nothing. Reach for it on any write whose table
2163
+ * has a column a caller must not set (`role`, `is_admin`, `credits`).
2164
+ */
2165
+ enforceHiddenFields?: boolean;
2166
+ table: DbTableRef<T>;
2167
+ /** The match field (defaults to the primary key `id`). */
2168
+ /** The lookup field. A dotted path reaches an object column's sub-key or a joined table's column ({@link QualifiedCol}). */
2169
+ fieldName?: QualifiedCol<ColsOf<T>>;
2170
+ /** The value to match for the edit branch. */
2171
+ fieldValue: Value;
2172
+ /** The row to upsert as explicit entries (exact control over each field + `ignore`). */
2173
+ data?: DbField[];
2174
+ /** A partial row keyed by column name; expanded against the table's declared columns. */
2175
+ row?: RowMap<ColsOf<T>, RowsOf<T>>;
2176
+ /** Capture the upserted row into this stack variable. Captured literally so
2177
+ * `InferResponse` can trace a `ref` back to this statement. */
2178
+ as?: As;
2179
+ /**
2180
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
2181
+ * Absent unless set — Xano writes it on some statements and not others, so it
2182
+ * is authored rather than derived (see {@link dboBinding}).
2183
+ */
2184
+ tableAlias?: string;
2185
+ }
2186
+ /** `db.add_or_edit <table>` — upsert a record by a field match (`mvp:dbo_addoreditby`).
2187
+ * Binds the **full upserted row** (`$inst->toArray()`, the edit-or-insert result),
2188
+ * so it's branded with `as` + the row shape for `InferResponse`. */
2189
+ declare function dbAddOrEdit<T extends ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: DbAddOrEditArgs<T, As> & {
2190
+ asFilters?: Fs;
2191
+ }): DbResult<As, ApplyFilters<FullRowShapeOf<T>, Fs>>;
2192
+ interface DbSchemaArgs extends StatementOptions {
2193
+ /**
2194
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
2195
+ * Absent unless set — Xano writes it on some statements and not others, so it
2196
+ * is authored rather than derived (see {@link dboBinding}).
2197
+ */
2198
+ tableAlias?: string;
2199
+ table: DbTableRef;
2200
+ /** Dot-path into the schema to read. */
2201
+ path: Value;
2202
+ as?: string;
2203
+ }
2204
+ /** `db.schema <table>` — read a table's schema (`mvp:dbo_get_schema`). */
2205
+ declare function dbSchema(args: DbSchemaArgs): Statement;
2206
+ /**
2207
+ * Result shape of a raw-SQL query. The engine schema types this as open
2208
+ * `static:text` (default `"list"`); the known values are suggested while any
2209
+ * string remains accepted.
2210
+ */
2211
+ type DbResponseType = "list" | "single" | (string & {});
2212
+ /**
2213
+ * How the SQL body is interpolated before it runs.
2214
+ *
2215
+ * `"prepared"` (the engine default) substitutes the positional `args` as bound
2216
+ * parameters. `"template_engine"` renders the body as a template first, which is
2217
+ * what lets a query interpolate structure — a column list, a table name — that a
2218
+ * bound parameter cannot carry. It changes how the statement executes, so it is
2219
+ * authored rather than inferred, and the key is written only when set: the
2220
+ * engine defaults it and omits it at the default.
2221
+ */
2222
+ type DbSqlParser = "prepared" | "template_engine";
2223
+ interface DbDirectQueryArgs extends StatementOptions {
2224
+ /** The raw SQL to run (stored verbatim as `context.code`). */
2225
+ sql: string;
2226
+ /** Result shape: `"list"` (default) or `"single"`. */
2227
+ responseType?: DbResponseType;
2228
+ /** Positional bind arguments — each a tagged value (filters preserved). */
2229
+ args?: Value[];
2230
+ /** How the SQL body is interpolated. See {@link DbSqlParser}. */
2231
+ parser?: DbSqlParser;
2232
+ /** Capture the result into this stack variable. */
2233
+ as?: string;
2234
+ }
2235
+ /**
2236
+ * `db.direct_query` (`mvp:dbo_direct_query`) — execute raw SQL against the
2237
+ * workspace database. Unlike the `!map:dbo` family it references no table, so
2238
+ * `context` carries the SQL (`code`), the `response_type`, and the positional
2239
+ * `arg[]` bind values instead of a `dbo.id`. It keeps the same rich envelope.
2240
+ */
2241
+ declare function dbDirectQuery(args: DbDirectQueryArgs): Statement;
2242
+ interface DbBulkAddArgs extends StatementOptions {
2243
+ /**
2244
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
2245
+ * Absent unless set — Xano writes it on some statements and not others, so it
2246
+ * is authored rather than derived (see {@link dboBinding}).
2247
+ */
2248
+ tableAlias?: string;
2249
+ table: DbTableRef;
2250
+ /** The rows to insert (an array value). */
2251
+ items: Value;
2252
+ /**
2253
+ * Honor an explicit `id` on each row (`allow_id_field`).
2254
+ *
2255
+ * ⚠ **Unset/`false` means the engine STRIPS `id` from every item** and assigns
2256
+ * the next sequence value instead — silently, with no error and no warning.
2257
+ * The rows then sit at ids nothing else expects, which surfaces much later as
2258
+ * a foreign key pointing at the wrong row (issue #259).
2259
+ *
2260
+ * This is the opposite of a `table` `seed`, where supplying `id` pins it. If
2261
+ * you are inserting rows whose ids other rows reference, set this to `true`.
2262
+ * Set it to `false` explicitly to state that engine-assigned ids are intended.
2263
+ */
2264
+ allowIdField?: boolean;
2265
+ as?: string;
2266
+ }
2267
+ /**
2268
+ * `db.bulk.add <table>` — insert many rows (`mvp:dbo_bulkadd`).
2269
+ *
2270
+ * ⚠ An `id` on a row is DISCARDED unless {@link DbBulkAddArgs.allowIdField} is
2271
+ * `true` — see that field. Literal rows carrying one are rejected here rather
2272
+ * than silently renumbered by the engine (issue #259).
2273
+ */
2274
+ declare function dbBulkAdd(args: DbBulkAddArgs): Statement;
2275
+ interface DbBulkDeleteArgs<As extends string = string> extends StatementOptions {
2276
+ /**
2277
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
2278
+ * Absent unless set — Xano writes it on some statements and not others, so it
2279
+ * is authored rather than derived (see {@link dboBinding}).
2280
+ */
2281
+ tableAlias?: string;
2282
+ table: DbTableRef;
2283
+ /**
2284
+ * Filter selecting which rows to delete — the same `where` surface as
2285
+ * `s.db.query`: `expr(...)`/`cmp(...)` comparisons, `and(...)`/`or(...)` groups,
2286
+ * an array of those (ANDed), or a raw `Value`. Encoded into `context.search`
2287
+ * via {@link encodeSearch}. **A `where` that constrains nothing deletes every
2288
+ * row in the table**, which is why it requires {@link DbBulkDeleteArgs.allRows}.
2289
+ */
2290
+ where?: DbWhere;
2291
+ /**
2292
+ * Delete EVERY row: the explicit opt-in a `where`-less bulk delete requires.
2293
+ *
2294
+ * A filter-less delete is a truncate, and the shape that reaches it — forgetting
2295
+ * the predicate — looks identical to the shape that meant it. Saying so costs one
2296
+ * word and cannot be typed by accident. Passing both this and a `where` is a
2297
+ * contradiction and throws.
2298
+ *
2299
+ * Emits an EMPTY-GROUP `context.search`, which is what the engine accepts as
2300
+ * "every row" — omitting the key entirely is refused with
2301
+ * `Missing param: search` (XTS-5). Use `s.db.truncate({ reset: true })` when
2302
+ * the id sequence should restart too; this one returns the deleted count.
2303
+ */
2304
+ allRows?: true;
2305
+ /** Capture the deleted-row count into this stack variable. Captured literally so
2306
+ * `InferResponse` can trace a `ref` back to this statement. */
2307
+ as?: As;
2308
+ }
2309
+ /**
2310
+ * `db.bulk.delete <table>` — delete many rows by a search (`mvp:dbo_bulkdelete`).
2311
+ * Unlike the other bulk ops, the filter rides `context.search`,
2312
+ * NOT an input entry. The `where` is encoded through the shared {@link encodeSearch}
2313
+ * — the identical operand-based `{expression:[…]}` shape `s.db.query` emits — so the
2314
+ * modern DSL (`expr`/`cmp`/`and`/`or`) is fully supported here too.
2315
+ *
2316
+ * Golden-verified against a live capture: `context.search` (shared with the
2317
+ * `dbo_view` search reader) is byte-exact. A `where` that constrains nothing —
2318
+ * an empty `and()`/`or()` group — deletes all rows and returns the count; the
2319
+ * key itself is mandatory, so `allRows` supplies the empty group (XTS-5).
2320
+ *
2321
+ * Binds the **deleted-row count** (the engine's `__self: int` output), so it's
2322
+ * branded with `as` + `number` for `InferResponse` — table-independent.
2323
+ */
2324
+ declare function dbBulkDelete<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: DbBulkDeleteArgs<As> & {
2325
+ asFilters?: Fs;
2326
+ }): DbResult<As, ApplyFilters<number, Fs>>;
2327
+ interface DbBulkWriteArgs<T extends ObjectRef = ObjectRef, As extends string = string> extends StatementOptions {
2328
+ /**
2329
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
2330
+ * Absent unless set — Xano writes it on some statements and not others, so it
2331
+ * is authored rather than derived (see {@link dboBinding}).
2332
+ */
2333
+ tableAlias?: string;
2334
+ table: DbTableRef<T>;
2335
+ /** The rows to write (an array value), each carrying its key. */
2336
+ items: Value;
2337
+ /** Capture the result into this stack variable. Captured literally so
2338
+ * `InferResponse` can trace a `ref` back to this statement. */
2339
+ as?: As;
2340
+ }
2341
+ /** `db.bulk.patch <table>` — partial-update many rows (`mvp:dbo_bulkpatch`).
2342
+ * Binds the **patched-row LIST** (the engine's `__self[]` row output), so it's
2343
+ * branded with `as` + the row-list shape for `InferResponse`. */
2344
+ declare function dbBulkPatch<T extends ObjectRef, const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(args: DbBulkWriteArgs<T, As> & {
2345
+ asFilters?: Fs;
2346
+ }): DbResult<As, ApplyFilters<FullRowShapeOf<T>[], Fs>>;
2347
+ /**
2348
+ * `db.bulk.update <table>` — REPLACE many rows (`mvp:dbo_bulkupdate`).
2349
+ *
2350
+ * ⚠ **Every column an item omits is written to its zero value** (`""` / `0` /
2351
+ * `null` / `[]` / `{}`), not left alone, with an HTTP 200 and no error. This is
2352
+ * a whole-row replace: `{ id: 7, status: "done" }` sets the status and blanks
2353
+ * every other column of row 7. Confirmed in the engine — update and patch run
2354
+ * the same code, and update writes each absent column's default.
2355
+ *
2356
+ * **Use {@link dbBulkPatch} (`s.db.bulk.patch`) to write only the keys an item
2357
+ * carries.** That is what "update these titles" means; this statement is for
2358
+ * replacing rows wholesale. `export()` warns when a STATIC `items` array omits
2359
+ * columns of the bound table, and `--strict` / `export({ strict: true })` fails
2360
+ * the build on it — but an `items` built from a `ref`/`inp` cannot be inspected,
2361
+ * so nothing catches that one for you (issue #15).
2362
+ *
2363
+ * Left **unbranded** (plain {@link Statement}): the engine declares no output
2364
+ * schema for `dbo_bulkupdate`/`dbo_bulkadd`, so
2365
+ * `InferResponse` faithfully resolves a returned bulk-add/update var to `unknown`
2366
+ * — matching where the engine's own OpenAPI walk falls back to `json`. Only
2367
+ * `bulk.patch` (row list) and `bulk.delete` (count) carry a static output schema.
2368
+ */
2369
+ declare function dbBulkUpdate(args: DbBulkWriteArgs): Statement;
2370
+ /**
2371
+ * Paging controls for `db.query`. Static controls (`page`/`per_page`/`offset` as
2372
+ * plain numbers) land in `context.return.list.paging` (with `enabled:true`) and
2373
+ * mirror the engine schema's `return.list.paging` block: `page=1`, `per_page=25`,
2374
+ * `offset=0`, `totals=false`, `metadata=true`.
2375
+ *
2376
+ * **Input-bound (dynamic) paging (issue #66):** pass a {@link Value} (e.g.
2377
+ * `inp("page")`) for `page`/`per_page`/`offset` instead of a number and it is
2378
+ * emitted into `context.simpleExternal.<field>` as a tagged `{value,tag,filters}`
2379
+ * (byte shape from the `simpleExternal` golden — the inner key is `value`, not
2380
+ * `operand`), while the static block stays as the engine's baseline/fallback and
2381
+ * the gate (`enabled:true`). `search`/`sort` accept a {@link Value} for a
2382
+ * dynamic custom-query / sort override; the engine reads those unconditionally.
2383
+ *
2384
+ * The `enabled:true` gate is keyed on whether a **page/per_page/offset** field is
2385
+ * present (static or `Value`) — a `paging` object carrying *only* `search`/`sort`
2386
+ * leaves `enabled:false`, so a dynamic-search-only override does not silently
2387
+ * activate default pagination and truncate the result to 25 rows.
2388
+ *
2389
+ * Note `metadata:true` (the default) wraps the result in a paging envelope
2390
+ * (`{ items, curPage, nextPage, … }`) rather than returning a bare row list; pass
2391
+ * `metadata:false` to keep the bare array. The envelope only applies when a
2392
+ * page/per_page/offset field is present.
2393
+ */
2394
+ interface DbPaging {
2395
+ page?: number | Value;
2396
+ per_page?: number | Value;
2397
+ offset?: number | Value;
2398
+ totals?: boolean;
2399
+ metadata?: boolean;
2400
+ /**
2401
+ * The engine's paging gate (`context.return.<type>.paging.enabled`).
2402
+ *
2403
+ * **Leave this unset.** It defaults to being DERIVED — on whenever a
2404
+ * `page`/`per_page`/`offset` field or a classic `external` blob is present —
2405
+ * which is what stops a `search`/`sort`-only `paging` from silently truncating a
2406
+ * result to 25 rows (issue #41). Setting it overrides that derivation.
2407
+ *
2408
+ * It exists because a stored query can carry the two apart: real workspaces
2409
+ * persist a non-default `per_page` with the gate OFF, and a derived-only encoder
2410
+ * cannot reproduce that — which cost ~158 `db.query` statements their
2411
+ * readability. So this is here to REPRESENT a stored state faithfully, like
2412
+ * `table: null`; authoring `enabled: false` beside a `per_page` asks the engine
2413
+ * to ignore that `per_page`.
2414
+ *
2415
+ * Note it also moves where addons graft: a metadata paging envelope puts rows
2416
+ * under `items[]`, so the gate and the addon offset stay consistent.
2417
+ */
2418
+ enabled?: boolean;
2419
+ /** Dynamic custom-query override (`context.simpleExternal.search`) — a {@link Value}, ANDed onto the static `where`. */
2420
+ search?: Value;
2421
+ /** Dynamic sort override (`context.simpleExternal.sort`) — a {@link Value}; replaces the static sort at runtime. */
2422
+ sort?: Value;
2423
+ }
2424
+ /**
2425
+ * Which parts of a classic {@link DbExternal} blob the engine is permitted to
2426
+ * honor. Each defaults to the engine's own default (search/sort/page `true`,
2427
+ * `per_page` `false`) — the shape from the `external` golden.
2428
+ */
2429
+ interface DbExternalPermissions {
2430
+ search?: boolean;
2431
+ sort?: boolean;
2432
+ page?: boolean;
2433
+ per_page?: boolean;
2434
+ }
2435
+ /**
2436
+ * The classic single-blob external override (`context.external`). Its resolved
2437
+ * `value` is a whole faceted-filter object (`{search, sort, page, per_page}`),
2438
+ * typically fed from one request input; `permissions` gates which of those
2439
+ * sub-keys the engine honors.
2440
+ *
2441
+ * Combines with input-bound `paging` as a **fallback chain**: the engine uses
2442
+ * this blob when it resolves to something non-empty, and falls back to the
2443
+ * per-field `paging` binds when it does not. Supplying both is a working
2444
+ * configuration — an optional whole-config override in front of per-field
2445
+ * defaults — not a conflict.
2446
+ */
2447
+ interface DbExternal {
2448
+ /** The whole external config as one tagged {@link Value} (e.g. `inp("filters")`). */
2449
+ value: Value;
2450
+ /** Per-part gates; each defaults to the engine default. */
2451
+ permissions?: DbExternalPermissions;
2452
+ }
2453
+ interface DbQueryArgs<T extends ObjectRef = ObjectRef, As extends string = string, Cols extends readonly OutputPath<ColsOf<T> | EvalAliases<E>>[] = readonly ColsOf<T>[], A extends readonly AddonSpec[] = readonly AddonSpec[], P extends DbPaging | undefined = DbPaging | undefined, RT extends DbReturnType = DbReturnType, E extends readonly DbEval[] = readonly DbEval[], AG extends DbAggregate = DbAggregate> extends StatementOptions {
2454
+ /**
2455
+ * SQL alias for the bound table (`context.dbo.as`), used to qualify columns.
2456
+ * Absent unless set — Xano writes it on some statements and not others, so it
2457
+ * is authored rather than derived (see {@link dboBinding}).
2458
+ */
2459
+ tableAlias?: string;
2460
+ table: DbTableRef<T>;
2461
+ /**
2462
+ * The engine's `context.return.type`. `"list"` (default) returns a row array
2463
+ * (or paging envelope); `"single"` a first-match `row | null`; `"count"` a
2464
+ * `number`; `"exists"` a `boolean`; `"stream"` a pageable `row[]` with no
2465
+ * metadata envelope. `InferResponse` reflects each shape.
2466
+ */
2467
+ returnType?: RT;
2468
+ /** Primary filter — `expr(...)`, an array of `expr(...)` (ANDed), or a raw `Value`. */
2469
+ where?: DbWhere;
2470
+ /** Additional filter ANDed with `where` (same forms as `where`). */
2471
+ additionalWhere?: DbWhere;
2472
+ /**
2473
+ * Joins (`context.bind[]`) — `[{ table, as?, join?, where? }]`. Joined columns
2474
+ * are addressable by dotted path in `where`/`sort`/`eval`; the row shape is
2475
+ * unchanged (output columns still come from `output`/`eval`).
2476
+ */
2477
+ bind?: DbBind[];
2478
+ /** Sort directives (`[{ sortBy, dir }]`) — applied by the engine. */
2479
+ sort?: SortDirective<ColsOf<T> | EvalAliases<E>>[];
2480
+ /** Acquire row locks. */
2481
+ lock?: boolean;
2482
+ /**
2483
+ * Paging controls (`page`/`per_page`/`offset`/`totals`/`metadata`) — applied by
2484
+ * the engine. **Supplying `paging` changes the response shape:** with metadata
2485
+ * on (the default) the result is wrapped in a paging envelope
2486
+ * (`{ items, curPage, nextPage, prevPage, offset, perPage, itemsReceived }`,
2487
+ * plus `itemsTotal`/`pageTotal` when `totals:true`) instead of a bare row list,
2488
+ * and `InferResponse` reflects that (issue #58). Pass `metadata:false` to keep
2489
+ * the bare array.
2490
+ */
2491
+ paging?: P;
2492
+ /**
2493
+ * Classic single-blob external override (`context.external`) — one tagged
2494
+ * {@link Value} whose resolved value is a whole `{search,sort,page,per_page}`
2495
+ * config, with per-part `permissions` gates. Mutually exclusive with an
2496
+ * input-bound `paging` field (a `Value` page/per_page/offset/search/sort): the
2497
+ * engine honors `simpleExternal` only when `external` is empty, so authoring
2498
+ * both throws. Setting `external` forces `paging.enabled:true` so its
2499
+ * page/per_page take effect even with no `paging` arg.
2500
+ */
2501
+ external?: DbExternal;
2502
+ /**
2503
+ * Distinct-row handling for a `list`/`stream` query (`"auto"` default | `"yes"`
2504
+ * | `"no"`) → `context.return.<type>.distinct`. Ignored for single/count/exists.
2505
+ */
2506
+ distinct?: DbDistinct;
2507
+ /**
2508
+ * Computed output columns (`context.eval[]`) — each `{ name, as, filters? }`.
2509
+ * The `as` alias grafts onto every returned row as an `unknown`-typed key
2510
+ * (`InferResponse`), since a filter pipeline's output isn't statically knowable.
2511
+ * An alias shadowing an existing column throws at build time.
2512
+ */
2513
+ eval?: E;
2514
+ /**
2515
+ * Aggregate/group-by config, used with `returnType:"aggregate"` →
2516
+ * `context.return.aggregate.{group,eval,sort,paging}`. `InferResponse` types the
2517
+ * aggregate row from the `group` and `eval` aliases (values `unknown`).
2518
+ */
2519
+ aggregate?: AG;
2520
+ /** Restrict returned columns. Captured literally so `InferResponse` narrows
2521
+ * the traced row list to exactly these columns. */
2522
+ output?: Cols;
2523
+ /** Attach addons to enrich each returned row (see {@link AddonSpec}). Each
2524
+ * addon's alias (the last segment of its `as`) is merged onto the row shape in
2525
+ * `InferResponse` as an `unknown`-typed key — narrow it at the call site. Author
2526
+ * `as` relative to a row (`"_user"`); when the query returns a metadata paging
2527
+ * envelope, the `items[]` offset is prefixed automatically. */
2528
+ addon?: A;
2529
+ /** Capture the result list into this stack variable. Captured literally so
2530
+ * `InferResponse` can trace a `ref` back to this statement. */
2531
+ as?: As;
2532
+ }
2533
+ /**
2534
+ * `db.query <table>` — the query-all search builder (`mvp:dbo_view`). Emits the
2535
+ * context the engine actually reads:
2536
+ * the filter under `context.search` (`{expression:[…]}`, the same operand-based
2537
+ * shape as conditionals/trigger search), sort + paging under
2538
+ * `context.return.list`, and output-column restriction via the statement `output`
2539
+ * envelope. `where`/`sort`/`paging`/`output` are all applied by the engine.
2540
+ *
2541
+ * A comparison `where` (plus `additionalWhere`) encodes into one ANDed
2542
+ * `expression[]`; a raw `Value` is passed through as `context.search`.
2543
+ */
2544
+ declare function dbQuery<T extends ObjectRef, const As extends string = "", const Cols extends readonly OutputPath<ColsOf<T> | EvalAliases<E>>[] = readonly [], const A extends readonly AddonSpec[] = readonly [], const P extends DbPaging | undefined = undefined, const RT extends DbReturnType = "list", const E extends readonly DbEval[] = readonly [], const AG extends DbAggregate = DbAggregate, const Fs extends readonly FilterXdo[] = readonly []>(args: DbQueryArgs<T, As, Cols, A, P, RT, E, AG> & {
2545
+ asFilters?: Fs;
2546
+ }): DbResult<As, ApplyFilters<QueryResult<RowShapeOf<T, Cols>, A, P, RT, E, AG>, Fs>>;
2547
+ interface DbTransactionArgs extends StatementAnnotations {
2548
+ /** The statements to run atomically. */
2549
+ body: Statement[];
2550
+ /**
2551
+ * Capture the transaction's result into this stack variable.
2552
+ *
2553
+ * A transaction returns whatever its sub-stack returned, so the binding is
2554
+ * real state and not decoration — a pulled workspace stores one (issue #147).
2555
+ * The engine's XanoScript schema for this statement declares no `as`
2556
+ * argument, which is why nothing here modelled it; the statement class
2557
+ * returns a value all the same, and the stack item carries the binding like
2558
+ * any other.
2559
+ */
2560
+ as?: string;
2561
+ }
2562
+ /**
2563
+ * `db.transaction { … }` — run a sub-stack in a database transaction
2564
+ * (`mvp:db_transaction`). Carries the `run` sub-stack and, where the author
2565
+ * bound one, the result variable. Byte-verified (parser-minimal) against the
2566
+ * engine's persisted shape.
2567
+ */
2568
+ declare function dbTransaction(args: DbTransactionArgs): Statement;
2569
+ /** Supported external-SQL engines for `db.external.<engine>.direct_query`. */
2570
+ type ExternalSqlEngine = "mssql" | "mysql" | "oracle" | "postgres" | "snowflake";
2571
+ interface DbExternalQueryArgs extends StatementOptions {
2572
+ /** Which external database engine to target. */
2573
+ engine: ExternalSqlEngine;
2574
+ sql: string;
2575
+ /**
2576
+ * How to reach the external database. Prefer `env("NAME")` over a literal.
2577
+ *
2578
+ * A `Value` is stored as the tagged `context.connection_string_flex`, which is
2579
+ * what new work should write. A bare **string** is stored in the older
2580
+ * `context.connection_string` instead — the engine reads it as the name of a
2581
+ * workspace environment variable unless it already looks like a URL, and
2582
+ * falls back to it whenever the tagged value is empty. The two are separate
2583
+ * stored fields, so a workspace holding the older one round-trips as the older
2584
+ * one rather than being quietly rewritten (issue #138).
2585
+ */
2586
+ connectionString: Value | string;
2587
+ responseType?: DbResponseType;
2588
+ args?: Value[];
2589
+ /** How the SQL body is interpolated. See {@link DbSqlParser}. */
2590
+ parser?: DbSqlParser;
2591
+ as?: string;
2592
+ }
2593
+ /**
2594
+ * `db.external.<engine>.direct_query' — raw SQL against an external database.
2595
+ * Stored shape from the engine's direct-query format (the shared base; these engines extend
2596
+ * it with `connection_string:true`): `context.{code, response_type,
2597
+ * connection_string_flex, arg[]}`. The connection string lands under
2598
+ * `connection_string_flex` (a tagged assignment value), NOT `connection_string`.
2599
+ *
2600
+ * Golden-verified against a live postgres capture: the engine persists
2601
+ * `context.{code,response_type,connection_string_flex,arg}` and does NOT store
2602
+ * `parser` at its default, so the SDK's omission is correct. The rich envelope
2603
+ * matches. @TODO(byte-verify): only postgres captured; the other 4 engines share
2604
+ * the format and stay modeled-by-analogy.
2605
+ */
2606
+ declare function dbExternalQuery(args: DbExternalQueryArgs): Statement;
2607
+
2608
+ /**
2609
+ * Hand-authored typed wrappers for the HTTP-request statement family — the
2610
+ * "External API Request" (`api.request`) and its siblings `stream.from_request`
2611
+ * and `webflow.request`. Each has a generated bare-`Value`
2612
+ * factory because the codegen source YAML types every field as generic
2613
+ * `!kinds assign`; the engine's *runtime* schema is stricter (method enum, int
2614
+ * timeout, object params, string-array headers, booleans) and the frontend
2615
+ * enforces that shape. These wrappers surface ergonomic, literal-friendly types
2616
+ * (each still accepting a dynamic {@link Value}) and delegate encoding to the
2617
+ * generated factory, so the emitted statement stays byte-identical to the
2618
+ * generated path. Shared coercion + TLS validation live in {@link ./coerce.ts}.
2619
+ *
2620
+ * TLS/mTLS field interdependencies are validated at build time only when the
2621
+ * combination is statically provable-invalid (see `assertSslConsistency`); a
2622
+ * dynamic `Value` is never rejected. `description` (Settings tab) and `output`
2623
+ * (Output tab) ride the envelope where the statement carries one — today only
2624
+ * `api.request` does (its siblings are lean specs).
2625
+ */
2626
+
2627
+ /**
2628
+ * The `{request, response}` envelope every external-request statement binds to
2629
+ * its `as` variable (`api.request`, `webflow.request`, `microservice.request`). Shape
2630
+ * confirmed against the Xano engine and a live run: `headers` are
2631
+ * arrays of raw `"Name: value"` lines, `result` is the response body (JSON-decoded
2632
+ * when possible, else the raw string — hence `unknown`), `status` the HTTP code,
2633
+ * and `error` is present only on a transport-level (curl) failure.
2634
+ */
2635
+ interface ApiRequestResult {
2636
+ request: {
2637
+ url: string;
2638
+ method: string;
2639
+ headers: string[];
2640
+ params: unknown;
2641
+ };
2642
+ response: {
2643
+ headers: string[];
2644
+ result: unknown;
2645
+ status: number;
2646
+ error?: {
2647
+ code: number;
2648
+ message: string;
2649
+ };
2650
+ };
2651
+ }
2652
+ interface ApiRequestArgs extends HttpRequestFields, StatementAnnotations {
2653
+ /** Capture the response (`{request, response}`) into this stack variable. */
2654
+ as?: string;
2655
+ /** Request URL. */
2656
+ url?: string | Value;
2657
+ /** Per-statement description (frontend "Settings" tab). */
2658
+ description?: string;
2659
+ /** Output-envelope shaping — result-variable filter chain / field mapping (frontend "Output" tab). */
2660
+ output?: OutputAuthored;
2661
+ }
2662
+ /**
2663
+ * `api.request` — issue an external HTTP request. Ergonomic, literal-friendly
2664
+ * field types over the generated `mvp:api_request` factory; delegates encoding
2665
+ * to it for byte-parity. Any field also accepts a dynamic {@link Value}.
2666
+ *
2667
+ * `method` suggests the 7 verbs, `params` is a key/value object (→ query string
2668
+ * for GET/HEAD/OPTIONS, body otherwise), `headers` an array of full header-line
2669
+ * strings, `timeout` seconds (engine bounds 1–86400), and the verify/follow
2670
+ * flags booleans.
2671
+ *
2672
+ * A plain-object `params` may carry tagged values (`inp`/`ref`/`c.*`) at the TOP
2673
+ * LEVEL only — each is lifted onto a `const:obj` via a `set` filter. Nest one
2674
+ * inside an object or array and encoding throws, because `const:obj` embeds a
2675
+ * plain JSON constant. For a body with any structure, wrap the whole thing in
2676
+ * `obj({...})`, which encodes any depth as a single `const:expr2`.
2677
+ */
2678
+ declare function apiRequest<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(a?: ApiRequestArgs & {
2679
+ as?: As;
2680
+ asFilters?: Fs;
2681
+ }): Statement & AsShapeBrand<As, ApplyFilters<ApiRequestResult, Fs>>;
2682
+ interface StreamFromRequestArgs extends HttpRequestFields, StatementAnnotations {
2683
+ /** Capture the streaming response into this stack variable. */
2684
+ as?: string;
2685
+ /** Request URL. */
2686
+ url?: string | Value;
2687
+ }
2688
+ /**
2689
+ * `stream.from_request` — stream an external HTTP request (`mvp:streaming_api_request`).
2690
+ * Same typed field surface as {@link apiRequest}; delegates to the generated factory.
2691
+ */
2692
+ declare function streamFromRequest(a?: StreamFromRequestArgs): Statement;
2693
+ interface WebflowRequestArgs extends HttpRequestFields, StatementAnnotations {
2694
+ /** Capture the response into this stack variable. */
2695
+ as?: string;
2696
+ /** Request path (relative to the Webflow API host). */
2697
+ path?: string | Value;
2698
+ }
2699
+ /**
2700
+ * `webflow.request` — call the Webflow API (`mvp:connect_webflow_api_request`).
2701
+ * Like {@link apiRequest} but addressed by `path` (the host is engine-supplied).
2702
+ */
2703
+ declare function webflowRequest<const As extends string = "", const Fs extends readonly FilterXdo[] = readonly []>(a?: WebflowRequestArgs & {
2704
+ as?: As;
2705
+ asFilters?: Fs;
2706
+ }): Statement & AsShapeBrand<As, ApplyFilters<ApiRequestResult, Fs>>;
2707
+
2708
+ /**
2709
+ * `microservice.request` — call a container workload running alongside the
2710
+ * workspace (`mvp:microservice_request`).
2711
+ *
2712
+ * Its own module rather than a member of the external-HTTP-request family: a
2713
+ * microservice is a first-class workspace object with its own def factory and
2714
+ * its own deploy path, and this statement shares nothing with `api.request`
2715
+ * beyond the `{request, response}` result envelope — no TLS/cert fields, no
2716
+ * `output` envelope, and a different required-field contract (see
2717
+ * {@link MICROSERVICE_DEFAULTS}).
2718
+ *
2719
+ * The bulk of what lives here is host/port resolution: `host` and `port` are an
2720
+ * authoring convenience that folds into the single `"name:port"` string the
2721
+ * engine actually reads, and everything provably wrong about that pairing is
2722
+ * thrown on at build time rather than left to fail at request time.
2723
+ */
2724
+
2725
+ /** Host spellings `s.microservice.request` accepts. */
2726
+ type MicroserviceHost = MicroserviceDef | string | Value;
2727
+ /**
2728
+ * The literal `servicePort`s a def declares, at the type level — the type-side
2729
+ * mirror of {@link declaredServicePorts}.
2730
+ */
2731
+ type PortsOf<D> = D extends {
2732
+ deployment: {
2733
+ containers: readonly (infer C)[];
2734
+ };
2735
+ } ? C extends {
2736
+ ports: readonly (infer P)[];
2737
+ } ? P extends {
2738
+ servicePort: infer S extends string;
2739
+ } ? S : never : never : never;
2740
+ /** `"8080"` → `8080`, so a port may be written as a number. */
2741
+ type AsNumber<S extends string> = S extends `${infer N extends number}` ? N : never;
2742
+ /**
2743
+ * What `port` accepts for a given `host`.
2744
+ *
2745
+ * Constrained to the declared ports ONLY when they are known as literals. Two
2746
+ * cases deliberately fall back to the open type rather than narrowing to
2747
+ * `never`, because a false type error on valid code is worse than a missing
2748
+ * one: a def whose ports widened to `string` (annotated `MicroserviceDef`,
2749
+ * built dynamically), and a def that declares no ports at all (helm).
2750
+ */
2751
+ type PortArg<D> = string extends PortsOf<D> ? number | string : [PortsOf<D>] extends [never] ? number | string : PortsOf<D> | AsNumber<PortsOf<D>>;
2752
+ /**
2753
+ * The five request fields this statement shares with the external-HTTP family,
2754
+ * taken FROM that family's field set rather than restated.
2755
+ *
2756
+ * The two declarations used to be typed byte-for-byte identically in two files,
2757
+ * and the cost showed up the first time one of them widened: the `headers`
2758
+ * record form (issue #72) had to be hand-added in both places, and missing the
2759
+ * second would have left the record spelling silently unavailable here (issue
2760
+ * #92). The per-field docs stay local because the DEFAULTS differ — this
2761
+ * statement's block schema requires all five, so it emits them (see
2762
+ * {@link MICROSERVICE_DEFAULTS}) where `api.request` may leave them out.
2763
+ */
2764
+ type HttpFields = Pick<HttpRequestFields, "method" | "params" | "headers" | "timeout" | "follow_location">;
2765
+ interface MicroserviceArgs<H extends MicroserviceHost = MicroserviceHost> extends StatementOptions {
2766
+ /** Capture the response into this stack variable. */
2767
+ as?: string;
2768
+ /**
2769
+ * Target microservice — the `microservice()` def to call.
2770
+ *
2771
+ * A plain string is also accepted, and is the only way to reach an
2772
+ * instance-level microservice (those live in instance settings, not the
2773
+ * workspace, so there is no def to pass). It carries its own port:
2774
+ * `"legacy:80"`.
2775
+ */
2776
+ host: H;
2777
+ /**
2778
+ * Port to call, folded into `host` as `name:port`.
2779
+ *
2780
+ * Optional: a microservice declaring exactly one `servicePort` resolves to it.
2781
+ * One declaring several requires this field, and rejects a port it does not
2782
+ * expose — as a TYPE error when the def's ports are known as literals, and as
2783
+ * a build-time throw otherwise. Serialized as text, matching how
2784
+ * `servicePort` is stored.
2785
+ */
2786
+ port?: H extends MicroserviceDef ? PortArg<H> : number | string;
2787
+ /** Request path. */
2788
+ path: string | Value;
2789
+ /** HTTP verb — the 7 engine verbs are suggested; any string or dynamic `Value` is accepted. Defaults to `"GET"`. */
2790
+ method?: HttpFields["method"];
2791
+ /** Request params — a key/value object. Defaults to `{}`. */
2792
+ params?: HttpFields["params"];
2793
+ /** Headers — a `{ Name: value }` record (values may be tagged) or an array of full header-line strings. Defaults to `[]`. */
2794
+ headers?: HttpFields["headers"];
2795
+ /** Request timeout in seconds. Defaults to `10`. */
2796
+ timeout?: HttpFields["timeout"];
2797
+ /** Follow HTTP redirects. Defaults to `true`. */
2798
+ follow_location?: HttpFields["follow_location"];
2799
+ }
2800
+ /**
2801
+ * `microservice.request` — call an in-cluster microservice
2802
+ * (`mvp:microservice_request`). Typed over the generated factory; no TLS/cert
2803
+ * fields (the engine schema omits them).
2804
+ *
2805
+ * Only `host` and `path` are required. `method`, `params`, `headers`, `timeout`,
2806
+ * and `follow_location` default to the engine's own values
2807
+ * ({@link MICROSERVICE_DEFAULTS}) and are always EMITTED — this statement's
2808
+ * block schema requires them, so they cannot simply be left out:
2809
+ *
2810
+ * ```ts
2811
+ * s.microservice.request({ as: "result", host: echoService, path: "/health" })
2812
+ * ```
2813
+ *
2814
+ * Address it by passing the `microservice()` def itself — its declared ports are
2815
+ * then checked at the authoring site, and a rename fixes every call site at once:
2816
+ *
2817
+ * ```ts
2818
+ * s.microservice.request({ host: echoService, path: "/health", ... })
2819
+ * ```
2820
+ *
2821
+ * `host` binds by NAME, not by guid — deliberately, because the engine resolves
2822
+ * this field by name too (a workspace-scoped lookup on the microservice's name).
2823
+ * A guid here would not be merely unconventional; it would be wrong.
2824
+ */
2825
+ declare function microserviceRequest<const As extends string = "", const H extends MicroserviceHost = MicroserviceHost, const Fs extends readonly FilterXdo[] = readonly []>(a: MicroserviceArgs<H> & {
2826
+ as?: As;
2827
+ } & {
2828
+ asFilters?: Fs;
2829
+ }): Statement & AsShapeBrand<As, ApplyFilters<ApiRequestResult, Fs>>;
2830
+
2831
+ /**
2832
+ * Typed `precondition` / `throw` overrides (issue #21).
2833
+ *
2834
+ * `s.throw` raises a generic error the runtime returns with **HTTP 200** and an
2835
+ * error body — a client checking `res.ok` (or any non-2xx guard) treats a
2836
+ * deliberately-thrown error as success. `s.precondition` instead maps its
2837
+ * `error_type` to a status-bearing exception (400/401/403/404/429/…), so a
2838
+ * boundary rejection is observable via standard HTTP semantics.
2839
+ *
2840
+ * Both delegate to the codegen'd factory — the encoded statement is identical —
2841
+ * and only narrow/annotate the authoring types. `error_type` in particular ships
2842
+ * from codegen as a bare `string`; here it becomes the engine's enum so the
2843
+ * valid values (and the status each yields) are discoverable at the call site.
2844
+ */
2845
+
2846
+ /**
2847
+ * The exception a failed {@link precondition} raises, and the HTTP status the
2848
+ * runtime returns for it. Mirrors the engine's `mvp:precondition` `error_type`
2849
+ * enum ({@link https://github.com/xanots/sdk/issues/21 #21}):
2850
+ *
2851
+ * - `standard` — generic error (the default).
2852
+ * - `badrequest` — **400** Bad Request.
2853
+ * - `inputerror` — **400** Bad Request, tagged as input validation (the
2854
+ * `payload` is attached as the offending param).
2855
+ * - `unauthorized` — **401** Unauthorized.
2856
+ * - `accessdenied` — **403** Forbidden.
2857
+ * - `notfound` — **404** Not Found.
2858
+ * - `toomanyrequests` — **429** Too Many Requests.
2859
+ */
2860
+ declare const PRECONDITION_ERROR_TYPES: readonly ["standard", "notfound", "toomanyrequests", "accessdenied", "unauthorized", "badrequest", "inputerror"];
2861
+ type PreconditionErrorType = (typeof PRECONDITION_ERROR_TYPES)[number];
2862
+ interface PreconditionArgs extends StatementAnnotations {
2863
+ /** The condition that must hold. When it evaluates falsy, the error is raised. */
2864
+ expr?: Condition;
2865
+ /**
2866
+ * Which status-bearing exception to raise on failure (default `standard`). Use
2867
+ * e.g. `badrequest` / `inputerror` to reject invalid input with a **400** a
2868
+ * client can detect via `res.ok` — unlike `s.throw`, which returns 200.
2869
+ */
2870
+ error_type?: PreconditionErrorType;
2871
+ /**
2872
+ * The error message. ⚠ **Use `c.text("…")`, not a bare string.**
2873
+ *
2874
+ * The engine reads this field as a TAGGED value and falls back to the generic
2875
+ * `"Precondition failed."` whenever what it reads is empty or non-scalar — so
2876
+ * a bare string is dropped and the client never sees the message you wrote.
2877
+ * A `c.text(...)` (or any computed {@link Value}) is delivered intact. The
2878
+ * `error_type` → HTTP status mapping is correct either way; it is only the
2879
+ * message that is lost.
2880
+ *
2881
+ * The bare-string form stays accepted because a pulled workspace can carry
2882
+ * one and has to round-trip, not because it is a spelling to choose.
2883
+ */
2884
+ error?: Value | string;
2885
+ /** Extra payload attached to the error (for `inputerror`, the offending param). */
2886
+ payload?: Value;
2887
+ }
2888
+ /**
2889
+ * `precondition { … }` — assert a condition and raise a **status-bearing** error
2890
+ * if it fails (`mvp:precondition`). Prefer this over {@link throwError} (`s.throw`)
2891
+ * whenever the rejection must be observable via HTTP status — a client guarding
2892
+ * on `res.ok` sees a real 4xx instead of a 200 with an error body. See issue #21.
2893
+ *
2894
+ * @example
2895
+ * s.precondition({
2896
+ * expr: fl.starts_with(input.url, "http"),
2897
+ * error_type: "badrequest",
2898
+ * error: c.text("url must start with http:// or https://"),
2899
+ * })
2900
+ */
2901
+ declare function precondition(a?: PreconditionArgs): Statement;
2902
+ interface ThrowArgs extends StatementAnnotations {
2903
+ /** Optional error name/code. */
2904
+ name?: string;
2905
+ /** The error value/message. */
2906
+ value: Value;
2907
+ }
2908
+ /**
2909
+ * `throw <value>` — raise an error from the stack (`mvp:throw_error`).
2910
+ *
2911
+ * ⚠️ The runtime returns a thrown error with **HTTP 200** and an error body, so
2912
+ * a client checking `res.ok` treats it as success. For a rejection that surfaces
2913
+ * as a real 4xx status, use {@link precondition} (`s.precondition`) with an
2914
+ * `error_type`. See issue #21.
2915
+ */
2916
+ declare function throwError(a: ThrowArgs): Statement;
2917
+
2918
+ /**
2919
+ * Typed overrides for statement args the engine declares as a CLOSED SET but the
2920
+ * codegen ships as a bare `string` (issue #65).
2921
+ *
2922
+ * The generated catalog harvests `enum` from the engine's runtime INPUT schemas,
2923
+ * so a closed set declared on a `context`-routed field arrives untyped. Both
2924
+ * fields here are context-routed, which is why they slipped through: the engine
2925
+ * states the members plainly, the SDK's types did not, and a typo type-checked,
2926
+ * exported, and deployed before misbehaving on a live environment.
2927
+ *
2928
+ * `access` is the sharp case. It defaults to `public`, so a misspelled
2929
+ * `"private"` does not fail closed — it serves the file to the world. That is
2930
+ * the wrong direction to fail in, and it was reachable with no compile-time
2931
+ * signal and no documented value list.
2932
+ *
2933
+ * Same shape as {@link ../special/precondition.ts}: delegate to the codegen'd
2934
+ * factory so the encoded statement is byte-identical, and narrow only the
2935
+ * authoring type. The member arrays are exported and consumed by the manifest
2936
+ * renderer (`CONTEXT_FIELD_ENUMS`), so the shipped types and the rendered
2937
+ * catalog line cannot drift from each other.
2938
+ */
2939
+
2940
+ /**
2941
+ * Who can read a file created by the `s.storage.create_*` family.
2942
+ *
2943
+ * - `public` — world-readable by URL (**the engine's default**).
2944
+ * - `private` — reachable only through a signed URL
2945
+ * (`s.storage.sign_private_url`).
2946
+ *
2947
+ * Mirrors the engine's `access` enum on `mvp:create_attachment`,
2948
+ * `mvp:create_audio`, `mvp:create_image` and `mvp:create_video`.
2949
+ */
2950
+ declare const STORAGE_ACCESS: readonly ["public", "private"];
2951
+ type StorageAccess = (typeof STORAGE_ACCESS)[number];
2952
+ /**
2953
+ * What `s.util.set_header` does when the header it sets is already present.
2954
+ *
2955
+ * - `replace` — overwrite the existing value (**the engine's default**).
2956
+ * - `append` — add another value, keeping the existing one.
2957
+ *
2958
+ * Mirrors the engine's `duplicates` enum on `mvp:setheader`.
2959
+ */
2960
+ declare const HEADER_DUPLICATES: readonly ["replace", "append"];
2961
+ type HeaderDuplicates = (typeof HEADER_DUPLICATES)[number];
2962
+ /** `access` narrowed on a generated `storage.create_*` factory. */
2963
+ type WithAccess<T> = Omit<T, "access"> & {
2964
+ access?: StorageAccess;
2965
+ };
2966
+ type CreateAttachmentArgs = WithAccess<Parameters<typeof generated.storage.create_attachment>[0]>;
2967
+ type CreateAudioArgs = WithAccess<Parameters<typeof generated.storage.create_audio>[0]>;
2968
+ type CreateImageArgs = WithAccess<Parameters<typeof generated.storage.create_image>[0]>;
2969
+ type CreateVideoArgs = WithAccess<Parameters<typeof generated.storage.create_video>[0]>;
2970
+ type SetHeaderArgs = Omit<Parameters<typeof generated.util.set_header>[0], "duplicates"> & {
2971
+ duplicates?: HeaderDuplicates;
2972
+ };
2973
+ /**
2974
+ * `create_attachment` — store an uploaded file resource as an attachment.
2975
+ *
2976
+ * ⚠ `access` defaults to `"public"` (world-readable by URL). Pass
2977
+ * `access: "private"` and reach the file through `s.storage.sign_private_url`
2978
+ * when it must not be.
2979
+ */
2980
+ declare function createAttachment(a: CreateAttachmentArgs): Statement;
2981
+ /**
2982
+ * `create_audio` — store an uploaded file resource as audio metadata.
2983
+ *
2984
+ * ⚠ `access` defaults to `"public"` (world-readable by URL).
2985
+ */
2986
+ declare function createAudio(a: CreateAudioArgs): Statement;
2987
+ /**
2988
+ * `create_image` — store an uploaded file resource as image metadata.
2989
+ *
2990
+ * ⚠ `access` defaults to `"public"` (world-readable by URL).
2991
+ */
2992
+ declare function createImage(a: CreateImageArgs): Statement;
2993
+ /**
2994
+ * `create_video` — store an uploaded file resource as video metadata.
2995
+ *
2996
+ * ⚠ `access` defaults to `"public"` (world-readable by URL).
2997
+ */
2998
+ declare function createVideo(a: CreateVideoArgs): Statement;
2999
+ /**
3000
+ * `set_header` — set a response header. `duplicates` decides what happens when
3001
+ * the header is already present: `replace` (the default) overwrites it,
3002
+ * `append` adds another value alongside it.
3003
+ */
3004
+ declare function setHeader(a: SetHeaderArgs): Statement;
3005
+
3006
+ /**
3007
+ * Typed refusal of `capture` on `s.lambda` (issue #73).
3008
+ *
3009
+ * The grounding docs introduce an inline `code:` arrow and then, several
3010
+ * paragraphs later, `lam.fn(fn, { surface?, capture? })`. Nothing connected the
3011
+ * two, so `capture` read as a property of lambda bodies generally. The bare
3012
+ * "does not exist in type" error that produced implies the WRONG fix — drop the
3013
+ * field — when the right one is to move the body into `lam.fn`.
3014
+ *
3015
+ * Naming the field and pointing at `lam.fn` costs nothing at runtime: the
3016
+ * factory delegates unchanged, so the encoded statement is byte-identical.
3017
+ */
3018
+
3019
+ type LambdaArgs = Parameters<typeof generated.lambda>[0] & {
3020
+ /**
3021
+ * @deprecated Not a field of `s.lambda`. `capture` is an option of `lam.fn` —
3022
+ * move the body there: `code: lam.fn(fn, { capture: { … } })`.
3023
+ *
3024
+ * An inline `code:` arrow receives bindings only, so there is no slot here to
3025
+ * pass data through. Relocate the body; do not drop the field.
3026
+ */
3027
+ capture?: never;
3028
+ };
3029
+ /**
3030
+ * `lambda { … }` — run a JavaScript body (`mvp:lambda`).
3031
+ *
3032
+ * Delegates to the generated factory unchanged. The only addition is a typed
3033
+ * refusal of `capture` (issue #73): the grounding docs introduce an inline
3034
+ * `code:` arrow and then `lam.fn(fn, { capture })` several paragraphs later, so
3035
+ * `capture` reads as a property of lambda bodies generally. The bare
3036
+ * "does not exist in type" error that produced implies the wrong fix — drop the
3037
+ * field — when the right one is to move the body into `lam.fn`. Naming it here
3038
+ * costs nothing at runtime and puts the answer in the error.
3039
+ */
3040
+ declare function lambda(a?: LambdaArgs): Statement;
3041
+
3042
+ declare const s: {
3043
+ readonly precondition: typeof precondition;
3044
+ readonly throw: typeof throwError;
3045
+ readonly lambda: typeof lambda;
3046
+ readonly set_var: typeof setVar;
3047
+ readonly update_var: typeof updateVar;
3048
+ readonly conditional: typeof conditional;
3049
+ readonly comment: typeof comment;
3050
+ readonly for: typeof forLoop;
3051
+ readonly foreach: typeof foreachLoop;
3052
+ readonly while: typeof whileLoop;
3053
+ readonly group: typeof group;
3054
+ readonly switch: typeof switchStatement;
3055
+ readonly try_catch: typeof tryCatch;
3056
+ readonly return: typeof returnValue;
3057
+ readonly foreach_break: typeof foreachBreak;
3058
+ readonly foreach_continue: typeof foreachContinue;
3059
+ readonly foreach_remove: typeof foreachRemove;
3060
+ readonly function: {
3061
+ readonly run: typeof functionRun;
3062
+ readonly call: typeof functionCall;
3063
+ };
3064
+ readonly action: {
3065
+ readonly call: typeof actionCall;
3066
+ readonly package: {
3067
+ readonly call: typeof actionPackageCall;
3068
+ };
3069
+ };
3070
+ readonly workflow_test: {
3071
+ readonly call: typeof workflowTestCall;
3072
+ };
3073
+ readonly api: {
3074
+ readonly call: typeof apiCall;
3075
+ readonly realtime_event: typeof realtimeEvent;
3076
+ readonly request: typeof apiRequest;
3077
+ readonly stream: (a: {
3078
+ value: Value;
3079
+ disabled?: boolean;
3080
+ description?: string;
3081
+ }) => Statement;
3082
+ };
3083
+ readonly microservice: {
3084
+ readonly request: typeof microserviceRequest;
3085
+ };
3086
+ readonly realtime: {
3087
+ readonly publish: typeof realtimePublish;
3088
+ readonly get_session: (a?: {
3089
+ as?: string;
3090
+ disabled?: boolean;
3091
+ description?: string;
3092
+ asFilters?: FilterXdo[];
3093
+ }) => Statement;
3094
+ };
3095
+ readonly stream: {
3096
+ readonly from_request: typeof streamFromRequest;
3097
+ readonly from_csv: (a: {
3098
+ as?: string;
3099
+ value: Value;
3100
+ separator?: Value;
3101
+ enclosure?: Value;
3102
+ escape_char?: Value;
3103
+ disabled?: boolean;
3104
+ description?: string;
3105
+ asFilters?: FilterXdo[];
3106
+ output?: OutputAuthored;
3107
+ }) => Statement;
3108
+ readonly from_jsonl: (a: {
3109
+ as?: string;
3110
+ value: Value;
3111
+ disabled?: boolean;
3112
+ description?: string;
3113
+ asFilters?: FilterXdo[];
3114
+ }) => Statement;
3115
+ };
3116
+ readonly webflow: {
3117
+ readonly request: typeof webflowRequest;
3118
+ };
3119
+ readonly task: {
3120
+ readonly call: typeof taskCall;
3121
+ };
3122
+ readonly tool: {
3123
+ readonly call: typeof toolCall;
3124
+ };
3125
+ readonly trigger: {
3126
+ readonly call: typeof triggerCall;
3127
+ };
3128
+ readonly middleware: {
3129
+ readonly call: typeof middlewareCall;
3130
+ };
3131
+ readonly addon: {
3132
+ readonly call: typeof addonCall;
3133
+ };
3134
+ readonly db: {
3135
+ readonly add: typeof dbAdd;
3136
+ readonly edit: typeof dbEdit;
3137
+ readonly add_or_edit: typeof dbAddOrEdit;
3138
+ readonly get: typeof dbGet;
3139
+ readonly get_by_id: typeof dbGetById;
3140
+ readonly del: typeof dbDel;
3141
+ readonly has: typeof dbHas;
3142
+ readonly patch: typeof dbPatch;
3143
+ readonly truncate: typeof dbTruncate;
3144
+ readonly schema: typeof dbSchema;
3145
+ readonly direct_query: typeof dbDirectQuery;
3146
+ readonly query: typeof dbQuery;
3147
+ readonly transaction: typeof dbTransaction;
3148
+ readonly bulk: {
3149
+ readonly add: typeof dbBulkAdd;
3150
+ readonly delete: typeof dbBulkDelete;
3151
+ readonly patch: typeof dbBulkPatch;
3152
+ readonly update: typeof dbBulkUpdate;
3153
+ };
3154
+ readonly external: {
3155
+ readonly mssql: {
3156
+ direct_query: (a: Omit<Parameters<typeof dbExternalQuery>[0], "engine">) => Statement;
3157
+ };
3158
+ readonly mysql: {
3159
+ direct_query: (a: Omit<Parameters<typeof dbExternalQuery>[0], "engine">) => Statement;
3160
+ };
3161
+ readonly oracle: {
3162
+ direct_query: (a: Omit<Parameters<typeof dbExternalQuery>[0], "engine">) => Statement;
3163
+ };
3164
+ readonly postgres: {
3165
+ direct_query: (a: Omit<Parameters<typeof dbExternalQuery>[0], "engine">) => Statement;
3166
+ };
3167
+ readonly snowflake: {
3168
+ direct_query: (a: Omit<Parameters<typeof dbExternalQuery>[0], "engine">) => Statement;
3169
+ };
3170
+ };
3171
+ readonly set_datasource: (a: {
3172
+ value: Value;
3173
+ workspace_id?: Value;
3174
+ disabled?: boolean;
3175
+ description?: string;
3176
+ }) => Statement;
3177
+ };
3178
+ readonly ai: {
3179
+ readonly agent: {
3180
+ readonly run: typeof aiAgentRun;
3181
+ };
3182
+ readonly external: {
3183
+ mcp: {
3184
+ server_details: (a?: {
3185
+ as?: string;
3186
+ url?: Value;
3187
+ bearer_token?: Value;
3188
+ connection_type?: "sse" | "stream" | Value;
3189
+ disabled?: boolean;
3190
+ description?: string;
3191
+ asFilters?: FilterXdo[];
3192
+ }) => Statement;
3193
+ tool: {
3194
+ list: (a?: {
3195
+ as?: string;
3196
+ url?: Value;
3197
+ bearer_token?: Value;
3198
+ connection_type?: "sse" | "stream" | Value;
3199
+ disabled?: boolean;
3200
+ description?: string;
3201
+ asFilters?: FilterXdo[];
3202
+ }) => Statement;
3203
+ run: (a?: {
3204
+ as?: string;
3205
+ url?: Value;
3206
+ bearer_token?: Value;
3207
+ connection_type?: "sse" | "stream" | Value;
3208
+ tool?: Value;
3209
+ args?: Value;
3210
+ disabled?: boolean;
3211
+ description?: string;
3212
+ asFilters?: FilterXdo[];
3213
+ }) => Statement;
3214
+ };
3215
+ };
3216
+ };
3217
+ };
3218
+ readonly cloud: {
3219
+ readonly job: typeof cloudJob & {
3220
+ await: typeof cloudJobAwait;
3221
+ status: typeof cloudJobStatus;
3222
+ };
3223
+ readonly algolia: {
3224
+ request: (a: {
3225
+ as?: string;
3226
+ application_id: Value;
3227
+ api_key: Value;
3228
+ url: Value;
3229
+ method?: "POST" | "GET" | "DELETE" | "PUT" | Value;
3230
+ payload: Value;
3231
+ disabled?: boolean;
3232
+ description?: string;
3233
+ asFilters?: FilterXdo[];
3234
+ output?: OutputAuthored;
3235
+ }) => Statement;
3236
+ };
3237
+ readonly aws: {
3238
+ opensearch: {
3239
+ document: (a: {
3240
+ as?: string;
3241
+ auth_type?: "IAM" | "master" | Value;
3242
+ key_id?: Value;
3243
+ access_key?: Value;
3244
+ region?: Value;
3245
+ base_url: Value;
3246
+ method?: "GET" | "POST" | "PUT" | "DELETE" | Value;
3247
+ index?: Value;
3248
+ doc_id?: Value;
3249
+ doc?: Value;
3250
+ disabled?: boolean;
3251
+ description?: string;
3252
+ asFilters?: FilterXdo[];
3253
+ }) => Statement;
3254
+ query: (a?: {
3255
+ as?: string;
3256
+ auth_type?: "IAM" | "master" | Value;
3257
+ key_id?: Value;
3258
+ access_key?: Value;
3259
+ region?: Value;
3260
+ base_url?: Value;
3261
+ index?: Value;
3262
+ payload?: Value;
3263
+ size?: Value;
3264
+ from?: Value;
3265
+ included_fields?: Value;
3266
+ return_type?: "search" | "count" | Value;
3267
+ expression?: Value;
3268
+ sort?: Value;
3269
+ disabled?: boolean;
3270
+ description?: string;
3271
+ asFilters?: FilterXdo[];
3272
+ }) => Statement;
3273
+ request: (a?: {
3274
+ as?: string;
3275
+ auth_type?: "IAM" | "master" | Value;
3276
+ key_id?: Value;
3277
+ access_key?: Value;
3278
+ region?: Value;
3279
+ method?: "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH" | Value;
3280
+ url?: Value;
3281
+ query?: Value;
3282
+ disabled?: boolean;
3283
+ description?: string;
3284
+ asFilters?: FilterXdo[];
3285
+ }) => Statement;
3286
+ };
3287
+ s3: {
3288
+ delete_file: (a: {
3289
+ as?: string;
3290
+ bucket: Value;
3291
+ region: Value;
3292
+ key: Value;
3293
+ secret: Value;
3294
+ file_key: Value;
3295
+ disabled?: boolean;
3296
+ description?: string;
3297
+ asFilters?: FilterXdo[];
3298
+ }) => Statement;
3299
+ get_file_info: (a: {
3300
+ as?: string;
3301
+ bucket: Value;
3302
+ region: Value;
3303
+ key: Value;
3304
+ secret: Value;
3305
+ file_key: Value;
3306
+ disabled?: boolean;
3307
+ description?: string;
3308
+ asFilters?: FilterXdo[];
3309
+ }) => Statement;
3310
+ list_directory: (a: {
3311
+ as?: string;
3312
+ bucket: Value;
3313
+ region: Value;
3314
+ key: Value;
3315
+ secret: Value;
3316
+ prefix?: Value;
3317
+ next_page_token?: Value;
3318
+ disabled?: boolean;
3319
+ description?: string;
3320
+ asFilters?: FilterXdo[];
3321
+ }) => Statement;
3322
+ read_file: (a: {
3323
+ as?: string;
3324
+ bucket: Value;
3325
+ region: Value;
3326
+ key: Value;
3327
+ secret: Value;
3328
+ file_key: Value;
3329
+ disabled?: boolean;
3330
+ description?: string;
3331
+ asFilters?: FilterXdo[];
3332
+ }) => Statement;
3333
+ sign_url: (a: {
3334
+ as?: string;
3335
+ bucket: Value;
3336
+ region: Value;
3337
+ key: Value;
3338
+ secret: Value;
3339
+ file_key: Value;
3340
+ ttl?: Value;
3341
+ disabled?: boolean;
3342
+ description?: string;
3343
+ asFilters?: FilterXdo[];
3344
+ }) => Statement;
3345
+ upload_file: (a: {
3346
+ as?: string;
3347
+ bucket: Value;
3348
+ region: Value;
3349
+ key: Value;
3350
+ secret: Value;
3351
+ file_key?: Value;
3352
+ file: Value;
3353
+ metadata?: Value;
3354
+ object_lock_mode?: "compliance" | "governance" | Value;
3355
+ object_lock_retain_until?: Value;
3356
+ disabled?: boolean;
3357
+ description?: string;
3358
+ asFilters?: FilterXdo[];
3359
+ }) => Statement;
3360
+ };
3361
+ };
3362
+ readonly azure: {
3363
+ storage: {
3364
+ delete_file: (a: {
3365
+ as?: string;
3366
+ account_name: Value;
3367
+ account_key: Value;
3368
+ container_name: Value;
3369
+ filePath: Value;
3370
+ disabled?: boolean;
3371
+ description?: string;
3372
+ asFilters?: FilterXdo[];
3373
+ }) => Statement;
3374
+ get_file_info: (a: {
3375
+ as?: string;
3376
+ account_name: Value;
3377
+ account_key: Value;
3378
+ container_name: Value;
3379
+ filePath: Value;
3380
+ disabled?: boolean;
3381
+ description?: string;
3382
+ asFilters?: FilterXdo[];
3383
+ }) => Statement;
3384
+ list_directory: (a: {
3385
+ as?: string;
3386
+ account_name: Value;
3387
+ account_key: Value;
3388
+ container_name: Value;
3389
+ path?: Value;
3390
+ disabled?: boolean;
3391
+ description?: string;
3392
+ asFilters?: FilterXdo[];
3393
+ }) => Statement;
3394
+ read_file: (a: {
3395
+ as?: string;
3396
+ account_name: Value;
3397
+ account_key: Value;
3398
+ container_name: Value;
3399
+ filePath: Value;
3400
+ disabled?: boolean;
3401
+ description?: string;
3402
+ asFilters?: FilterXdo[];
3403
+ }) => Statement;
3404
+ sign_url: (a: {
3405
+ as?: string;
3406
+ account_name: Value;
3407
+ account_key: Value;
3408
+ container_name: Value;
3409
+ path: Value;
3410
+ ttl?: Value;
3411
+ disabled?: boolean;
3412
+ description?: string;
3413
+ asFilters?: FilterXdo[];
3414
+ }) => Statement;
3415
+ upload_file: (a: {
3416
+ as?: string;
3417
+ account_name: Value;
3418
+ account_key: Value;
3419
+ container_name: Value;
3420
+ filePath: Value;
3421
+ file: Value;
3422
+ metadata?: Value;
3423
+ disabled?: boolean;
3424
+ description?: string;
3425
+ asFilters?: FilterXdo[];
3426
+ }) => Statement;
3427
+ };
3428
+ };
3429
+ readonly elasticsearch: {
3430
+ document: (a: {
3431
+ as?: string;
3432
+ auth_type?: "Basic" | "Bearer" | "API Key" | Value;
3433
+ key_id: Value;
3434
+ access_key: Value;
3435
+ base_url: Value;
3436
+ index: Value;
3437
+ method?: "GET" | "POST" | "PUT" | "DELETE" | Value;
3438
+ doc_id: Value;
3439
+ doc: Value;
3440
+ disabled?: boolean;
3441
+ description?: string;
3442
+ asFilters?: FilterXdo[];
3443
+ }) => Statement;
3444
+ query: (a?: {
3445
+ as?: string;
3446
+ auth_type?: "Basic" | "Bearer" | "API Key" | Value;
3447
+ key_id?: Value;
3448
+ access_key?: Value;
3449
+ base_url?: Value;
3450
+ index?: Value;
3451
+ payload?: Value;
3452
+ size?: Value;
3453
+ from?: Value;
3454
+ included_fields?: Value;
3455
+ return_type?: "search" | "count" | Value;
3456
+ expression?: Value;
3457
+ sort?: Value;
3458
+ disabled?: boolean;
3459
+ description?: string;
3460
+ asFilters?: FilterXdo[];
3461
+ }) => Statement;
3462
+ request: (a?: {
3463
+ as?: string;
3464
+ auth_type?: "Basic" | "Bearer" | "API Key" | Value;
3465
+ key_id?: Value;
3466
+ access_key?: Value;
3467
+ method?: "POST" | "GET" | "PUT" | "DELETE" | "PATCH" | Value;
3468
+ url?: Value;
3469
+ payload?: Value;
3470
+ disabled?: boolean;
3471
+ description?: string;
3472
+ asFilters?: FilterXdo[];
3473
+ }) => Statement;
3474
+ };
3475
+ readonly google: {
3476
+ storage: {
3477
+ delete_file: (a: {
3478
+ as?: string;
3479
+ service_account: Value;
3480
+ bucket: Value;
3481
+ filePath: Value;
3482
+ disabled?: boolean;
3483
+ description?: string;
3484
+ asFilters?: FilterXdo[];
3485
+ }) => Statement;
3486
+ get_file_info: (a: {
3487
+ as?: string;
3488
+ service_account: Value;
3489
+ bucket: Value;
3490
+ filePath: Value;
3491
+ disabled?: boolean;
3492
+ description?: string;
3493
+ asFilters?: FilterXdo[];
3494
+ }) => Statement;
3495
+ list_directory: (a: {
3496
+ as?: string;
3497
+ service_account: Value;
3498
+ bucket: Value;
3499
+ path: Value;
3500
+ disabled?: boolean;
3501
+ description?: string;
3502
+ asFilters?: FilterXdo[];
3503
+ }) => Statement;
3504
+ read_file: (a: {
3505
+ as?: string;
3506
+ service_account: Value;
3507
+ bucket: Value;
3508
+ filePath: Value;
3509
+ disabled?: boolean;
3510
+ description?: string;
3511
+ asFilters?: FilterXdo[];
3512
+ }) => Statement;
3513
+ sign_url: (a: {
3514
+ as?: string;
3515
+ service_account: Value;
3516
+ bucket: Value;
3517
+ filePath: Value;
3518
+ method?: "GET" | "POST" | Value;
3519
+ ttl?: Value;
3520
+ disabled?: boolean;
3521
+ description?: string;
3522
+ asFilters?: FilterXdo[];
3523
+ }) => Statement;
3524
+ upload_file: (a: {
3525
+ as?: string;
3526
+ service_account: Value;
3527
+ bucket: Value;
3528
+ filePath: Value;
3529
+ file: Value;
3530
+ metadata?: Value;
3531
+ disabled?: boolean;
3532
+ description?: string;
3533
+ asFilters?: FilterXdo[];
3534
+ }) => Statement;
3535
+ };
3536
+ };
3537
+ };
3538
+ readonly array: {
3539
+ readonly map: typeof arrayMap;
3540
+ readonly union: typeof arrayUnion;
3541
+ readonly difference: (a?: {
3542
+ as?: string;
3543
+ expr?: Value;
3544
+ value?: Value;
3545
+ by?: Value;
3546
+ disabled?: boolean;
3547
+ description?: string;
3548
+ asFilters?: FilterXdo[];
3549
+ }) => Statement;
3550
+ readonly every: (a?: {
3551
+ expr?: Value;
3552
+ as?: string;
3553
+ if?: Condition;
3554
+ disabled?: boolean;
3555
+ description?: string;
3556
+ asFilters?: FilterXdo[];
3557
+ output?: OutputAuthored;
3558
+ }) => Statement;
3559
+ readonly filter: (a?: {
3560
+ expr?: Value;
3561
+ as?: string;
3562
+ if?: Condition;
3563
+ disabled?: boolean;
3564
+ description?: string;
3565
+ asFilters?: FilterXdo[];
3566
+ }) => Statement;
3567
+ readonly filter_count: (a?: {
3568
+ expr?: Value;
3569
+ as?: string;
3570
+ if?: Condition;
3571
+ disabled?: boolean;
3572
+ description?: string;
3573
+ asFilters?: FilterXdo[];
3574
+ }) => Statement;
3575
+ readonly find: (a?: {
3576
+ expr?: Value;
3577
+ as?: string;
3578
+ if?: Condition;
3579
+ disabled?: boolean;
3580
+ description?: string;
3581
+ asFilters?: FilterXdo[];
3582
+ output?: OutputAuthored;
3583
+ }) => Statement;
3584
+ readonly find_index: (a?: {
3585
+ expr?: Value;
3586
+ as?: string;
3587
+ if?: Condition;
3588
+ disabled?: boolean;
3589
+ description?: string;
3590
+ asFilters?: FilterXdo[];
3591
+ }) => Statement;
3592
+ readonly group_by: (a?: {
3593
+ as?: string;
3594
+ expr?: Value;
3595
+ by?: Value;
3596
+ disabled?: boolean;
3597
+ description?: string;
3598
+ asFilters?: FilterXdo[];
3599
+ }) => Statement;
3600
+ readonly has: (a?: {
3601
+ expr?: Value;
3602
+ as?: string;
3603
+ if?: Condition;
3604
+ disabled?: boolean;
3605
+ description?: string;
3606
+ asFilters?: FilterXdo[];
3607
+ }) => Statement;
3608
+ readonly intersection: (a?: {
3609
+ as?: string;
3610
+ expr?: Value;
3611
+ value?: Value;
3612
+ by?: Value;
3613
+ disabled?: boolean;
3614
+ description?: string;
3615
+ asFilters?: FilterXdo[];
3616
+ }) => Statement;
3617
+ readonly merge: (a?: {
3618
+ name?: string;
3619
+ value?: Value;
3620
+ disabled?: boolean;
3621
+ description?: string;
3622
+ output?: OutputAuthored;
3623
+ }) => Statement;
3624
+ readonly partition: (a?: {
3625
+ expr?: Value;
3626
+ as?: string;
3627
+ if?: Condition;
3628
+ disabled?: boolean;
3629
+ description?: string;
3630
+ asFilters?: FilterXdo[];
3631
+ }) => Statement;
3632
+ readonly pop: (a?: {
3633
+ name?: string;
3634
+ as?: string;
3635
+ disabled?: boolean;
3636
+ description?: string;
3637
+ asFilters?: FilterXdo[];
3638
+ output?: OutputAuthored;
3639
+ }) => Statement;
3640
+ readonly push: (a: {
3641
+ name?: string;
3642
+ value: Value;
3643
+ disabled?: boolean;
3644
+ description?: string;
3645
+ output?: OutputAuthored;
3646
+ }) => Statement;
3647
+ readonly shift: (a?: {
3648
+ name?: string;
3649
+ as?: string;
3650
+ disabled?: boolean;
3651
+ description?: string;
3652
+ asFilters?: FilterXdo[];
3653
+ }) => Statement;
3654
+ readonly unshift: (a: {
3655
+ name?: string;
3656
+ value: Value;
3657
+ disabled?: boolean;
3658
+ description?: string;
3659
+ }) => Statement;
3660
+ };
3661
+ readonly expect: {
3662
+ readonly to_throw: typeof expectToThrow;
3663
+ readonly to_match: typeof expectToMatch;
3664
+ readonly to_be_defined: (a?: {
3665
+ expr?: Value;
3666
+ disabled?: boolean;
3667
+ description?: string;
3668
+ }) => Statement;
3669
+ readonly to_be_empty: (a?: {
3670
+ expr?: Value;
3671
+ disabled?: boolean;
3672
+ description?: string;
3673
+ }) => Statement;
3674
+ readonly to_be_false: (a?: {
3675
+ expr?: Value;
3676
+ disabled?: boolean;
3677
+ description?: string;
3678
+ }) => Statement;
3679
+ readonly to_be_greater_than: (a?: {
3680
+ expr?: Value;
3681
+ value?: Value;
3682
+ disabled?: boolean;
3683
+ description?: string;
3684
+ }) => Statement;
3685
+ readonly to_be_in_the_future: (a?: {
3686
+ expr?: Value;
3687
+ disabled?: boolean;
3688
+ description?: string;
3689
+ }) => Statement;
3690
+ readonly to_be_in_the_past: (a?: {
3691
+ expr?: Value;
3692
+ disabled?: boolean;
3693
+ description?: string;
3694
+ }) => Statement;
3695
+ readonly to_be_less_than: (a?: {
3696
+ expr?: Value;
3697
+ value?: Value;
3698
+ disabled?: boolean;
3699
+ description?: string;
3700
+ }) => Statement;
3701
+ readonly to_be_null: (a?: {
3702
+ expr?: Value;
3703
+ disabled?: boolean;
3704
+ description?: string;
3705
+ }) => Statement;
3706
+ readonly to_be_true: (a?: {
3707
+ expr?: Value;
3708
+ disabled?: boolean;
3709
+ description?: string;
3710
+ }) => Statement;
3711
+ readonly to_be_within: (a?: {
3712
+ expr?: Value;
3713
+ min?: Value;
3714
+ max?: Value;
3715
+ disabled?: boolean;
3716
+ description?: string;
3717
+ }) => Statement;
3718
+ readonly to_contain: (a?: {
3719
+ expr?: Value;
3720
+ value?: Value;
3721
+ disabled?: boolean;
3722
+ description?: string;
3723
+ }) => Statement;
3724
+ readonly to_end_with: (a?: {
3725
+ expr?: Value;
3726
+ value?: Value;
3727
+ disabled?: boolean;
3728
+ description?: string;
3729
+ }) => Statement;
3730
+ readonly to_equal: (a?: {
3731
+ expr?: Value;
3732
+ value?: Value;
3733
+ disabled?: boolean;
3734
+ description?: string;
3735
+ }) => Statement;
3736
+ readonly to_not_be_defined: (a?: {
3737
+ expr?: Value;
3738
+ disabled?: boolean;
3739
+ description?: string;
3740
+ }) => Statement;
3741
+ readonly to_not_be_null: (a?: {
3742
+ expr?: Value;
3743
+ disabled?: boolean;
3744
+ description?: string;
3745
+ }) => Statement;
3746
+ readonly to_not_equal: (a?: {
3747
+ expr?: Value;
3748
+ value?: Value;
3749
+ disabled?: boolean;
3750
+ description?: string;
3751
+ }) => Statement;
3752
+ readonly to_start_with: (a?: {
3753
+ expr?: Value;
3754
+ value?: Value;
3755
+ disabled?: boolean;
3756
+ description?: string;
3757
+ }) => Statement;
3758
+ };
3759
+ readonly security: {
3760
+ readonly create_auth_token: typeof createAuthToken;
3761
+ readonly create_guid: typeof createGuid;
3762
+ readonly check_password: (a?: {
3763
+ as?: string;
3764
+ text_password?: Value;
3765
+ hash_password?: Value;
3766
+ disabled?: boolean;
3767
+ description?: string;
3768
+ asFilters?: FilterXdo[];
3769
+ output?: OutputAuthored;
3770
+ }) => Statement;
3771
+ readonly create_curve_key: (a?: {
3772
+ as?: string;
3773
+ curve?: "P-256" | "P-384" | "P-521" | Value;
3774
+ format?: "object" | "base64" | Value;
3775
+ disabled?: boolean;
3776
+ description?: string;
3777
+ asFilters?: FilterXdo[];
3778
+ }) => Statement;
3779
+ readonly create_password: (a?: {
3780
+ as?: string;
3781
+ character_count?: Value;
3782
+ require_lowercase?: Value;
3783
+ require_uppercase?: Value;
3784
+ require_digit?: Value;
3785
+ require_symbol?: Value;
3786
+ symbol_whitelist?: Value;
3787
+ disabled?: boolean;
3788
+ description?: string;
3789
+ asFilters?: FilterXdo[];
3790
+ }) => Statement;
3791
+ readonly create_rsa_key: (a?: {
3792
+ as?: string;
3793
+ bits?: Value;
3794
+ format?: "object" | "base64" | Value;
3795
+ disabled?: boolean;
3796
+ description?: string;
3797
+ asFilters?: FilterXdo[];
3798
+ }) => Statement;
3799
+ readonly create_secret_key: (a?: {
3800
+ as?: string;
3801
+ bits?: Value;
3802
+ format?: "object" | "base64" | Value;
3803
+ disabled?: boolean;
3804
+ description?: string;
3805
+ asFilters?: FilterXdo[];
3806
+ }) => Statement;
3807
+ readonly create_uuid: (a?: {
3808
+ as?: string;
3809
+ disabled?: boolean;
3810
+ description?: string;
3811
+ asFilters?: FilterXdo[];
3812
+ }) => Statement;
3813
+ readonly decrypt: (a?: {
3814
+ as?: string;
3815
+ data?: Value;
3816
+ algorithm?: "aes-128-cbc" | "aes-192-cbc" | "aes-256-cbc" | "aes-128-gcm" | "aes-192-gcm" | "aes-256-gcm" | Value;
3817
+ key?: Value;
3818
+ iv?: Value;
3819
+ disabled?: boolean;
3820
+ description?: string;
3821
+ asFilters?: FilterXdo[];
3822
+ }) => Statement;
3823
+ readonly encrypt: (a?: {
3824
+ as?: string;
3825
+ data?: Value;
3826
+ algorithm?: "aes-128-cbc" | "aes-192-cbc" | "aes-256-cbc" | "aes-128-gcm" | "aes-192-gcm" | "aes-256-gcm" | Value;
3827
+ key?: Value;
3828
+ iv?: Value;
3829
+ disabled?: boolean;
3830
+ description?: string;
3831
+ asFilters?: FilterXdo[];
3832
+ }) => Statement;
3833
+ readonly jwe_decode: (a?: {
3834
+ as?: string;
3835
+ token?: Value;
3836
+ key?: Value;
3837
+ check_claims?: Value;
3838
+ key_algorithm?: "A128KW" | "A192KW" | "A256KW" | "A128GCMKW" | "A192GCMKW" | "A256GCMKW" | "ECDH-ES+A128KW" | "ECDH-ES+A192KW" | "ECDH-ES+A256KW" | Value;
3839
+ content_algorithm?: "A128GCM" | "A192GCM" | "A256GCM" | "A128CBC-HS256" | "A192CBC-HS384" | "A256CBC-HS512" | Value;
3840
+ timeDrift?: Value;
3841
+ disabled?: boolean;
3842
+ description?: string;
3843
+ asFilters?: FilterXdo[];
3844
+ }) => Statement;
3845
+ readonly jwe_encode: (a?: {
3846
+ as?: string;
3847
+ headers?: Value;
3848
+ claims?: Value;
3849
+ key?: Value;
3850
+ key_algorithm?: "A128KW" | "A192KW" | "A256KW" | "A128GCMKW" | "A192GCMKW" | "A256GCMKW" | "ECDH-ES+A128KW" | "ECDH-ES+A192KW" | "ECDH-ES+A256KW" | Value;
3851
+ content_algorithm?: "A128GCM" | "A192GCM" | "A256GCM" | "A128CBC-HS256" | "A192CBC-HS384" | "A256CBC-HS512" | Value;
3852
+ ttl?: Value;
3853
+ disabled?: boolean;
3854
+ description?: string;
3855
+ asFilters?: FilterXdo[];
3856
+ }) => Statement;
3857
+ readonly jws_decode: (a?: {
3858
+ as?: string;
3859
+ token?: Value;
3860
+ key?: Value;
3861
+ check_claims?: Value;
3862
+ signature_algorithm?: "PS256" | "PS384" | "PS512" | "RS256" | "RS384" | "RS512" | "HS256" | "HS384" | "HS512" | "ES256" | "ES384" | "ES512" | Value;
3863
+ timeDrift?: Value;
3864
+ disabled?: boolean;
3865
+ description?: string;
3866
+ asFilters?: FilterXdo[];
3867
+ }) => Statement;
3868
+ readonly jws_encode: (a?: {
3869
+ as?: string;
3870
+ headers?: Value;
3871
+ claims?: Value;
3872
+ key?: Value;
3873
+ signature_algorithm?: "PS256" | "PS384" | "PS512" | "RS256" | "RS384" | "RS512" | "HS256" | "HS384" | "HS512" | "ES256" | "ES384" | "ES512" | Value;
3874
+ ttl?: Value;
3875
+ disabled?: boolean;
3876
+ description?: string;
3877
+ asFilters?: FilterXdo[];
3878
+ }) => Statement;
3879
+ readonly random_bytes: (a?: {
3880
+ as?: string;
3881
+ length?: Value;
3882
+ disabled?: boolean;
3883
+ description?: string;
3884
+ asFilters?: FilterXdo[];
3885
+ }) => Statement;
3886
+ readonly random_number: (a?: {
3887
+ as?: string;
3888
+ min?: Value;
3889
+ max?: Value;
3890
+ disabled?: boolean;
3891
+ description?: string;
3892
+ asFilters?: FilterXdo[];
3893
+ }) => Statement;
3894
+ };
3895
+ readonly util: {
3896
+ readonly get_raw_input: typeof getRawInput;
3897
+ readonly get_input: typeof getRawInput;
3898
+ readonly post_process: typeof postProcess;
3899
+ readonly ip_lookup: typeof ipLookup;
3900
+ readonly set_header: typeof setHeader;
3901
+ readonly geo_distance: (a?: {
3902
+ as?: string;
3903
+ latitude_1?: Value;
3904
+ longitude_1?: Value;
3905
+ latitude_2?: Value;
3906
+ longitude_2?: Value;
3907
+ disabled?: boolean;
3908
+ description?: string;
3909
+ asFilters?: FilterXdo[];
3910
+ }) => Statement;
3911
+ readonly get_all_input: (a?: {
3912
+ as?: string;
3913
+ disabled?: boolean;
3914
+ description?: string;
3915
+ asFilters?: FilterXdo[];
3916
+ }) => Statement;
3917
+ readonly get_env: (a?: {
3918
+ as?: string;
3919
+ disabled?: boolean;
3920
+ description?: string;
3921
+ asFilters?: FilterXdo[];
3922
+ }) => Statement;
3923
+ readonly get_vars: (a?: {
3924
+ as?: string;
3925
+ disabled?: boolean;
3926
+ description?: string;
3927
+ asFilters?: FilterXdo[];
3928
+ }) => Statement;
3929
+ readonly send_email: (a?: {
3930
+ as?: string;
3931
+ service_provider?: "resend" | "xano" | Value;
3932
+ api_key?: Value;
3933
+ subject?: Value;
3934
+ message?: Value;
3935
+ to?: Value;
3936
+ bcc?: Value;
3937
+ cc?: Value;
3938
+ from?: Value;
3939
+ reply_to?: Value;
3940
+ scheduled_at?: Value;
3941
+ disabled?: boolean;
3942
+ description?: string;
3943
+ asFilters?: FilterXdo[];
3944
+ }) => Statement;
3945
+ readonly sleep: (a: {
3946
+ value: Value;
3947
+ disabled?: boolean;
3948
+ description?: string;
3949
+ }) => Statement;
3950
+ readonly template_engine: (a: {
3951
+ as?: string;
3952
+ value: Value;
3953
+ disabled?: boolean;
3954
+ description?: string;
3955
+ asFilters?: FilterXdo[];
3956
+ }) => Statement;
3957
+ };
3958
+ readonly storage: {
3959
+ readonly create_attachment: typeof createAttachment;
3960
+ readonly create_audio: typeof createAudio;
3961
+ readonly create_image: typeof createImage;
3962
+ readonly create_video: typeof createVideo;
3963
+ readonly create_file_resource: (a: {
3964
+ as?: string;
3965
+ filename: Value;
3966
+ filedata: Value;
3967
+ disabled?: boolean;
3968
+ description?: string;
3969
+ asFilters?: FilterXdo[];
3970
+ output?: OutputAuthored;
3971
+ }) => Statement;
3972
+ readonly delete_file: (a: {
3973
+ pathname: Value;
3974
+ disabled?: boolean;
3975
+ description?: string;
3976
+ output?: OutputAuthored;
3977
+ }) => Statement;
3978
+ readonly read_file_resource: (a: {
3979
+ as?: string;
3980
+ value: Value;
3981
+ disabled?: boolean;
3982
+ description?: string;
3983
+ asFilters?: FilterXdo[];
3984
+ }) => Statement;
3985
+ readonly sign_private_url: (a: {
3986
+ as?: string;
3987
+ pathname: Value;
3988
+ ttl?: Value;
3989
+ disabled?: boolean;
3990
+ description?: string;
3991
+ asFilters?: FilterXdo[];
3992
+ }) => Statement;
3993
+ };
3994
+ readonly await: (a?: {
3995
+ as?: string;
3996
+ ids?: Value;
3997
+ timeout?: Value;
3998
+ disabled?: boolean;
3999
+ description?: string;
4000
+ asFilters?: FilterXdo[];
4001
+ }) => Statement;
4002
+ readonly datadog: {
4003
+ log: (a?: {
4004
+ message?: Value;
4005
+ status?: "debug" | "info" | "notice" | "warn" | "error" | "critical" | "alert" | "emergency" | Value;
4006
+ attributes?: Value;
4007
+ service?: Value;
4008
+ source?: Value;
4009
+ env?: Value;
4010
+ hostname?: Value;
4011
+ tags?: Value;
4012
+ timestamp?: Value;
4013
+ connection?: Value;
4014
+ disabled?: boolean;
4015
+ description?: string;
4016
+ }) => Statement;
4017
+ log_bulk: (a: {
4018
+ entries: Value;
4019
+ connection?: Value;
4020
+ disabled?: boolean;
4021
+ description?: string;
4022
+ }) => Statement;
4023
+ metric: (a: {
4024
+ metric?: Value;
4025
+ value: Value;
4026
+ type?: "count" | "gauge" | "rate" | "histogram" | "distribution" | Value;
4027
+ tags?: Value;
4028
+ service?: Value;
4029
+ source?: Value;
4030
+ env?: Value;
4031
+ hostname?: Value;
4032
+ timestamp?: Value;
4033
+ connection?: Value;
4034
+ disabled?: boolean;
4035
+ description?: string;
4036
+ }) => Statement;
4037
+ metric_bulk: (a: {
4038
+ entries: Value;
4039
+ connection?: Value;
4040
+ disabled?: boolean;
4041
+ description?: string;
4042
+ }) => Statement;
4043
+ };
4044
+ readonly debug: {
4045
+ log: (a: {
4046
+ value: Value;
4047
+ disabled?: boolean;
4048
+ description?: string;
4049
+ }) => Statement;
4050
+ stop: (a: {
4051
+ value: Value;
4052
+ disabled?: boolean;
4053
+ description?: string;
4054
+ }) => Statement;
4055
+ };
4056
+ readonly math: {
4057
+ add: (a: {
4058
+ name?: string;
4059
+ value: Value;
4060
+ disabled?: boolean;
4061
+ description?: string;
4062
+ output?: OutputAuthored;
4063
+ }) => Statement;
4064
+ bitwise: {
4065
+ and: (a: {
4066
+ name?: string;
4067
+ value: Value;
4068
+ disabled?: boolean;
4069
+ description?: string;
4070
+ output?: OutputAuthored;
4071
+ }) => Statement;
4072
+ or: (a: {
4073
+ name?: string;
4074
+ value: Value;
4075
+ disabled?: boolean;
4076
+ description?: string;
4077
+ output?: OutputAuthored;
4078
+ }) => Statement;
4079
+ xor: (a: {
4080
+ name?: string;
4081
+ value: Value;
4082
+ disabled?: boolean;
4083
+ description?: string;
4084
+ output?: OutputAuthored;
4085
+ }) => Statement;
4086
+ };
4087
+ div: (a: {
4088
+ name?: string;
4089
+ value: Value;
4090
+ disabled?: boolean;
4091
+ description?: string;
4092
+ }) => Statement;
4093
+ mod: (a: {
4094
+ name?: string;
4095
+ value: Value;
4096
+ disabled?: boolean;
4097
+ description?: string;
4098
+ }) => Statement;
4099
+ mul: (a: {
4100
+ name?: string;
4101
+ value: Value;
4102
+ disabled?: boolean;
4103
+ description?: string;
4104
+ }) => Statement;
4105
+ sub: (a: {
4106
+ name?: string;
4107
+ value: Value;
4108
+ disabled?: boolean;
4109
+ description?: string;
4110
+ }) => Statement;
4111
+ };
4112
+ readonly object: {
4113
+ entries: (a?: {
4114
+ as?: string;
4115
+ value?: Value;
4116
+ disabled?: boolean;
4117
+ description?: string;
4118
+ asFilters?: FilterXdo[];
4119
+ output?: OutputAuthored;
4120
+ }) => Statement;
4121
+ keys: (a?: {
4122
+ as?: string;
4123
+ value?: Value;
4124
+ disabled?: boolean;
4125
+ description?: string;
4126
+ asFilters?: FilterXdo[];
4127
+ output?: OutputAuthored;
4128
+ }) => Statement;
4129
+ values: (a?: {
4130
+ as?: string;
4131
+ value?: Value;
4132
+ disabled?: boolean;
4133
+ description?: string;
4134
+ asFilters?: FilterXdo[];
4135
+ output?: OutputAuthored;
4136
+ }) => Statement;
4137
+ };
4138
+ readonly redis: {
4139
+ count: (a: {
4140
+ as?: string;
4141
+ key: Value;
4142
+ disabled?: boolean;
4143
+ description?: string;
4144
+ asFilters?: FilterXdo[];
4145
+ }) => Statement;
4146
+ decr: (a: {
4147
+ as?: string;
4148
+ key: Value;
4149
+ by?: Value;
4150
+ disabled?: boolean;
4151
+ description?: string;
4152
+ asFilters?: FilterXdo[];
4153
+ }) => Statement;
4154
+ del: (a: {
4155
+ key: Value;
4156
+ disabled?: boolean;
4157
+ description?: string;
4158
+ }) => Statement;
4159
+ get: (a: {
4160
+ as?: string;
4161
+ key: Value;
4162
+ disabled?: boolean;
4163
+ description?: string;
4164
+ asFilters?: FilterXdo[];
4165
+ }) => Statement;
4166
+ has: (a: {
4167
+ as?: string;
4168
+ key: Value;
4169
+ disabled?: boolean;
4170
+ description?: string;
4171
+ asFilters?: FilterXdo[];
4172
+ }) => Statement;
4173
+ incr: (a: {
4174
+ as?: string;
4175
+ key: Value;
4176
+ by?: Value;
4177
+ disabled?: boolean;
4178
+ description?: string;
4179
+ asFilters?: FilterXdo[];
4180
+ }) => Statement;
4181
+ keys: (a: {
4182
+ as?: string;
4183
+ search: Value;
4184
+ disabled?: boolean;
4185
+ description?: string;
4186
+ asFilters?: FilterXdo[];
4187
+ }) => Statement;
4188
+ pop: (a: {
4189
+ as?: string;
4190
+ key: Value;
4191
+ count?: Value;
4192
+ disabled?: boolean;
4193
+ description?: string;
4194
+ asFilters?: FilterXdo[];
4195
+ }) => Statement;
4196
+ push: (a: {
4197
+ as?: string;
4198
+ key: Value;
4199
+ value: Value;
4200
+ disabled?: boolean;
4201
+ description?: string;
4202
+ asFilters?: FilterXdo[];
4203
+ }) => Statement;
4204
+ range: (a: {
4205
+ as?: string;
4206
+ key: Value;
4207
+ start?: Value;
4208
+ stop?: Value;
4209
+ disabled?: boolean;
4210
+ description?: string;
4211
+ asFilters?: FilterXdo[];
4212
+ }) => Statement;
4213
+ ratelimit: (a: {
4214
+ as?: string;
4215
+ key: Value;
4216
+ max?: Value;
4217
+ ttl?: Value;
4218
+ error?: Value;
4219
+ disabled?: boolean;
4220
+ description?: string;
4221
+ asFilters?: FilterXdo[];
4222
+ }) => Statement;
4223
+ remove: (a: {
4224
+ as?: string;
4225
+ key: Value;
4226
+ value: Value;
4227
+ count?: Value;
4228
+ disabled?: boolean;
4229
+ description?: string;
4230
+ asFilters?: FilterXdo[];
4231
+ }) => Statement;
4232
+ set: (a: {
4233
+ as?: string;
4234
+ key: Value;
4235
+ data: Value;
4236
+ ttl?: Value;
4237
+ create_only?: Value;
4238
+ disabled?: boolean;
4239
+ description?: string;
4240
+ asFilters?: FilterXdo[];
4241
+ }) => Statement;
4242
+ shift: (a: {
4243
+ as?: string;
4244
+ key: Value;
4245
+ count?: Value;
4246
+ disabled?: boolean;
4247
+ description?: string;
4248
+ asFilters?: FilterXdo[];
4249
+ }) => Statement;
4250
+ unshift: (a: {
4251
+ as?: string;
4252
+ key: Value;
4253
+ value: Value;
4254
+ disabled?: boolean;
4255
+ description?: string;
4256
+ asFilters?: FilterXdo[];
4257
+ }) => Statement;
4258
+ };
4259
+ readonly text: {
4260
+ append: (a: {
4261
+ name?: string;
4262
+ value: Value;
4263
+ disabled?: boolean;
4264
+ description?: string;
4265
+ }) => Statement;
4266
+ contains: (a: {
4267
+ name?: string;
4268
+ as?: string;
4269
+ value: Value;
4270
+ disabled?: boolean;
4271
+ description?: string;
4272
+ asFilters?: FilterXdo[];
4273
+ }) => Statement;
4274
+ ends_with: (a: {
4275
+ name?: string;
4276
+ as?: string;
4277
+ value: Value;
4278
+ disabled?: boolean;
4279
+ description?: string;
4280
+ asFilters?: FilterXdo[];
4281
+ }) => Statement;
4282
+ icontains: (a: {
4283
+ name?: string;
4284
+ as?: string;
4285
+ value: Value;
4286
+ disabled?: boolean;
4287
+ description?: string;
4288
+ asFilters?: FilterXdo[];
4289
+ }) => Statement;
4290
+ iends_with: (a: {
4291
+ name?: string;
4292
+ as?: string;
4293
+ value: Value;
4294
+ disabled?: boolean;
4295
+ description?: string;
4296
+ asFilters?: FilterXdo[];
4297
+ }) => Statement;
4298
+ istarts_with: (a: {
4299
+ name?: string;
4300
+ as?: string;
4301
+ value: Value;
4302
+ disabled?: boolean;
4303
+ description?: string;
4304
+ asFilters?: FilterXdo[];
4305
+ }) => Statement;
4306
+ ltrim: (a: {
4307
+ name?: string;
4308
+ value: Value;
4309
+ disabled?: boolean;
4310
+ description?: string;
4311
+ }) => Statement;
4312
+ prepend: (a: {
4313
+ name?: string;
4314
+ value: Value;
4315
+ disabled?: boolean;
4316
+ description?: string;
4317
+ }) => Statement;
4318
+ rtrim: (a: {
4319
+ name?: string;
4320
+ value: Value;
4321
+ disabled?: boolean;
4322
+ description?: string;
4323
+ }) => Statement;
4324
+ starts_with: (a: {
4325
+ name?: string;
4326
+ as?: string;
4327
+ value: Value;
4328
+ disabled?: boolean;
4329
+ description?: string;
4330
+ asFilters?: FilterXdo[];
4331
+ }) => Statement;
4332
+ trim: (a: {
4333
+ name?: string;
4334
+ value: Value;
4335
+ disabled?: boolean;
4336
+ description?: string;
4337
+ }) => Statement;
4338
+ };
4339
+ readonly zip: {
4340
+ add_to_archive: (a: {
4341
+ file: Value;
4342
+ filename: Value;
4343
+ zip: Value;
4344
+ password?: Value;
4345
+ password_encryption?: Value;
4346
+ disabled?: boolean;
4347
+ description?: string;
4348
+ }) => Statement;
4349
+ create_archive: (a: {
4350
+ as?: string;
4351
+ filename: Value;
4352
+ password?: Value;
4353
+ password_encryption?: "standard" | "AES-128" | "AES-192" | "AES-256" | Value;
4354
+ disabled?: boolean;
4355
+ description?: string;
4356
+ asFilters?: FilterXdo[];
4357
+ }) => Statement;
4358
+ delete_from_archive: (a: {
4359
+ filename: Value;
4360
+ zip: Value;
4361
+ password?: Value;
4362
+ disabled?: boolean;
4363
+ description?: string;
4364
+ }) => Statement;
4365
+ extract: (a: {
4366
+ as?: string;
4367
+ zip: Value;
4368
+ password?: Value;
4369
+ disabled?: boolean;
4370
+ description?: string;
4371
+ asFilters?: FilterXdo[];
4372
+ }) => Statement;
4373
+ view_contents: (a: {
4374
+ as?: string;
4375
+ zip: Value;
4376
+ password?: Value;
4377
+ disabled?: boolean;
4378
+ description?: string;
4379
+ asFilters?: FilterXdo[];
4380
+ }) => Statement;
4381
+ };
4382
+ };
4383
+
4384
+ /**
4385
+ * Wide aliases for the def types that carry generics — the annotation that lets
4386
+ * a workspace be assembled out of independently-authored modules (issue #71).
4387
+ *
4388
+ * The problem is TypeScript's, not the SDK's. `register*` stores defs and does
4389
+ * not read their brands, so it takes them however they arrive. What fails is the
4390
+ * expression that BUILDS the array:
4391
+ *
4392
+ * ```ts
4393
+ * const modules = [catalogModule, chatModule];
4394
+ * workspace("app").registerTables(modules.flatMap((m) => m.tables)); // ✗ TS2322
4395
+ * ```
4396
+ *
4397
+ * `Array.prototype.flatMap` is declared `(cb: (…) => U | ReadonlyArray<U>)`, so
4398
+ * `U` binds to the FIRST element's table type and every later table is checked
4399
+ * against that one table's schema. The diagnostic is ~40 lines of expanded
4400
+ * generics ending in a comparison between two unrelated column names, and it
4401
+ * names neither `flatMap` nor the real cause. `.concat()` collapses the same way.
4402
+ *
4403
+ * Two spellings work. Annotate the module array with the wide alias:
4404
+ *
4405
+ * ```ts
4406
+ * const modules: { tables: readonly AnyTableDef[] }[] = [catalogModule, chatModule];
4407
+ * workspace("app").registerTables(modules.flatMap((m) => [...m.tables])); // ✓
4408
+ * ```
4409
+ *
4410
+ * …or skip the loop and let an array LITERAL infer the union across every
4411
+ * element at once, which is the documented form:
4412
+ *
4413
+ * ```ts
4414
+ * workspace("app").registerTables([...catalogModule.tables, ...chatModule.tables]); // ✓
4415
+ * ```
4416
+ *
4417
+ * Nothing is lost by widening here. The typing an author actually needs lives on
4418
+ * the `table()`/`query()` handle they hold and pass to `s.db.*` — it is never
4419
+ * read back off the registered array.
4420
+ *
4421
+ * Aliases exist for exactly the def types whose generics can collapse this way.
4422
+ * `ApiGroupDef`, `TaskDef`, `TriggerDef`, `MiddlewareDef` and the rest carry no
4423
+ * generics, so a heterogeneous array of them infers cleanly with no annotation.
4424
+ */
4425
+
4426
+ /** Any `table()` handle, whatever its schema — see the module note on `flatMap`. */
4427
+ type AnyTableDef = TableDef;
4428
+ /** Any `query()` handle, whatever its input, stack, response, or name. */
4429
+ type AnyQueryDef = QueryHandle;
4430
+ /** Any `defineFunction()` def, whatever its input, stack, or response. */
4431
+ type AnyFunctionDef = FunctionDef;
4432
+ /** Any `addon()` handle, whatever it grafts onto the row. */
4433
+ type AnyAddonDef = AddonDef;
4434
+
4435
+ /**
4436
+ * `compile()` — façade over the `function` object kind (KTD-2). The envelope
4437
+ * encoding now lives in `src/kinds/function.ts`; this keeps the MVP's public
4438
+ * `compile`/`encodeResponse` surface stable.
4439
+ */
4440
+
4441
+ /** Compile a `FunctionDef` into the flattened importable function `xdo`. */
4442
+ declare function compile(fn: FunctionDef): FunctionXdo;
4443
+
4444
+ /**
4445
+ * An input binding the engine SKIPS.
4446
+ *
4447
+ * A statement's `input[]` entry carries an `ignore` flag. When it is set the
4448
+ * engine records `"<name>:ignore"` and never binds the value at all, so the
4449
+ * parameter falls back to its declared default — which is NOT the same as
4450
+ * passing an empty value, and not the same as omitting the entry (the entry,
4451
+ * with its remembered value, is still stored).
4452
+ *
4453
+ * 1,766 real input entries carry it. The db row-write family already models it
4454
+ * as an `ignore` flag on a `data:` cell; this is the same state for the
4455
+ * spec-routed statements, whose fields are plain {@link Value}s with nowhere to
4456
+ * hang a flag.
4457
+ *
4458
+ * It applies to EVERY spec-routed statement, not only the handful whose stored
4459
+ * envelope spells the entry members out in full — the lean and full input forms
4460
+ * are two serializations of one entry model (issue #16).
4461
+ *
4462
+ * The marker is carried on a non-enumerable property, so it never reaches
4463
+ * `JSON.stringify` and an ignored value serializes exactly like the value it
4464
+ * wraps — the flag is read only by the input encoder, which moves it onto the
4465
+ * entry.
4466
+ */
4467
+
4468
+ /**
4469
+ * Mark an input binding as ignored — stored with its value, skipped at runtime.
4470
+ *
4471
+ * Recovery-oriented: `codegen` emits it for a stored `ignore: true` entry so a
4472
+ * pulled workspace reproduces its bytes. Authoring one by hand is legal and
4473
+ * means "keep this parameter's value on record, but do not send it".
4474
+ */
4475
+ declare function ignored(value: Value): Value;
4476
+
4477
+ export { type ActionCallArgs, type AddonCallArgs, AddonDef, type AddonSpec, type AgentRunResult, type AiAgentRunArgs, type AnyAddonDef, type AnyFunctionDef, type AnyQueryDef, type AnyTableDef, type ApiCallArgs, type ApplyFilter, type ApplyFilters, type ArrayMapArgs, type CloudJobArgs, type CloudJobAwaitArgs, type CloudJobStatusArgs, type CreateAuthTokenArgs, type DbAddArgs, type DbAddOrEditArgs, type DbAggregate, type DbAggregatePaging, type DbBind, type DbBulkAddArgs, type DbBulkDeleteArgs, type DbBulkWriteArgs, type DbDelArgs, type DbDirectQueryArgs, type DbDistinct, type DbEditArgs, DbEval, type DbExternal, type DbExternalPermissions, type DbExternalQueryArgs, type DbField, type DbGetArgs, type DbHasArgs, type DbJoin, type DbPaging, type DbPatchArgs, type DbQueryArgs, type DbResponseType, type DbReturnType, type DbSchemaArgs, type DbTransactionArgs, type DbTruncateArgs, DbWhere, type ExpectToThrowArgs, type ExternalSqlEngine, FilterXdo, FilteredValue, type ForArgs, type ForeachArgs, FromFieldMap, type FunctionCallArgs, FunctionDef, type FunctionRunArgs, FunctionXdo, type GetRawInputArgs, type HeaderMap, type HttpMethod, type InferInput, type InferResponse, InferRow, type IpLookupArgs, type IpLookupResult, MicroserviceDef, type MiddlewareCallArgs, ObjInput, ObjValue, ObjectRef, QueryHandle, type RealtimeEventArgs, RefValue, SortDirective, type StackTupleWidened, Statement, StatementAnnotations, StatementOptions, type SwitchArgs, type SwitchCaseArgs, TableDef, type TaskCallArgs, type ToolCallArgs, type TriggerCallArgs, type TryCatchArgs, Value, type WhileArgs, type WorkflowTestCallArgs, XanoFileRef, actionCall, actionPackageCall, addonCall, aiAgentRun, apiCall, arrayMap, arrayUnion, cloudJob, cloudJobAwait, cloudJobStatus, comment, compile, conditional, createAuthToken, dbAdd, dbAddOrEdit, dbBulkAdd, dbBulkDelete, dbBulkPatch, dbBulkUpdate, dbDel, dbDirectQuery, dbEdit, dbExternalQuery, dbGet, dbHas, dbPatch, dbQuery, dbSchema, dbTransaction, dbTruncate, debugLog, die, expectToThrow, fileUrl, forLoop, foreachBreak, foreachContinue, foreachLoop, foreachRemove, functionCall, functionRun, getRawInput, group, ignored, ipLookup, middlewareCall, postProcess, realtimeEvent, returnValue, s, setVar, switchCase, switchStatement, taskCall, toolCall, triggerCall, tryCatch, updateVar, whileLoop, workflowTestCall };