@avelonjs/core 0.1.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/LICENSE +21 -0
- package/README.md +566 -0
- package/package.json +46 -0
- package/src/adapter.ts +204 -0
- package/src/drivers/ai.ts +99 -0
- package/src/drivers/cache.ts +48 -0
- package/src/drivers/common.ts +29 -0
- package/src/drivers/database.ts +160 -0
- package/src/drivers/flags.ts +50 -0
- package/src/drivers/identity.ts +133 -0
- package/src/drivers/logs.ts +61 -0
- package/src/drivers/mail.ts +73 -0
- package/src/drivers/notifications.ts +64 -0
- package/src/drivers/payments.ts +107 -0
- package/src/drivers/queue.ts +87 -0
- package/src/drivers/ratelimit.ts +66 -0
- package/src/drivers/realtime.ts +63 -0
- package/src/drivers/search.ts +92 -0
- package/src/drivers/social.ts +63 -0
- package/src/drivers/storage.ts +78 -0
- package/src/drivers/tokens.ts +87 -0
- package/src/errors.ts +166 -0
- package/src/events.ts +185 -0
- package/src/index.ts +22 -0
- package/src/query.ts +86 -0
- package/src/runtime/config.ts +231 -0
- package/src/runtime/dispatcher.ts +335 -0
- package/src/runtime/errands.ts +148 -0
- package/src/runtime/gate.ts +96 -0
- package/src/runtime/index.ts +81 -0
- package/src/runtime/jobs.ts +126 -0
- package/src/runtime/kernel.ts +202 -0
- package/src/runtime/requests.ts +77 -0
- package/src/runtime/transaction.ts +45 -0
- package/src/runtime/wards.ts +362 -0
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@avelonjs/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Frozen TypeScript contracts, errors, and capability types shared by Avelon packages.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Ryan Yannelli <ryanyannelli@gmail.com>",
|
|
8
|
+
"homepage": "https://github.com/yannelli/avelon",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/yannelli/avelon.git",
|
|
12
|
+
"directory": "packages/core"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/yannelli/avelon/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"avelon",
|
|
19
|
+
"typescript",
|
|
20
|
+
"contracts",
|
|
21
|
+
"query-ir"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"src",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"exports": {
|
|
33
|
+
".": "./src/index.ts"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"test": "bun test",
|
|
37
|
+
"typecheck": "tsc --noEmit"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/bun": "1.3.14",
|
|
41
|
+
"typescript": "5.9.3"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"bun": ">=1.3.14"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/adapter.ts
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/** HTTP methods understood by route manifests. */
|
|
2
|
+
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD'
|
|
3
|
+
|
|
4
|
+
/** A route entry consumed by adapters and dispatched by the kernel. */
|
|
5
|
+
export interface RouteDefinition<TController = unknown> {
|
|
6
|
+
/** Stable route name used for URL generation. */
|
|
7
|
+
name: string
|
|
8
|
+
/** Transport-neutral HTTP method. POST remains valid when server actions are unavailable. */
|
|
9
|
+
method: HttpMethod
|
|
10
|
+
/** Route path with named parameters. */
|
|
11
|
+
path: string
|
|
12
|
+
/** Controller reference passed through to the kernel without adapter inspection. */
|
|
13
|
+
controller: TController
|
|
14
|
+
/** Controller method invoked by the kernel. */
|
|
15
|
+
action: string
|
|
16
|
+
/** Middleware aliases applied in declaration order. */
|
|
17
|
+
middleware: readonly string[]
|
|
18
|
+
/** Route parameter names that require model binding. */
|
|
19
|
+
bindings: Readonly<Record<string, string>>
|
|
20
|
+
/** Whether the route also exposes a JSON transport. */
|
|
21
|
+
api: boolean
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Complete route input supplied to an adapter. */
|
|
25
|
+
export interface RouteManifest<TController = unknown> {
|
|
26
|
+
/** Manifest revision used to reject stale generated output. */
|
|
27
|
+
version: string
|
|
28
|
+
/** Routes in declaration order. */
|
|
29
|
+
routes: readonly RouteDefinition<TController>[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Options applied when writing a request or response cookie. */
|
|
33
|
+
export interface CookieOptions {
|
|
34
|
+
/** Host to which the cookie is sent. */
|
|
35
|
+
readonly domain?: string
|
|
36
|
+
/** Absolute time after which the cookie is invalid. */
|
|
37
|
+
readonly expires?: Date
|
|
38
|
+
/** Whether browser scripts are prevented from reading the cookie. */
|
|
39
|
+
readonly httpOnly?: boolean
|
|
40
|
+
/** Lifetime in seconds relative to when the cookie is written. */
|
|
41
|
+
readonly maxAge?: number
|
|
42
|
+
/** Whether the cookie is isolated to its top-level site partition. */
|
|
43
|
+
readonly partitioned?: boolean
|
|
44
|
+
/** Request path to which the cookie is sent. */
|
|
45
|
+
readonly path?: string
|
|
46
|
+
/** Cross-site sending policy. */
|
|
47
|
+
readonly sameSite?: 'lax' | 'strict' | 'none'
|
|
48
|
+
/** Whether the cookie is sent only over secure transports. */
|
|
49
|
+
readonly secure?: boolean
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Request-scoped cookie access supplied to identity drivers through application wiring. */
|
|
53
|
+
export interface RequestCookies {
|
|
54
|
+
/** Returns a cookie value or undefined when it is absent. */
|
|
55
|
+
get(name: string): string | undefined
|
|
56
|
+
/** Writes a cookie using transport-neutral options. */
|
|
57
|
+
set(name: string, value: string, options?: CookieOptions): void
|
|
58
|
+
/** Deletes a cookie using the path and domain that scoped the original cookie. */
|
|
59
|
+
delete(name: string, options?: Pick<CookieOptions, 'domain' | 'path'>): void
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Framework-neutral request passed from an adapter to the kernel. */
|
|
63
|
+
export interface HttpRequest<TBody = unknown> {
|
|
64
|
+
/** Request method. */
|
|
65
|
+
method: HttpMethod
|
|
66
|
+
/** Absolute request URL. */
|
|
67
|
+
url: string
|
|
68
|
+
/** Matched route parameters. */
|
|
69
|
+
params: Readonly<Record<string, string>>
|
|
70
|
+
/** Parsed query values, preserving repeated keys. */
|
|
71
|
+
query: Readonly<Record<string, string | readonly string[]>>
|
|
72
|
+
/** Normalized request headers. */
|
|
73
|
+
headers: Readonly<Record<string, string>>
|
|
74
|
+
/** Parsed request cookies. */
|
|
75
|
+
cookies: Readonly<Record<string, string>>
|
|
76
|
+
/** Adapter-decoded request body. */
|
|
77
|
+
body: TBody
|
|
78
|
+
/** Returns the undecoded wire payload independently of `body` decoding. */
|
|
79
|
+
rawBody(): Promise<Uint8Array>
|
|
80
|
+
/** Whether the native transport has observed request cancellation; may be a live getter. */
|
|
81
|
+
aborted: boolean
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Successful or failed controller action state suitable for any write transport. */
|
|
85
|
+
export interface ActionResult<TData = unknown> {
|
|
86
|
+
/** Result discriminator. */
|
|
87
|
+
type: 'action'
|
|
88
|
+
/** Whether the action completed successfully. */
|
|
89
|
+
ok: boolean
|
|
90
|
+
/** Serializable action output when available. */
|
|
91
|
+
data?: TData
|
|
92
|
+
/** Field-keyed validation messages when the action is invalid. */
|
|
93
|
+
errors?: Readonly<Record<string, readonly string[]>>
|
|
94
|
+
/** Transport-neutral HTTP status hint. */
|
|
95
|
+
status?: number
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Redirect requested by a controller. */
|
|
99
|
+
export interface RedirectResult {
|
|
100
|
+
/** Result discriminator. */
|
|
101
|
+
type: 'redirect'
|
|
102
|
+
/** Destination URL or application-relative path. */
|
|
103
|
+
location: string
|
|
104
|
+
/** Redirect status with defined browser semantics. */
|
|
105
|
+
status: 302 | 303 | 307 | 308
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Opaque adapter-owned view reference that core never inspects. */
|
|
109
|
+
export type ViewRef<TReference = unknown> = TReference
|
|
110
|
+
|
|
111
|
+
/** Controller result rendered by the configured adapter. */
|
|
112
|
+
export interface ViewResult<TViewRef = ViewRef, TProps extends object = Record<string, unknown>> {
|
|
113
|
+
/** Result discriminator. */
|
|
114
|
+
type: 'view'
|
|
115
|
+
/** Opaque view reference interpreted only by the adapter. */
|
|
116
|
+
view: TViewRef
|
|
117
|
+
/** Serializable properties supplied to the view. */
|
|
118
|
+
props: TProps
|
|
119
|
+
/** Transport-neutral HTTP status hint. */
|
|
120
|
+
status?: number
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Byte stream returned by an API controller through a streaming-capable adapter. */
|
|
124
|
+
export interface StreamResult {
|
|
125
|
+
/** Result discriminator. */
|
|
126
|
+
type: 'stream'
|
|
127
|
+
/** Response bytes yielded in transport order. */
|
|
128
|
+
body: AsyncIterable<Uint8Array>
|
|
129
|
+
/** Media type written before streaming begins. */
|
|
130
|
+
contentType: string
|
|
131
|
+
/** Transport-neutral HTTP status hint. */
|
|
132
|
+
status?: number
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Result variants the kernel may return to an adapter. */
|
|
136
|
+
export type KernelResult<TViewRef = ViewRef> =
|
|
137
|
+
| ActionResult
|
|
138
|
+
| RedirectResult
|
|
139
|
+
| ViewResult<TViewRef, object>
|
|
140
|
+
| StreamResult
|
|
141
|
+
|
|
142
|
+
/** Core request pipeline boundary used by every adapter. */
|
|
143
|
+
export interface Kernel<TController = unknown, TViewRef = ViewRef> {
|
|
144
|
+
/**
|
|
145
|
+
* Runs the request pipeline. Adapter wiring prevents stream results when the configured adapter
|
|
146
|
+
* declares `streaming: false`.
|
|
147
|
+
*/
|
|
148
|
+
dispatch(
|
|
149
|
+
route: RouteDefinition<TController>,
|
|
150
|
+
request: HttpRequest,
|
|
151
|
+
): Promise<KernelResult<TViewRef>>
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Options supplied while mounting a route manifest. */
|
|
155
|
+
export interface MountOptions<TController = unknown, TViewRef = ViewRef> {
|
|
156
|
+
/** Core dispatcher all mounted routes delegate to. */
|
|
157
|
+
kernel: Kernel<TController, TViewRef>
|
|
158
|
+
/** Optional URL prefix prepended by the adapter. */
|
|
159
|
+
basePath?: string
|
|
160
|
+
/** Whether development-only adapter behavior may be enabled. */
|
|
161
|
+
development?: boolean
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Observable output of mounting a route manifest. */
|
|
165
|
+
export interface MountResult {
|
|
166
|
+
/** Route names mounted for runtime dispatch. */
|
|
167
|
+
mounted: readonly string[]
|
|
168
|
+
/** Framework-owned files generated by a file-system adapter. */
|
|
169
|
+
generated: readonly string[]
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Translation boundary implemented by a web framework adapter. */
|
|
173
|
+
export interface Adapter<
|
|
174
|
+
TController = unknown,
|
|
175
|
+
TViewRef = ViewRef,
|
|
176
|
+
TNativeRequest = unknown,
|
|
177
|
+
TNativeResponse = unknown,
|
|
178
|
+
> {
|
|
179
|
+
/** Human-readable adapter name. */
|
|
180
|
+
readonly name: string
|
|
181
|
+
/** Literal capabilities used by route generation and runtime wiring. */
|
|
182
|
+
readonly capabilities: {
|
|
183
|
+
/** Whether routes are materialized as framework-owned files. */
|
|
184
|
+
readonly fileSystemRouting: boolean
|
|
185
|
+
/** Whether write routes use generated server actions instead of ordinary HTTP requests. */
|
|
186
|
+
readonly serverActions: boolean
|
|
187
|
+
/** Whether the adapter accepts `StreamResult`; false prevents the kernel from emitting one. */
|
|
188
|
+
readonly streaming: boolean
|
|
189
|
+
/** Whether middleware may execute in an edge runtime. */
|
|
190
|
+
readonly edgeMiddleware: boolean
|
|
191
|
+
}
|
|
192
|
+
/** Generates or registers routes while delegating request execution to the supplied kernel. */
|
|
193
|
+
mount(
|
|
194
|
+
manifest: RouteManifest<TController>,
|
|
195
|
+
options: MountOptions<TController, TViewRef>,
|
|
196
|
+
): Promise<MountResult>
|
|
197
|
+
/**
|
|
198
|
+
* Converts a native request. An unparseable body never causes this method to throw: `body` is
|
|
199
|
+
* null and kernel validation maps the failure to `Invalid`.
|
|
200
|
+
*/
|
|
201
|
+
toRequest(native: TNativeRequest): Promise<HttpRequest>
|
|
202
|
+
/** Converts a kernel result into the framework's native response representation. */
|
|
203
|
+
toResponse(result: KernelResult<TViewRef>): Promise<TNativeResponse>
|
|
204
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { CapabilityMembers, CapabilitySurface, DriverContract } from './common'
|
|
2
|
+
|
|
3
|
+
/** Portable AI operation modes. */
|
|
4
|
+
export type AiMode = 'completion' | 'embedding'
|
|
5
|
+
|
|
6
|
+
/** Literal AI modes and streaming support declared by a driver. */
|
|
7
|
+
export interface AiCapabilities<TMode extends AiMode = AiMode> {
|
|
8
|
+
/** Operation modes retained as a literal readonly list. */
|
|
9
|
+
readonly modes: readonly TMode[]
|
|
10
|
+
/** Whether completion output may be streamed. */
|
|
11
|
+
readonly streaming: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** One role-tagged message in a completion request. */
|
|
15
|
+
export interface AiMessage {
|
|
16
|
+
/** Message author's role. */
|
|
17
|
+
role: 'system' | 'user' | 'assistant'
|
|
18
|
+
/** Message text. */
|
|
19
|
+
content: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Portable completion request. */
|
|
23
|
+
export interface CompletionRequest {
|
|
24
|
+
/** Model identifier understood by the configured driver. */
|
|
25
|
+
model: string
|
|
26
|
+
/** Ordered conversation messages. */
|
|
27
|
+
messages: readonly AiMessage[]
|
|
28
|
+
/** Sampling temperature when supported by the selected model. */
|
|
29
|
+
temperature?: number
|
|
30
|
+
/** Maximum generated tokens. */
|
|
31
|
+
maxTokens?: number
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Completed text generation. */
|
|
35
|
+
export interface CompletionResult {
|
|
36
|
+
/** Generated text. */
|
|
37
|
+
text: string
|
|
38
|
+
/** Input tokens counted by the driver. */
|
|
39
|
+
inputTokens?: number
|
|
40
|
+
/** Output tokens counted by the driver. */
|
|
41
|
+
outputTokens?: number
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Increment emitted by a streaming completion. */
|
|
45
|
+
export interface CompletionChunk {
|
|
46
|
+
/** Incremental generated text. */
|
|
47
|
+
text: string
|
|
48
|
+
/** Whether this is the terminal chunk. */
|
|
49
|
+
done: boolean
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Embedding result preserving input order. */
|
|
53
|
+
export interface EmbeddingResult {
|
|
54
|
+
/** Vector for each supplied input. */
|
|
55
|
+
embeddings: readonly (readonly number[])[]
|
|
56
|
+
/** Input tokens counted by the driver. */
|
|
57
|
+
inputTokens?: number
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Base AI driver identity; operation methods are added only by literal mode capabilities. */
|
|
61
|
+
export interface AiDriver<
|
|
62
|
+
TCapabilities extends AiCapabilities = AiCapabilities,
|
|
63
|
+
TRaw = unknown,
|
|
64
|
+
> extends DriverContract<TCapabilities, TRaw> {}
|
|
65
|
+
|
|
66
|
+
/** Completion methods exposed only when completion mode is configured. */
|
|
67
|
+
export interface CompletionAiSurface {
|
|
68
|
+
/** Generates one complete response. */
|
|
69
|
+
complete(request: CompletionRequest): Promise<CompletionResult>
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Embedding methods exposed only when embedding mode is configured. */
|
|
73
|
+
export interface EmbeddingAiSurface {
|
|
74
|
+
/** Embeds one or more text inputs. */
|
|
75
|
+
embed(model: string, input: string | readonly string[]): Promise<EmbeddingResult>
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Streaming methods exposed only by completion drivers that support streaming. */
|
|
79
|
+
export interface StreamingAiSurface {
|
|
80
|
+
/** Streams completion chunks in generation order. */
|
|
81
|
+
stream(request: CompletionRequest): AsyncIterable<CompletionChunk>
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
type HasMode<TCapabilities extends AiCapabilities, TMode extends AiMode> =
|
|
85
|
+
TMode extends CapabilityMembers<TCapabilities['modes']> ? true : false
|
|
86
|
+
|
|
87
|
+
type StreamingFor<TCapabilities extends AiCapabilities> =
|
|
88
|
+
HasMode<TCapabilities, 'completion'> extends true
|
|
89
|
+
? CapabilitySurface<TCapabilities['streaming'], StreamingAiSurface>
|
|
90
|
+
: object
|
|
91
|
+
|
|
92
|
+
/** AI facade narrowed to literal operation modes and streaming support. */
|
|
93
|
+
export type AI<TDriver extends AiDriver> = Pick<
|
|
94
|
+
TDriver,
|
|
95
|
+
'name' | 'instance' | 'capabilities' | 'raw'
|
|
96
|
+
> &
|
|
97
|
+
CapabilitySurface<HasMode<TDriver['capabilities'], 'completion'>, CompletionAiSurface> &
|
|
98
|
+
CapabilitySurface<HasMode<TDriver['capabilities'], 'embedding'>, EmbeddingAiSurface> &
|
|
99
|
+
StreamingFor<TDriver['capabilities']>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { CapabilitySurface, DriverContract } from './common'
|
|
2
|
+
|
|
3
|
+
/** Literal cache features used to narrow namespaced and locking operations. */
|
|
4
|
+
export interface CacheCapabilities {
|
|
5
|
+
/** Whether entries may be grouped and invalidated by tag. */
|
|
6
|
+
readonly tags: boolean
|
|
7
|
+
/** Whether distributed or process-local locks are available. */
|
|
8
|
+
readonly locks: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Common key-value operations returned by a tagged cache namespace. */
|
|
12
|
+
export interface CacheStore {
|
|
13
|
+
/** Reads and decodes a value, returning null on a miss. */
|
|
14
|
+
get<TValue>(key: string): Promise<TValue | null>
|
|
15
|
+
/** Stores a value for an optional number of seconds. */
|
|
16
|
+
put<TValue>(key: string, value: TValue, ttlSeconds?: number): Promise<void>
|
|
17
|
+
/** Removes one key if it exists. */
|
|
18
|
+
forget(key: string): Promise<void>
|
|
19
|
+
/** Removes every entry in this cache namespace. */
|
|
20
|
+
flush(): Promise<void>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Base cache contract. */
|
|
24
|
+
export interface CacheDriver<
|
|
25
|
+
TCapabilities extends CacheCapabilities = CacheCapabilities,
|
|
26
|
+
TRaw = unknown,
|
|
27
|
+
>
|
|
28
|
+
extends DriverContract<TCapabilities, TRaw>, CacheStore {}
|
|
29
|
+
|
|
30
|
+
/** Tag operations exposed only by caches that support tagged namespaces. */
|
|
31
|
+
export interface TaggedCacheSurface {
|
|
32
|
+
/** Returns a cache namespace whose writes carry all supplied tags. */
|
|
33
|
+
tags(names: readonly string[]): CacheStore
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Lock operations exposed only by lock-capable cache drivers. */
|
|
37
|
+
export interface LockCacheSurface {
|
|
38
|
+
/** Runs a callback while holding a named lock for at most the requested duration. */
|
|
39
|
+
lock<TResult>(key: string, ttlSeconds: number, callback: () => Promise<TResult>): Promise<TResult>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Cache facade narrowed to tag and lock capabilities. */
|
|
43
|
+
export type Cache<TDriver extends CacheDriver> = Pick<
|
|
44
|
+
TDriver,
|
|
45
|
+
'name' | 'instance' | 'capabilities' | 'get' | 'put' | 'forget' | 'flush' | 'raw'
|
|
46
|
+
> &
|
|
47
|
+
CapabilitySurface<TDriver['capabilities']['tags'], TaggedCacheSurface> &
|
|
48
|
+
CapabilitySurface<TDriver['capabilities']['locks'], LockCacheSurface>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Common identity and escape-hatch contract implemented by every driver. */
|
|
2
|
+
export interface DriverContract<TCapabilities extends object = object, TRaw = unknown> {
|
|
3
|
+
/** Driver implementation name, independent of the configured instance. */
|
|
4
|
+
readonly name: string
|
|
5
|
+
/** Framework-level instance name such as `default`, `archive`, or `marketing`. */
|
|
6
|
+
readonly instance: string
|
|
7
|
+
/** Literal capability declaration used to narrow the configured facade. */
|
|
8
|
+
readonly capabilities: TCapabilities
|
|
9
|
+
/** Returns the typed underlying client for use in application driver extensions. */
|
|
10
|
+
raw(): TRaw
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Extracts the literal capability shape declared by a driver. */
|
|
14
|
+
export type DriverCapabilitiesOf<TDriver extends DriverContract> = TDriver['capabilities']
|
|
15
|
+
|
|
16
|
+
/** Resolves to an operation surface only when its capability is literally true. */
|
|
17
|
+
export type CapabilitySurface<TCapability, TSurface> = TCapability extends true ? TSurface : object
|
|
18
|
+
|
|
19
|
+
/** Resolves to the literal members retained in a readonly capability spectrum. */
|
|
20
|
+
export type CapabilityMembers<TValues extends readonly unknown[]> = TValues[number]
|
|
21
|
+
|
|
22
|
+
/** Checks a capability key at runtime while rejecting misspelled keys at compile time. */
|
|
23
|
+
export function supports<TCapabilities extends object, TKey extends keyof TCapabilities>(
|
|
24
|
+
driver: { readonly capabilities: TCapabilities },
|
|
25
|
+
capability: TKey,
|
|
26
|
+
): boolean {
|
|
27
|
+
const value = driver.capabilities[capability]
|
|
28
|
+
return value === true || (Array.isArray(value) ? value.length > 0 : Boolean(value))
|
|
29
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { QueryIR } from '../query'
|
|
2
|
+
import type { CapabilitySurface, DriverContract } from './common'
|
|
3
|
+
|
|
4
|
+
/** Literal database features used by the query facade, compiler, and Bailiff. */
|
|
5
|
+
export interface DatabaseCapabilities {
|
|
6
|
+
/** Whether multi-statement transactions are available. */
|
|
7
|
+
readonly transactions: boolean
|
|
8
|
+
/** Whether wards can be compiled to database row security. */
|
|
9
|
+
readonly rowSecurity: boolean
|
|
10
|
+
/** Maximum supported nested relation depth. */
|
|
11
|
+
readonly maxRelationDepth: number
|
|
12
|
+
/** Whether native full-text search is available. */
|
|
13
|
+
readonly fullTextSearch: boolean
|
|
14
|
+
/** Whether upsert queries are accepted. */
|
|
15
|
+
readonly upsert: boolean
|
|
16
|
+
/** Whether write queries may return rows. */
|
|
17
|
+
readonly returning: boolean
|
|
18
|
+
/**
|
|
19
|
+
* Whether driver-specific queries can execute window functions. Informational in v1; this gates
|
|
20
|
+
* no portable facade surface.
|
|
21
|
+
*/
|
|
22
|
+
readonly windowFunctions: boolean
|
|
23
|
+
/**
|
|
24
|
+
* Whether driver-specific queries can filter or project JSON values. Informational in v1; this
|
|
25
|
+
* gates no portable facade surface.
|
|
26
|
+
*/
|
|
27
|
+
readonly jsonOperators: boolean
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Result of compiling and executing one query IR operation. */
|
|
31
|
+
export interface QueryResult<TRow = Record<string, unknown>> {
|
|
32
|
+
/** Rows selected or returned by the operation. */
|
|
33
|
+
rows: readonly TRow[]
|
|
34
|
+
/** Number of rows affected by the operation. */
|
|
35
|
+
affected: number
|
|
36
|
+
/** Present only for `count` mode and absent for every other query mode. */
|
|
37
|
+
count?: number
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Driver-owned migration plan ready for review or application. */
|
|
41
|
+
export interface MigrationPlan {
|
|
42
|
+
/** Stable plan identifier. */
|
|
43
|
+
id: string
|
|
44
|
+
/** Ordered migration identifiers included in the plan. */
|
|
45
|
+
migrations: readonly string[]
|
|
46
|
+
/** Human-readable statements or steps for inspection. */
|
|
47
|
+
steps: readonly string[]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Current application state for one driver-owned migration. */
|
|
51
|
+
export interface MigrationStatus {
|
|
52
|
+
/** Stable migration identifier. */
|
|
53
|
+
id: string
|
|
54
|
+
/** Whether the migration has been applied. */
|
|
55
|
+
applied: boolean
|
|
56
|
+
/** Application time when known. */
|
|
57
|
+
appliedAt?: Date
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Base database contract available independently of optional capabilities. */
|
|
61
|
+
export interface DatabaseDriver<
|
|
62
|
+
TCapabilities extends DatabaseCapabilities = DatabaseCapabilities,
|
|
63
|
+
TRaw = unknown,
|
|
64
|
+
> extends DriverContract<TCapabilities, TRaw> {
|
|
65
|
+
/** Compiles and executes a serializable query operation. */
|
|
66
|
+
execute<TRow = Record<string, unknown>>(query: QueryIR): Promise<QueryResult<TRow>>
|
|
67
|
+
/** Invokes a named database routine for operations outside the portable query IR. */
|
|
68
|
+
rpc<TResult = unknown>(routine: string, args: Readonly<Record<string, unknown>>): Promise<TResult>
|
|
69
|
+
/** Produces the pending driver-owned migration plan. */
|
|
70
|
+
plan(): Promise<MigrationPlan>
|
|
71
|
+
/** Applies pending driver-owned migrations. */
|
|
72
|
+
apply(): Promise<readonly MigrationStatus[]>
|
|
73
|
+
/** Rolls back the requested number of applied migration batches. */
|
|
74
|
+
rollback(steps?: number): Promise<readonly MigrationStatus[]>
|
|
75
|
+
/** Returns the status of every known migration. */
|
|
76
|
+
status(): Promise<readonly MigrationStatus[]>
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Database operations available inside a transaction callback. */
|
|
80
|
+
export interface DatabaseTransaction {
|
|
81
|
+
/** Compiles and executes a query in the current transaction. */
|
|
82
|
+
execute<TRow = Record<string, unknown>>(query: QueryIR): Promise<QueryResult<TRow>>
|
|
83
|
+
/** Invokes a named routine in the current transaction. */
|
|
84
|
+
rpc<TResult = unknown>(routine: string, args: Readonly<Record<string, unknown>>): Promise<TResult>
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Transaction methods exposed only by transaction-capable drivers. */
|
|
88
|
+
export interface TransactionSurface {
|
|
89
|
+
/** Runs a callback atomically and returns its result after commit. */
|
|
90
|
+
transaction<TResult>(
|
|
91
|
+
callback: (transaction: DatabaseTransaction) => Promise<TResult>,
|
|
92
|
+
): Promise<TResult>
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Row-security methods exposed only by drivers that compile wards. */
|
|
96
|
+
export interface RowSecuritySurface {
|
|
97
|
+
/** Synchronizes compiled wards with the database's row-security policies. */
|
|
98
|
+
syncWards(): Promise<void>
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Full-text methods exposed only by drivers with native search support. */
|
|
102
|
+
export interface DatabaseFullTextSurface {
|
|
103
|
+
/** Searches a table's indexed text and returns matching rows. */
|
|
104
|
+
search<TRow = Record<string, unknown>>(
|
|
105
|
+
table: string,
|
|
106
|
+
query: string,
|
|
107
|
+
options?: { readonly columns?: readonly string[]; readonly limit?: number },
|
|
108
|
+
): Promise<QueryResult<TRow>>
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
type DatabaseQuery<TCapabilities extends DatabaseCapabilities> = QueryIR &
|
|
112
|
+
(TCapabilities['upsert'] extends true
|
|
113
|
+
? object
|
|
114
|
+
: { mode: Exclude<QueryIR['mode'], 'upsert'>; conflict?: never }) &
|
|
115
|
+
(TCapabilities['returning'] extends true ? object : { returning?: never })
|
|
116
|
+
|
|
117
|
+
type DatabaseTransactionFor<TCapabilities extends DatabaseCapabilities> =
|
|
118
|
+
TCapabilities['transactions'] extends true ? TransactionSurface : object
|
|
119
|
+
|
|
120
|
+
type DatabaseRowSecurityFor<TCapabilities extends DatabaseCapabilities> = CapabilitySurface<
|
|
121
|
+
TCapabilities['rowSecurity'],
|
|
122
|
+
RowSecuritySurface
|
|
123
|
+
>
|
|
124
|
+
|
|
125
|
+
type DatabaseFullTextFor<TCapabilities extends DatabaseCapabilities> = CapabilitySurface<
|
|
126
|
+
TCapabilities['fullTextSearch'],
|
|
127
|
+
DatabaseFullTextSurface
|
|
128
|
+
>
|
|
129
|
+
|
|
130
|
+
/** Always-available database facade methods with capability-restricted query input. */
|
|
131
|
+
export interface DatabaseSurface<TDriver extends DatabaseDriver> {
|
|
132
|
+
/** Driver implementation name. */
|
|
133
|
+
readonly name: TDriver['name']
|
|
134
|
+
/** Configured connection name. */
|
|
135
|
+
readonly instance: TDriver['instance']
|
|
136
|
+
/** Driver's exact literal capability declaration. */
|
|
137
|
+
readonly capabilities: TDriver['capabilities']
|
|
138
|
+
/** Compiles and executes a query allowed by the configured capability declaration. */
|
|
139
|
+
execute<TRow = Record<string, unknown>>(
|
|
140
|
+
query: DatabaseQuery<TDriver['capabilities']>,
|
|
141
|
+
): Promise<QueryResult<TRow>>
|
|
142
|
+
/** Invokes a named database routine. */
|
|
143
|
+
rpc<TResult = unknown>(routine: string, args: Readonly<Record<string, unknown>>): Promise<TResult>
|
|
144
|
+
/** Produces the pending migration plan. */
|
|
145
|
+
plan(): Promise<MigrationPlan>
|
|
146
|
+
/** Applies pending migrations. */
|
|
147
|
+
apply(): Promise<readonly MigrationStatus[]>
|
|
148
|
+
/** Rolls back applied migration batches. */
|
|
149
|
+
rollback(steps?: number): Promise<readonly MigrationStatus[]>
|
|
150
|
+
/** Returns all migration states. */
|
|
151
|
+
status(): Promise<readonly MigrationStatus[]>
|
|
152
|
+
/** Returns the driver's typed underlying client. */
|
|
153
|
+
raw(): ReturnType<TDriver['raw']>
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Database facade narrowed to the exact capabilities of its configured driver. */
|
|
157
|
+
export type Database<TDriver extends DatabaseDriver> = DatabaseSurface<TDriver> &
|
|
158
|
+
DatabaseTransactionFor<TDriver['capabilities']> &
|
|
159
|
+
DatabaseRowSecurityFor<TDriver['capabilities']> &
|
|
160
|
+
DatabaseFullTextFor<TDriver['capabilities']>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { DriverContract } from './common'
|
|
2
|
+
|
|
3
|
+
/** Literal feature-flag capabilities. */
|
|
4
|
+
export interface FlagCapabilities {
|
|
5
|
+
/** Whether evaluations may use actor and request targeting context. */
|
|
6
|
+
readonly targeting: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Explicit context supplied to a targeted feature-flag evaluation. */
|
|
10
|
+
export interface FlagContext {
|
|
11
|
+
/** Stable actor identifier when evaluating for an actor. */
|
|
12
|
+
actorId?: string
|
|
13
|
+
/** Stable organization identifier when evaluating for an organization. */
|
|
14
|
+
organizationId?: string
|
|
15
|
+
/** Additional serializable targeting attributes. */
|
|
16
|
+
attributes?: Readonly<Record<string, string | number | boolean>>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Feature flag evaluation contract. */
|
|
20
|
+
export interface FlagDriver<
|
|
21
|
+
TCapabilities extends FlagCapabilities = FlagCapabilities,
|
|
22
|
+
TRaw = unknown,
|
|
23
|
+
> extends DriverContract<TCapabilities, TRaw> {
|
|
24
|
+
/** Evaluates a flag and returns the supplied default when it is unknown. */
|
|
25
|
+
evaluate<TValue>(key: string, defaultValue: TValue, context?: FlagContext): Promise<TValue>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type FlagContextFor<TCapabilities extends FlagCapabilities> =
|
|
29
|
+
TCapabilities['targeting'] extends true ? FlagContext : never
|
|
30
|
+
|
|
31
|
+
/** Feature-flag facade narrowed to its driver's targeting capability. */
|
|
32
|
+
export interface FlagSurface<TDriver extends FlagDriver> {
|
|
33
|
+
/** Driver implementation name. */
|
|
34
|
+
readonly name: TDriver['name']
|
|
35
|
+
/** Configured flag connection name. */
|
|
36
|
+
readonly instance: TDriver['instance']
|
|
37
|
+
/** Exact flag capability declaration. */
|
|
38
|
+
readonly capabilities: TDriver['capabilities']
|
|
39
|
+
/** Evaluates a flag with optional context only when targeting is supported. */
|
|
40
|
+
evaluate<TValue>(
|
|
41
|
+
key: string,
|
|
42
|
+
defaultValue: TValue,
|
|
43
|
+
context?: FlagContextFor<TDriver['capabilities']>,
|
|
44
|
+
): Promise<TValue>
|
|
45
|
+
/** Returns the driver's typed underlying client. */
|
|
46
|
+
raw(): ReturnType<TDriver['raw']>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Feature-flag facade narrowed to its driver's exact capabilities. */
|
|
50
|
+
export type Flags<TDriver extends FlagDriver> = FlagSurface<TDriver>
|