bonsai-js 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -5
- package/README.md +211 -8
- package/dist/autocomplete/index.d.mts +47 -0
- package/dist/autocomplete/index.d.mts.map +1 -0
- package/dist/autocomplete/index.mjs +1038 -0
- package/dist/autocomplete/index.mjs.map +1 -0
- package/dist/{errors-t5i9AEaf.mjs → errors-BONB6P_5.mjs} +2 -3
- package/dist/{errors-t5i9AEaf.mjs.map → errors-BONB6P_5.mjs.map} +1 -1
- package/dist/execution-context-B-5hQ92X.mjs +564 -0
- package/dist/execution-context-B-5hQ92X.mjs.map +1 -0
- package/dist/index.d.mts +16 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +148 -601
- package/dist/index.mjs.map +1 -1
- package/dist/stdlib/index.d.mts +1 -1
- package/dist/stdlib/index.mjs +1 -1
- package/dist/stdlib/index.mjs.map +1 -1
- package/dist/{types-ClpZDF5z.d.mts → types-C58c6SlH.d.mts} +73 -16
- package/dist/types-C58c6SlH.d.mts.map +1 -0
- package/package.json +6 -2
- package/dist/types-ClpZDF5z.d.mts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,61 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.4.0] - 2026-06-02
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Context-aware functions** (`addContextFunction`): register functions that receive the evaluation context as their first parameter (typed `Readonly<TCtx>`, passed by reference), enabling auth/permission/personalization patterns without threading context through expression arguments. Pure and context-aware functions share a single namespace; `isContextFunction(name)` introspects the kind.
|
|
15
|
+
- **Generic context typing** (`bonsai<TCtx>()`): the factory is now generic over context type, with end-to-end type safety through `evaluate`, `evaluateSync`, `compile`, and `addContextFunction`. Backward compatible: defaults to `Record<string, unknown>` when unspecified.
|
|
16
|
+
- New exported types: `ContextFunctionFn`, generic `BonsaiPlugin<TCtx>`, generic `CompiledExpression<TCtx>`, generic `BonsaiInstance<TCtx>`.
|
|
17
|
+
- Internal: pure and context-aware functions share one tagged registry, and the cached `Bindings` snapshot consolidates transforms and that registry into a single object passed to the evaluator.
|
|
18
|
+
|
|
19
|
+
### Resolves
|
|
20
|
+
|
|
21
|
+
- #33: context access from registered functions.
|
|
22
|
+
|
|
23
|
+
### Credits
|
|
24
|
+
|
|
25
|
+
- Thanks to @jaenyf for raising #33 and contributing PR #34.
|
|
26
|
+
|
|
27
|
+
## [0.3.0] - 2026-03-21
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- **Autocomplete API** (`bonsai-js/autocomplete`): cursor-aware expression completions with property, method, transform, function, and keyword suggestions
|
|
32
|
+
- `getPolicy()` method on `BonsaiInstance` for reading security policy
|
|
33
|
+
- `InferredTypeName`, `PolicySnapshot`, `ResolveResult` shared types
|
|
34
|
+
- Tolerant tokenization for incomplete expressions with regex fallback
|
|
35
|
+
- Type inference from sample context objects with array element type detection
|
|
36
|
+
- Lambda-aware dot classification (lambda-start, lambda member-access, top-level member-access)
|
|
37
|
+
- Security policy filtering in completions (respects allowedProperties/deniedProperties in all paths)
|
|
38
|
+
- Optional chaining (`?.`) support in completions
|
|
39
|
+
- Fuzzy matching with camelCase-aware scoring
|
|
40
|
+
- `onError` callback for debugging autocomplete failures
|
|
41
|
+
- `transformTypes` option to skip auto-probing for performance
|
|
42
|
+
- Eval-based type inference for method chains (e.g., `user.name.trim().`)
|
|
43
|
+
- Nested lambda element inference (e.g., `groups.map(.users.filter(.`)
|
|
44
|
+
- Pre-computed method completion cache for fast method suggestions
|
|
45
|
+
- Autocomplete benchmarks (`benchmarks/autocomplete.bench.ts`)
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- **Performance**: core `evaluateSync` 1.4–2.4x faster (LRU cache fast path, pooled ExecutionContext, leaf node fast path)
|
|
50
|
+
- **Performance**: autocomplete method completions 3–4x faster via pre-computed completion objects
|
|
51
|
+
- LRU cache uses `lastKey` tracking to skip reordering on repeated hits
|
|
52
|
+
- `ExecutionContext` reusable via `reset()` — avoids per-call allocation in `evaluateSync`
|
|
53
|
+
- Leaf AST nodes (literals, identifiers) skip depth tracking overhead in both sync and async evaluators
|
|
54
|
+
|
|
55
|
+
### Security
|
|
56
|
+
|
|
57
|
+
- Transform names validated as safe identifiers before `evaluateSync` interpolation
|
|
58
|
+
- `resolvePropertyChain` enforces `allowedProperties`/`deniedProperties` policy at every chain step
|
|
59
|
+
- `BLOCKED_NAMES` unified with `BLOCKED_PROPERTIES` from execution context (single source of truth)
|
|
60
|
+
- Catch blocks use `isExpectedError()` checking all 4 Bonsai error types — unexpected errors surface via `onError`
|
|
61
|
+
- Top-level `complete()` catches unexpected errors and returns `[]` (never crashes host)
|
|
62
|
+
|
|
8
63
|
## [0.2.1] - 2026-03-16
|
|
9
64
|
|
|
10
65
|
### Added
|
|
@@ -22,11 +77,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
22
77
|
- **Bare dot identity lambda:** `. > 2` and `. * 10` now work as lambda shorthand for the current item itself, in both method calls and pipe transforms (e.g., `[1,2,3,4].filter(. > 2)`, `[1,2,3] |> map(. * 10)`)
|
|
23
78
|
- Async-safe evaluation for all higher-order array methods — lambda predicates that return Promises are correctly resolved in both top-level and nested contexts via `evaluate()`
|
|
24
79
|
- Documentation for array methods, lambda shorthand, and method chaining in README and website docs
|
|
25
|
-
|
|
26
|
-
## [Unreleased]
|
|
27
|
-
|
|
28
|
-
### Added
|
|
29
|
-
|
|
30
80
|
- Deterministic property-based parser and evaluator invariant tests
|
|
31
81
|
- Random fuzz coverage for malformed parser input
|
|
32
82
|
- Adversarial regression tests for deep nesting, oversized arrays, nested blocked keys, and spread misuse
|
package/README.md
CHANGED
|
@@ -125,6 +125,58 @@ expr.addFunction('lookupTier', async (userId) => {
|
|
|
125
125
|
await expr.evaluate('lookupTier(userId) == "pro"', { userId: 'u_123' })
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
+
### Context-aware functions
|
|
129
|
+
|
|
130
|
+
Register functions that read the evaluation context directly. The function
|
|
131
|
+
receives the evaluation context as its first parameter (typed read-only), so
|
|
132
|
+
you can keep expressions terse and let the function pull what it needs:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { bonsai } from 'bonsai-js'
|
|
136
|
+
|
|
137
|
+
interface AppContext {
|
|
138
|
+
currentUserId: string
|
|
139
|
+
perms: readonly string[]
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const app = bonsai<AppContext>()
|
|
143
|
+
|
|
144
|
+
app.addContextFunction('lookupCurrentUserTier', async (ctx) => {
|
|
145
|
+
const row = await db.users.findById(ctx.currentUserId)
|
|
146
|
+
return row?.tier ?? 'free'
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
app.addContextFunction('hasPermission', (ctx, action) =>
|
|
150
|
+
ctx.perms.includes(String(action)))
|
|
151
|
+
|
|
152
|
+
await app.evaluate(
|
|
153
|
+
'lookupCurrentUserTier() == "pro" && hasPermission("admin")',
|
|
154
|
+
{ currentUserId: 'u_123', perms: ['admin', 'write'] },
|
|
155
|
+
)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The instance is generic over the context type (`bonsai<AppContext>()`), giving
|
|
159
|
+
you end-to-end type safety: `ctx` is typed inside the function, and the call
|
|
160
|
+
site is type-checked against the same shape. If your context type has required
|
|
161
|
+
fields, TypeScript also requires you to pass the `context` argument to
|
|
162
|
+
`evaluate`, `evaluateSync`, and compiled-expression evaluation.
|
|
163
|
+
|
|
164
|
+
The context is passed to your function by reference, not copied or frozen. The
|
|
165
|
+
`Readonly<TCtx>` parameter type signals that you should treat it as read-only:
|
|
166
|
+
TypeScript flags reassigning its top-level fields. Bonsai does not deep-freeze
|
|
167
|
+
it, so nested mutation and writes from untyped JavaScript reach the object you
|
|
168
|
+
passed in. If you need isolation between evaluations, pass a fresh context
|
|
169
|
+
object each time.
|
|
170
|
+
|
|
171
|
+
Pure functions (`addFunction`) and context-aware functions (`addContextFunction`)
|
|
172
|
+
share a single namespace. Registering the same name with either method
|
|
173
|
+
overwrites the prior registration, so re-registering a context-aware name with
|
|
174
|
+
`addFunction` turns it back into a pure function (check `isContextFunction(name)`
|
|
175
|
+
if the kind matters). Functions registered with `addFunction` never receive the
|
|
176
|
+
context; reach for `addContextFunction` when a function needs it. Plugins typed
|
|
177
|
+
against a minimal context requirement can still be applied to instances with a
|
|
178
|
+
wider context shape.
|
|
179
|
+
|
|
128
180
|
### Editor validation
|
|
129
181
|
|
|
130
182
|
```ts
|
|
@@ -361,20 +413,25 @@ evaluateExpression<number>('x * 2', { x: 21 }) // 42
|
|
|
361
413
|
## Instance Methods
|
|
362
414
|
|
|
363
415
|
```ts
|
|
364
|
-
|
|
365
|
-
|
|
416
|
+
type EvaluationContextArgs<TCtx extends object = Record<string, unknown>> =
|
|
417
|
+
{} extends TCtx ? [context?: TCtx] : [context: TCtx]
|
|
418
|
+
|
|
419
|
+
interface BonsaiInstance<TCtx extends object = Record<string, unknown>> {
|
|
420
|
+
use(plugin: BonsaiPlugin<TCtx>): this
|
|
366
421
|
addTransform(name: string, fn: TransformFn): this
|
|
367
422
|
addFunction(name: string, fn: FunctionFn): this
|
|
423
|
+
addContextFunction(name: string, fn: ContextFunctionFn<TCtx>): this
|
|
368
424
|
removeTransform(name: string): boolean
|
|
369
425
|
removeFunction(name: string): boolean
|
|
370
426
|
hasTransform(name: string): boolean
|
|
371
427
|
hasFunction(name: string): boolean
|
|
428
|
+
isContextFunction(name: string): boolean
|
|
372
429
|
listTransforms(): string[]
|
|
373
430
|
listFunctions(): string[]
|
|
374
431
|
clearCache(): void
|
|
375
|
-
compile(expression: string): CompiledExpression
|
|
376
|
-
evaluate<T = unknown>(expression: string,
|
|
377
|
-
evaluateSync<T = unknown>(expression: string,
|
|
432
|
+
compile(expression: string): CompiledExpression<TCtx>
|
|
433
|
+
evaluate<T = unknown>(expression: string, ...args: EvaluationContextArgs<TCtx>): Promise<T>
|
|
434
|
+
evaluateSync<T = unknown>(expression: string, ...args: EvaluationContextArgs<TCtx>): T
|
|
378
435
|
validate(expression: string): ValidationResult
|
|
379
436
|
}
|
|
380
437
|
```
|
|
@@ -382,9 +439,12 @@ interface BonsaiInstance {
|
|
|
382
439
|
Method notes:
|
|
383
440
|
|
|
384
441
|
- `use()` runs a plugin immediately and returns the same instance.
|
|
385
|
-
- `addTransform()` and `
|
|
386
|
-
- `
|
|
442
|
+
- `addTransform()`, `addFunction()`, and `addContextFunction()` overwrite any existing registration with the same name. Pure and context-aware functions share a single namespace.
|
|
443
|
+
- `addContextFunction()` registers a function that receives the live evaluation context as its first argument (typed read-only; passed by reference, not copied or frozen). See [Context-aware functions](#context-aware-functions).
|
|
444
|
+
- `isContextFunction()` returns `true` if the named function was registered via `addContextFunction()`.
|
|
445
|
+
- `listTransforms()` and `listFunctions()` return the currently registered names. `listFunctions()` includes both pure and context-aware functions.
|
|
387
446
|
- `clearCache()` clears the internal AST cache and compiled-expression cache. It does not remove registered transforms/functions.
|
|
447
|
+
- Pass a context type generic to `bonsai<MyContext>()` for end-to-end type safety: `evaluate`, `evaluateSync`, `addContextFunction`, `compile`, and `use` all propagate the type. If `MyContext` has required fields, TypeScript requires a context argument when evaluating.
|
|
388
448
|
|
|
389
449
|
## Extending the Runtime
|
|
390
450
|
|
|
@@ -578,9 +638,152 @@ Bonsai is optimized for repeated evaluation.
|
|
|
578
638
|
|
|
579
639
|
Benchmark guidance and current numbers live in the website docs and benchmark suite. Treat raw benchmark numbers as directional, not part of the API contract.
|
|
580
640
|
|
|
641
|
+
## Autocomplete
|
|
642
|
+
|
|
643
|
+
Bonsai ships a cursor-aware autocomplete engine at `bonsai-js/autocomplete`. It provides ranked, type-aware completion suggestions for any cursor position in an expression — designed for rule builders, expression editors, and admin tools. Tree-shakeable: if you don't import it, it's not in your bundle.
|
|
644
|
+
|
|
645
|
+
```ts
|
|
646
|
+
import { bonsai } from 'bonsai-js'
|
|
647
|
+
import { strings, arrays } from 'bonsai-js/stdlib'
|
|
648
|
+
import { createAutocomplete } from 'bonsai-js/autocomplete'
|
|
649
|
+
|
|
650
|
+
const expr = bonsai().use(strings).use(arrays)
|
|
651
|
+
|
|
652
|
+
const ac = createAutocomplete(expr, {
|
|
653
|
+
context: { user: { name: 'Alice', age: 25 }, items: [1, 2, 3] },
|
|
654
|
+
})
|
|
655
|
+
|
|
656
|
+
ac.complete('user.', 5)
|
|
657
|
+
// [{ label: 'name', detail: 'string', kind: 'property' },
|
|
658
|
+
// { label: 'age', detail: 'number', kind: 'property' }, ...]
|
|
659
|
+
|
|
660
|
+
ac.complete('user.name.', 10)
|
|
661
|
+
// [{ label: 'trim', detail: 'string → string', insertText: 'trim()', cursorOffset: 5 },
|
|
662
|
+
// { label: 'toUpperCase', detail: 'string → string' }, ...]
|
|
663
|
+
|
|
664
|
+
ac.complete('items |> ', 9)
|
|
665
|
+
// Only array-compatible transforms — string-only transforms automatically excluded.
|
|
666
|
+
|
|
667
|
+
ac.complete('users.filter(.', 14)
|
|
668
|
+
// [{ label: 'name', detail: 'string' }, { label: 'age', detail: 'number' }]
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
### What it provides
|
|
672
|
+
|
|
673
|
+
| Context | What you get |
|
|
674
|
+
|---|---|
|
|
675
|
+
| `user.` | Object properties with value types |
|
|
676
|
+
| `user?.name?.` | Optional chaining — same completions as dot access |
|
|
677
|
+
| `user.name.` | Type-appropriate methods with return types |
|
|
678
|
+
| `user.name.trim().` | Methods inferred through chained calls (eval-based) |
|
|
679
|
+
| `user.name.to` | Fuzzy-filtered methods via static type inference |
|
|
680
|
+
| `items \|> ` | Transforms filtered by inferred input type |
|
|
681
|
+
| `users.filter(.` | Lambda element properties with types |
|
|
682
|
+
| `users.filter(.name.` | Lambda member — methods for the element property type |
|
|
683
|
+
| `groups.map(.users.filter(.` | Nested lambda element inference |
|
|
684
|
+
| `us` | Context variables, functions, keywords |
|
|
685
|
+
| `name.tLC` | Fuzzy matching (camelCase-aware) |
|
|
686
|
+
|
|
687
|
+
### How to integrate
|
|
688
|
+
|
|
689
|
+
The API returns pure data — no DOM, no framework dependency. Wire it into any UI:
|
|
690
|
+
|
|
691
|
+
```ts
|
|
692
|
+
// Custom dropdown
|
|
693
|
+
textarea.addEventListener('input', () => {
|
|
694
|
+
ac.setContext(getCurrentContext())
|
|
695
|
+
const completions = ac.complete(textarea.value, textarea.selectionStart)
|
|
696
|
+
showDropdown(completions)
|
|
697
|
+
})
|
|
698
|
+
|
|
699
|
+
// Monaco editor
|
|
700
|
+
const monacoKindMap = {
|
|
701
|
+
variable: monaco.languages.CompletionItemKind.Variable,
|
|
702
|
+
property: monaco.languages.CompletionItemKind.Property,
|
|
703
|
+
method: monaco.languages.CompletionItemKind.Method,
|
|
704
|
+
transform: monaco.languages.CompletionItemKind.Function,
|
|
705
|
+
function: monaco.languages.CompletionItemKind.Function,
|
|
706
|
+
keyword: monaco.languages.CompletionItemKind.Keyword,
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
monaco.languages.registerCompletionItemProvider('bonsai', {
|
|
710
|
+
triggerCharacters: ['.', '|', '('],
|
|
711
|
+
provideCompletionItems(model, position) {
|
|
712
|
+
ac.setContext(getCurrentContext())
|
|
713
|
+
const offset = model.getOffsetAt(position)
|
|
714
|
+
return {
|
|
715
|
+
suggestions: ac.complete(model.getValue(), offset).map(c => ({
|
|
716
|
+
label: c.label,
|
|
717
|
+
kind: monacoKindMap[c.kind],
|
|
718
|
+
insertText: c.insertText ?? c.label,
|
|
719
|
+
detail: c.detail,
|
|
720
|
+
})),
|
|
721
|
+
}
|
|
722
|
+
},
|
|
723
|
+
})
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
Context can be updated dynamically — call `ac.setContext(newData)` whenever the user's data changes.
|
|
727
|
+
|
|
728
|
+
### Options
|
|
729
|
+
|
|
730
|
+
```ts
|
|
731
|
+
createAutocomplete(instance, {
|
|
732
|
+
// Expression evaluation context — the data your users are writing expressions against
|
|
733
|
+
context: { user: { name: 'Alice' }, items: [1, 2, 3] },
|
|
734
|
+
|
|
735
|
+
// Explicit transform type map — skips auto-probing for better performance.
|
|
736
|
+
// Keys are transform names, values are arrays of accepted input types.
|
|
737
|
+
// When omitted, types are discovered automatically by probing each transform.
|
|
738
|
+
transformTypes: {
|
|
739
|
+
upper: ['string'],
|
|
740
|
+
trim: ['string'],
|
|
741
|
+
count: ['array'],
|
|
742
|
+
sort: ['array'],
|
|
743
|
+
},
|
|
744
|
+
|
|
745
|
+
// Error callback for debugging missing or incorrect completions.
|
|
746
|
+
// Only called for unexpected internal errors — not for expected parse/eval failures.
|
|
747
|
+
onError: (error, phase) => console.warn(`[autocomplete] ${phase}:`, error),
|
|
748
|
+
})
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
### Security policy
|
|
752
|
+
|
|
753
|
+
Autocomplete respects the same `allowedProperties` and `deniedProperties` policy configured on the Bonsai instance. Completions are filtered to match what the evaluator would actually allow:
|
|
754
|
+
|
|
755
|
+
```ts
|
|
756
|
+
const expr = bonsai({ allowedProperties: ['name', 'age'] })
|
|
757
|
+
const ac = createAutocomplete(expr, {
|
|
758
|
+
context: { user: { name: 'Alice', secret: 'hidden' } },
|
|
759
|
+
})
|
|
760
|
+
|
|
761
|
+
ac.complete('user.', 5)
|
|
762
|
+
// 'secret' is excluded — only 'name' and 'age' appear
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
This applies to all contexts: property access, lambda element properties, and nested chain resolution. Methods (`trim`, `filter`, etc.) are always shown for their applicable types — they are controlled by `deniedProperties`, not `allowedProperties`.
|
|
766
|
+
|
|
767
|
+
### Completion type
|
|
768
|
+
|
|
769
|
+
```ts
|
|
770
|
+
interface Completion {
|
|
771
|
+
label: string // Display text and default insert text
|
|
772
|
+
kind: 'variable' | 'property' | 'method' | 'transform' | 'function' | 'keyword'
|
|
773
|
+
detail?: string // Type info: 'string', 'string → array', '"Alice"', 'array(3)'
|
|
774
|
+
insertText?: string // Override insert: 'trim()', 'filter(.)', 'min()'
|
|
775
|
+
cursorOffset?: number // Cursor position in insertText (e.g., between parens)
|
|
776
|
+
sortPriority: number // Lower = higher rank
|
|
777
|
+
}
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
### Error handling
|
|
781
|
+
|
|
782
|
+
`complete()` never throws — it always returns `Completion[]`. If an unexpected internal error occurs, it returns `[]` and reports the error via the `onError` callback. Expected errors (syntax errors from incomplete expressions, security policy blocks, type mismatches) are silently handled as part of normal autocomplete operation.
|
|
783
|
+
|
|
581
784
|
## Stability
|
|
582
785
|
|
|
583
|
-
Bonsai follows SemVer for the documented package entrypoints `bonsai-js` and `bonsai-js/
|
|
786
|
+
Bonsai follows SemVer for the documented package entrypoints `bonsai-js`, `bonsai-js/stdlib`, and `bonsai-js/autocomplete`.
|
|
584
787
|
|
|
585
788
|
- Supported runtimes are Node 20+ and current Bun releases.
|
|
586
789
|
- The packed npm artifact is smoke-tested on Node 20 and 22.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { r as BonsaiInstance, u as InferredTypeName } from "../types-C58c6SlH.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/autocomplete/tokenizer.d.ts
|
|
4
|
+
/** Known phases where errors can occur during completion. */
|
|
5
|
+
type CompletionPhase = 'tokenize' | 'tryEvalPrefix' | 'inferPipeInputType' | `probeTransform:${string}` | 'complete';
|
|
6
|
+
type ErrorHandler = (error: unknown, phase: CompletionPhase) => void;
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/autocomplete/completions.d.ts
|
|
9
|
+
type CompletionInsert = {
|
|
10
|
+
insertText?: undefined;
|
|
11
|
+
cursorOffset?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
insertText: string;
|
|
14
|
+
cursorOffset?: number;
|
|
15
|
+
};
|
|
16
|
+
interface CompletionBase {
|
|
17
|
+
label: string;
|
|
18
|
+
kind: 'variable' | 'property' | 'method' | 'transform' | 'function' | 'keyword';
|
|
19
|
+
detail?: string;
|
|
20
|
+
/** Lower values sort first. Can become negative after fuzzy-match boosting. */
|
|
21
|
+
sortPriority: number;
|
|
22
|
+
}
|
|
23
|
+
type Completion = CompletionBase & CompletionInsert;
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/autocomplete/index.d.ts
|
|
26
|
+
interface AutocompleteOptions {
|
|
27
|
+
context?: Record<string, unknown>;
|
|
28
|
+
/** Map of transform name → accepted input types (e.g., { upper: ['string'], filter: ['array'] }).
|
|
29
|
+
* When set, pipe-transform completions are filtered by the inferred input type.
|
|
30
|
+
* When omitted, auto-probing discovers type compatibility by calling each transform
|
|
31
|
+
* with a sample value — this runs once per type and is cached per instance.
|
|
32
|
+
* For performance-sensitive contexts (e.g., large transform registries), pass this
|
|
33
|
+
* explicitly to avoid the cold-start probe cost. */
|
|
34
|
+
transformTypes?: Record<string, InferredTypeName[]>;
|
|
35
|
+
/** Called when an unexpected internal error occurs during completion.
|
|
36
|
+
* Expected errors (e.g., syntax errors, security blocks, type mismatches) are not reported.
|
|
37
|
+
* Useful for debugging missing or incorrect completions. */
|
|
38
|
+
onError?: ErrorHandler;
|
|
39
|
+
}
|
|
40
|
+
interface AutocompleteInstance {
|
|
41
|
+
complete(expression: string, cursor: number): Completion[];
|
|
42
|
+
setContext(context: Record<string, unknown>): void;
|
|
43
|
+
}
|
|
44
|
+
declare function createAutocomplete(instance: BonsaiInstance, options?: AutocompleteOptions): AutocompleteInstance;
|
|
45
|
+
//#endregion
|
|
46
|
+
export { AutocompleteInstance, AutocompleteOptions, type Completion, createAutocomplete };
|
|
47
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/autocomplete/tokenizer.ts","../../src/autocomplete/completions.ts","../../src/autocomplete/index.ts"],"mappings":";;;;KAcY,eAAA;AAAA,KAOA,YAAA,IAAgB,KAAA,WAAgB,KAAA,EAAO,eAAA;;;KCd9C,gBAAA;EACC,UAAA;EAAwB,YAAA;AAAA;EACxB,UAAA;EAAoB,YAAA;AAAA;AAAA,UAEhB,cAAA;EACR,KAAA;EACA,IAAA;EACA,MAAA;EDO0C;ECL1C,YAAA;AAAA;AAAA,KAGU,UAAA,GAAa,cAAA,GAAiB,gBAAA;;;UCTzB,mBAAA;EACf,OAAA,GAAU,MAAA;EFGe;;AAO3B;;;;EEHE,cAAA,GAAiB,MAAA,SAAe,gBAAA;EFGiB;;;EECjD,OAAA,GAAU,YAAA;AAAA;AAAA,UAGK,oBAAA;EACf,QAAA,CAAS,UAAA,UAAoB,MAAA,WAAiB,UAAA;EAC9C,UAAA,CAAW,OAAA,EAAS,MAAA;AAAA;AAAA,iBAcN,kBAAA,CACd,QAAA,EAAU,cAAA,EACV,OAAA,GAAS,mBAAA,GACR,oBAAA"}
|