@query-farm/vgi 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/arrow/impl-arrowjs/index.d.ts +7 -0
  2. package/dist/arrow/impl-flechette/arrowjs-shape.d.ts +16 -0
  3. package/dist/arrow/impl-flechette/compat.d.ts +22 -0
  4. package/dist/arrow/impl-flechette/index.d.ts +2 -0
  5. package/dist/arrow/impl-flechette/ipc.d.ts +1 -1
  6. package/dist/arrow/index.d.ts +2 -2
  7. package/dist/arrow/predicates.d.ts +16 -0
  8. package/dist/cache-control.d.ts +33 -0
  9. package/dist/catalog/composite.d.ts +2 -0
  10. package/dist/catalog/interface.d.ts +11 -0
  11. package/dist/client-entry.js +9 -3
  12. package/dist/client-entry.js.map +7 -7
  13. package/dist/functions/registry.d.ts +31 -0
  14. package/dist/functions/scalar.d.ts +7 -3
  15. package/dist/generated/vgi-client.d.ts +16 -0
  16. package/dist/index.core.d.ts +2 -2
  17. package/dist/index.js +175 -19
  18. package/dist/index.js.map +19 -19
  19. package/dist/protocol/handlers/function.d.ts +8 -0
  20. package/dist/protocol/handlers/shared.d.ts +4 -0
  21. package/dist/protocol/types.d.ts +8 -0
  22. package/dist/serve-entry.js +40 -13
  23. package/dist/serve-entry.js.map +10 -10
  24. package/dist/util/arrow/index.d.ts +1 -1
  25. package/dist/worker-cf-entry.js +167 -17
  26. package/dist/worker-cf-entry.js.map +17 -17
  27. package/dist/worker.d.ts +9 -0
  28. package/package.json +5 -5
  29. package/src/arrow/impl-arrowjs/index.ts +10 -0
  30. package/src/arrow/impl-flechette/arrowjs-shape.ts +78 -0
  31. package/src/arrow/impl-flechette/canonical.ts +19 -0
  32. package/src/arrow/impl-flechette/compat.ts +254 -0
  33. package/src/arrow/impl-flechette/empty.ts +5 -1
  34. package/src/arrow/impl-flechette/index.ts +8 -0
  35. package/src/arrow/impl-flechette/ipc.ts +72 -6
  36. package/src/arrow/impl-flechette/normalize-type.ts +10 -2
  37. package/src/arrow/impl-flechette/schema.ts +13 -9
  38. package/src/arrow/index.ts +3 -0
  39. package/src/arrow/predicates.ts +59 -0
  40. package/src/cache-control.ts +35 -0
  41. package/src/catalog/composite.ts +9 -0
  42. package/src/catalog/interface.ts +15 -0
  43. package/src/catalog/read-only.ts +13 -0
  44. package/src/functions/registry.ts +127 -5
  45. package/src/functions/scalar.ts +10 -5
  46. package/src/generated/vgi-client.ts +17 -1
  47. package/src/index.core.ts +4 -0
  48. package/src/protocol/dispatch.ts +1 -0
  49. package/src/protocol/handlers/function.ts +38 -9
  50. package/src/protocol/handlers/shared.ts +25 -1
  51. package/src/protocol/serializers/bind.ts +7 -0
  52. package/src/protocol/types.ts +8 -0
  53. package/src/util/arrow/index.ts +1 -0
  54. package/src/worker.ts +15 -1
@@ -10,3 +10,10 @@ export { readCanonicalValue } from "./canonical.js";
10
10
  export { withBatchMetadata } from "./metadata.js";
11
11
  export { serializeSchema, deserializeSchema, serializeBatch, deserializeBatch, } from "./ipc.js";
12
12
  export { buildStatisticsBatch, type ColumnStatistics } from "./statistics.js";
13
+ /**
14
+ * No-op on this backend: arrow-js `RecordBatch`/`Vector` already expose the
15
+ * full API worker code uses, and arrow-js is a peer dependency, so there is
16
+ * only ever one copy. Present so both backends satisfy one facade interface —
17
+ * see impl-flechette/compat.ts for what this does there.
18
+ */
19
+ export declare function adoptArrowJsShape<T>(batch: T): T;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Attach `isSigned` to a flechette Int type, recursing through children /
3
+ * dictionary / index types.
4
+ *
5
+ * The alias is a non-enumerable getter so it never shows up in structural
6
+ * comparisons, IPC encoding or `Object.keys` — flechette keeps writing
7
+ * `signed`, and this is purely a read-side view of it. Mutating in place is
8
+ * safe: these objects are freshly built per decode.
9
+ */
10
+ export declare function aliasIntSigned<T>(type: T): T;
11
+ /**
12
+ * Bring a freshly decoded flechette schema up to the arrow-js shape shared
13
+ * code expects: every field (and nested child field) has a metadata `Map`,
14
+ * and every Int type answers to `isSigned`.
15
+ */
16
+ export declare function normalizeDecodedSchema<T>(schema: T): T;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Give a batch the arrow-js shape even when it was not built by our copy of
3
+ * flechette.
4
+ *
5
+ * The prototype patches above are scoped to one module instance. npm/bun will
6
+ * happily install a *second* copy of `@query-farm/flechette` — nested under
7
+ * `@query-farm/vgi-rpc`, say, whenever the two version ranges disagree even
8
+ * transiently — and then batches decoded off the wire by vgi-rpc are instances
9
+ * of classes our patches never touched. Worker code that has been calling
10
+ * `col.isValid(i)` happily for the whole bind phase suddenly gets
11
+ * `TypeError: col.isValid is not a function` on the first exchange round, with
12
+ * nothing in the stack to suggest the cause. That is not hypothetical: it took
13
+ * out four integration tests, and a duplicate copy is invisible to
14
+ * `bun install` output and to the lockfile, which lists flechette once.
15
+ *
16
+ * So rather than trusting module identity, patch whatever prototypes we are
17
+ * actually handed, once each. `adopted` keeps it to a WeakSet probe per call.
18
+ *
19
+ * Returns its argument (mutating prototypes, not the batch) so call sites can
20
+ * wrap inline.
21
+ */
22
+ export declare function adoptArrowJsShape<T>(batch: T): T;
@@ -1,4 +1,5 @@
1
1
  import type { VgiBackendInfo } from "../types.js";
2
+ import "./compat.js";
2
3
  export declare const backend: VgiBackendInfo;
3
4
  export { schema, field, nullType, bool, int, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float16, float32, float64, utf8, binary, fixedSizeBinary, decimal, decimal128, decimal256, date, dateDay, dateMillisecond, time, timeSecond, timeMillisecond, timeMicrosecond, timeNanosecond, timestamp, duration, interval, list, fixedSizeList, struct, map, dictionary, union, sparseUnion, denseUnion, TimeUnit, DateUnit, IntervalUnit, UnionMode, } from "./schema.js";
4
5
  export { emptyBatch } from "./empty.js";
@@ -10,3 +11,4 @@ export { readCanonicalValue } from "./canonical.js";
10
11
  export { withBatchMetadata } from "./metadata.js";
11
12
  export { serializeSchema, deserializeSchema, serializeBatch, deserializeBatch, } from "./ipc.js";
12
13
  export { buildStatisticsBatch, type ColumnStatistics } from "./statistics.js";
14
+ export { adoptArrowJsShape } from "./compat.js";
@@ -30,4 +30,4 @@ export declare function serializeBatch(batch: VgiBatch): Uint8Array;
30
30
  * multi-batch streams this collapses to a single logical batch, matching
31
31
  * the subprocess transport's one-batch-per-call convention.
32
32
  */
33
- export declare function deserializeBatch(bytes: Uint8Array): VgiBatch;
33
+ export declare function deserializeBatch(input: Uint8Array): VgiBatch;
@@ -1,6 +1,6 @@
1
1
  export type { VgiTypeId, VgiDataType, VgiField, VgiSchema, VgiColumn, VgiColumnData, VgiBatch, VgiBackendInfo, TaggedUnion, } from "./types.js";
2
- export { TypeId, isNull, isInt, isFloat, isBinary, isUtf8, isBool, isDecimal, isDate, isTime, isTimestamp, isInterval, isList, isStruct, isUnion, isFixedSizeBinary, isFixedSizeList, isMap, isDuration, isDictionary, isBatch, } from "./predicates.js";
3
- export { backend, emptyBatch, batchFromRows, batchFromColumns, columnFromArray, iterRows, batchToScalarDict, batchToSecretDict, safeNumber, decodeDictValue, filterBatch, projectSchema, projectBatch, withBatchMetadata, readCanonicalValue, serializeSchema, deserializeSchema, serializeBatch, deserializeBatch, buildStatisticsBatch, } from "#arrow-impl";
2
+ export { TypeId, isNull, isInt, isFloat, isBinary, isUtf8, isBool, isDecimal, isDate, isTime, isTimestamp, isInterval, isList, isStruct, isUnion, isFixedSizeBinary, isFixedSizeList, isMap, isDuration, isDictionary, isBatch, typeSignature, } from "./predicates.js";
3
+ export { backend, emptyBatch, batchFromRows, batchFromColumns, columnFromArray, iterRows, batchToScalarDict, batchToSecretDict, safeNumber, decodeDictValue, filterBatch, projectSchema, projectBatch, withBatchMetadata, adoptArrowJsShape, readCanonicalValue, serializeSchema, deserializeSchema, serializeBatch, deserializeBatch, buildStatisticsBatch, } from "#arrow-impl";
4
4
  export type { ColumnStatistics } from "#arrow-impl";
5
5
  export { schema, field, nullType, bool, int, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float16, float32, float64, utf8, binary, fixedSizeBinary, decimal, decimal128, decimal256, date, dateDay, dateMillisecond, time, timeSecond, timeMillisecond, timeMicrosecond, timeNanosecond, timestamp, duration, interval, timestampSeconds, timestampMillis, timestampMicros, timestampNanos, durationSeconds, durationMillis, durationMicros, durationNanos, list, fixedSizeList, struct, map, dictionary, union, sparseUnion, denseUnion, TimeUnit, DateUnit, IntervalUnit, UnionMode, } from "./schema-types.js";
6
6
  export type { NullDescriptor, BoolType, IntType, Int8Type, Int16Type, Int32Type, Int64Type, Uint8Type, Uint16Type, Uint32Type, Uint64Type, FloatType, Utf8Type, LargeUtf8Type, BinaryType, LargeBinaryType, FixedSizeBinaryType, DecimalType, Date32Type, Date64Type, Time32Type, Time64Type, TimestampType, DurationType, IntervalType, ListType, FixedSizeListType, StructType, MapType, DictionaryType, UnionType, TypedField, TUnit, } from "./codec/type-descriptors.js";
@@ -41,6 +41,22 @@ export declare function isFixedSizeList(t: VgiDataType): boolean;
41
41
  export declare function isMap(t: VgiDataType): boolean;
42
42
  export declare function isDuration(t: VgiDataType): boolean;
43
43
  export declare function isDictionary(t: VgiDataType): boolean;
44
+ /**
45
+ * Stable structural identity for an Arrow type, usable for equality.
46
+ *
47
+ * `String(type)` is NOT usable for this: arrow-js DataTypes are class
48
+ * instances with a meaningful `toString()` ("Int64", "Utf8", …), while
49
+ * flechette types are plain object literals that stringify to
50
+ * "[object Object]". Comparing with `toString()` therefore reports *every*
51
+ * flechette type as equal to every other, and never equal to a declared
52
+ * arrow-js type — which collapsed overload resolution to a first-match tie
53
+ * (`type_info(42::BIGINT)` picked the INTEGER overload).
54
+ *
55
+ * Both libraries agree on `typeId` and on the parameter *values*; they differ
56
+ * only on a few property names, so those are read under both spellings. The
57
+ * output is an opaque key — compare it, don't display it.
58
+ */
59
+ export declare function typeSignature(t: VgiDataType | null | undefined): string;
44
60
  /** Runtime check: does `x` quack like a VgiBatch? Used at API boundaries
45
61
  * where callers may pass either a batch or a plain column dict. Duck-typed
46
62
  * because arrow-js and flechette use unrelated classes. */
@@ -35,6 +35,8 @@ export declare const CACHE_REVALIDATABLE_KEY = "vgi.cache.revalidatable";
35
35
  export declare const CACHE_STALE_WHILE_REVALIDATE_KEY = "vgi.cache.stale_while_revalidate";
36
36
  export declare const CACHE_STALE_IF_ERROR_KEY = "vgi.cache.stale_if_error";
37
37
  export declare const CACHE_NOT_MODIFIED_KEY = "vgi.cache.not_modified";
38
+ export declare const CACHE_PARTITION_SCOPE_KEY = "vgi.cache.partition_scope";
39
+ export declare const CACHE_PER_VALUE_KEY = "vgi.cache.per_value";
38
40
  export declare const CACHE_IF_NONE_MATCH_KEY = "vgi.cache.if_none_match";
39
41
  export declare const CACHE_IF_MODIFIED_SINCE_KEY = "vgi.cache.if_modified_since";
40
42
  export declare const CACHE_SCOPE_CATALOG = "catalog";
@@ -75,6 +77,37 @@ export interface CacheControl {
75
77
  * assert the client's stored payload is still fresh (the client reuses it
76
78
  * instead of re-streaming). */
77
79
  notModified?: boolean;
80
+ /** Opt in to per-PARTITION caching: in addition to the whole-scan entry, the
81
+ * client stores the result split by distinct partition tuple, so a later
82
+ * `=`/`IN`-filtered scan on the partition column(s) can serve the requested
83
+ * partitions without calling the worker. Only meaningful for a
84
+ * `SINGLE_VALUE_PARTITIONS` table function; purely additive. */
85
+ partitionScope?: boolean;
86
+ /**
87
+ * Opt in to per-VALUE memoization: in addition to the whole-result entry, the
88
+ * client memoizes each distinct worker-input tuple's output keyed on that
89
+ * tuple, so the same value is served without calling the worker on a later
90
+ * chunk or a later query. Only meaningful for an exchange-mode MAP — a
91
+ * scalar, or a blended table-in-out invoked through a correlated `LATERAL`.
92
+ *
93
+ * **Default off, and it should stay off unless one call is genuinely
94
+ * expensive.** This is not a free win: serving a value from the memo costs a
95
+ * key probe, a decode and a per-value assembly step, and that only pays back
96
+ * when it is cheaper than asking you for the answer. For a cheap map —
97
+ * arithmetic, a string tweak, a lookup in a table the worker already has in
98
+ * memory — it is a large net loss (the engine measures a per-value serve at
99
+ * roughly 50x the cost of just calling the worker for a simple arithmetic
100
+ * map). Only the function author knows which side of that line a call falls
101
+ * on, which is why the engine will not guess: turn it on for model
102
+ * inference, geocoding, an external API call, or anything rate-limited or
103
+ * billed per request.
104
+ *
105
+ * Independent of freshness: `ttl`/`expires` make a result cacheable at all,
106
+ * while this decides whether the per-value tier is additionally populated.
107
+ * Requires a deterministic, side-effect-free function, exactly like the rest
108
+ * of the result cache.
109
+ */
110
+ perValue?: boolean;
78
111
  }
79
112
  /**
80
113
  * Render a {@link CacheControl} to the `vgi.cache.*` batch-metadata map.
@@ -4,6 +4,8 @@ export declare class CompositeCatalogInterface extends CatalogInterface {
4
4
  private readonly _backends;
5
5
  constructor(_backends: CatalogInterface[]);
6
6
  private _route;
7
+ /** Route to the owning backend and ask it, so the answer is per-attachment. */
8
+ catalogNameForAttach(attachOpaqueData: Uint8Array): string | null;
7
9
  catalogs(): string[];
8
10
  catalogsInfo(): Promise<CatalogInfo[]>;
9
11
  attach(name: string, options?: Record<string, unknown>, dataVersionSpec?: string | null, implementationVersion?: string | null): Promise<CatalogAttachResult>;
@@ -180,6 +180,17 @@ export declare function buildScanBranchesResult(branches: ScanBranchInput[], req
180
180
  */
181
181
  type Awaitable<T> = T | Promise<T>;
182
182
  export declare abstract class CatalogInterface {
183
+ /**
184
+ * Which catalog an `attach_opaque_data` belongs to, or null if unknown.
185
+ *
186
+ * Two catalogs served by one worker may declare the same schema *and*
187
+ * function name, in which case the attachment is the only thing that tells
188
+ * them apart — the bind path uses this to scope function resolution. The
189
+ * default answers from `catalogs()` when this interface owns exactly one,
190
+ * which is right for every single-catalog implementation; the composite
191
+ * overrides it to route by its backend index byte.
192
+ */
193
+ catalogNameForAttach(_attachOpaqueData: Uint8Array): string | null;
183
194
  abstract catalogs(): string[];
184
195
  /**
185
196
  * Attach this catalog. The framework already validates ATTACH options
@@ -122,6 +122,7 @@ __export(exports_impl_arrowjs, {
122
122
  batchFromRows: () => batchFromRows,
123
123
  batchFromColumns: () => batchFromColumns,
124
124
  backend: () => backend,
125
+ adoptArrowJsShape: () => adoptArrowJsShape,
125
126
  UnionMode: () => UnionMode,
126
127
  TimeUnit: () => TimeUnit,
127
128
  IntervalUnit: () => IntervalUnit,
@@ -1758,6 +1759,9 @@ function assemble(columnNames, minData, maxData, hasNull, hasNotNull, distinctCo
1758
1759
 
1759
1760
  // src/arrow/impl-arrowjs/index.ts
1760
1761
  var backend = { name: "arrow-js" };
1762
+ function adoptArrowJsShape(batch) {
1763
+ return batch;
1764
+ }
1761
1765
  // src/arrow/schema-types.ts
1762
1766
  var { TimeUnit: TimeUnit2, DateUnit: DateUnit3, IntervalUnit: IntervalUnit2, UnionMode: UnionMode2, schema: schema2 } = exports_impl_arrowjs;
1763
1767
  function field2(name, type, nullable, metadata) {
@@ -2000,7 +2004,8 @@ var BIND_REQUEST_SCHEMA = schema2([
2000
2004
  field2("transaction_opaque_data", binary2(), true),
2001
2005
  field2("resolved_secrets_provided", bool2(), false),
2002
2006
  field2("at_unit", utf82(), true),
2003
- field2("at_value", utf82(), true)
2007
+ field2("at_value", utf82(), true),
2008
+ field2("schema_name", utf82(), true)
2004
2009
  ]);
2005
2010
  var COPY_FROM_STRUCT_TYPE = struct2([
2006
2011
  field2("format", utf82(), false),
@@ -2032,7 +2037,8 @@ function serializeBindRequest(req) {
2032
2037
  transaction_opaque_data: req.transaction_opaque_data ?? null,
2033
2038
  resolved_secrets_provided: req.resolved_secrets_provided ?? false,
2034
2039
  at_unit: req.at_unit ?? null,
2035
- at_value: req.at_value ?? null
2040
+ at_value: req.at_value ?? null,
2041
+ schema_name: req.schema_name ?? null
2036
2042
  };
2037
2043
  const extraFields = [];
2038
2044
  if (req.copy_from) {
@@ -3917,4 +3923,4 @@ export {
3917
3923
  ArgumentValidationError
3918
3924
  };
3919
3925
 
3920
- //# debugId=7B4A06FF3B2070C464756E2164756E21
3926
+ //# debugId=FCC2DEE998E0D9AC64756E2164756E21