@alienplatform/bindings 1.0.0 → 2.0.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 (56) hide show
  1. package/LICENSE.md +105 -0
  2. package/README.md +59 -0
  3. package/dist/errors.d.ts +56 -0
  4. package/dist/errors.d.ts.map +1 -0
  5. package/dist/factories.d.ts +26 -0
  6. package/dist/factories.d.ts.map +1 -0
  7. package/dist/index.d.ts +19 -1768
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +23 -44772
  10. package/dist/loader.d.ts +171 -0
  11. package/dist/loader.d.ts.map +1 -0
  12. package/dist/loader.js +3712 -0
  13. package/dist/native.d.ts +41 -0
  14. package/dist/native.d.ts.map +1 -0
  15. package/dist/native.js +46 -0
  16. package/dist/types.d.ts +150 -0
  17. package/dist/types.d.ts.map +1 -0
  18. package/package.json +39 -21
  19. package/AGENTS.md +0 -70
  20. package/dist/index.js.map +0 -1
  21. package/scripts/generate-proto.sh +0 -46
  22. package/src/bindings/AGENTS.md +0 -105
  23. package/src/bindings/artifact-registry.ts +0 -314
  24. package/src/bindings/build.ts +0 -195
  25. package/src/bindings/function.ts +0 -164
  26. package/src/bindings/index.ts +0 -12
  27. package/src/bindings/kv.ts +0 -240
  28. package/src/bindings/queue.ts +0 -191
  29. package/src/bindings/service-account.ts +0 -113
  30. package/src/bindings/storage.ts +0 -535
  31. package/src/bindings/vault.ts +0 -133
  32. package/src/channel.ts +0 -94
  33. package/src/commands.ts +0 -76
  34. package/src/context.ts +0 -368
  35. package/src/errors.ts +0 -259
  36. package/src/events.ts +0 -463
  37. package/src/generated/artifact_registry.ts +0 -1934
  38. package/src/generated/build.ts +0 -1263
  39. package/src/generated/container.ts +0 -485
  40. package/src/generated/control.ts +0 -1574
  41. package/src/generated/function.ts +0 -741
  42. package/src/generated/google/protobuf/duration.ts +0 -196
  43. package/src/generated/google/protobuf/timestamp.ts +0 -225
  44. package/src/generated/kv.ts +0 -1137
  45. package/src/generated/queue.ts +0 -729
  46. package/src/generated/service_account.ts +0 -766
  47. package/src/generated/storage.ts +0 -3653
  48. package/src/generated/vault.ts +0 -519
  49. package/src/generated/wait_until.ts +0 -781
  50. package/src/global.ts +0 -316
  51. package/src/grpc-utils.ts +0 -159
  52. package/src/index.ts +0 -156
  53. package/src/types.ts +0 -384
  54. package/src/wait-until.ts +0 -257
  55. package/tsconfig.json +0 -8
  56. package/tsdown.config.ts +0 -14
package/src/channel.ts DELETED
@@ -1,94 +0,0 @@
1
- /**
2
- * gRPC channel management for the Alien bindings SDK.
3
- */
4
-
5
- import { AlienError } from "@alienplatform/core"
6
- import { type Channel, createChannel } from "nice-grpc"
7
- import { GrpcConnectionError, MissingEnvVarError } from "./errors.js"
8
-
9
- /** Environment variable containing the gRPC endpoint */
10
- const GRPC_ENDPOINT_VAR = "ALIEN_BINDINGS_GRPC_ADDRESS"
11
-
12
- /** Cached channels by address */
13
- const channelCache = new Map<string, Channel>()
14
-
15
- /** Re-export the Channel type */
16
- export type GrpcChannel = Channel
17
-
18
- /**
19
- * Get the gRPC endpoint from environment variables.
20
- */
21
- export function getGrpcEndpoint(): string {
22
- const endpoint = process.env[GRPC_ENDPOINT_VAR]
23
- if (!endpoint) {
24
- throw new AlienError(
25
- MissingEnvVarError.create({
26
- variable: GRPC_ENDPOINT_VAR,
27
- description:
28
- "This variable is set by alien-runtime when running inside the Alien environment.",
29
- }),
30
- )
31
- }
32
- return endpoint
33
- }
34
-
35
- /**
36
- * Create a gRPC channel to the specified address.
37
- *
38
- * @param address - The gRPC server address
39
- * @returns The created channel
40
- */
41
- export async function createGrpcChannel(address: string): Promise<Channel> {
42
- try {
43
- return createChannel(address)
44
- } catch (error) {
45
- throw (await AlienError.from(error)).withContext(
46
- GrpcConnectionError.create({
47
- endpoint: address,
48
- reason: error instanceof Error ? error.message : String(error),
49
- }),
50
- )
51
- }
52
- }
53
-
54
- /**
55
- * Get or create a cached gRPC channel to the specified address.
56
- *
57
- * @param address - The gRPC server address
58
- * @returns The cached or newly created channel
59
- */
60
- export async function getOrCreateChannel(address: string): Promise<Channel> {
61
- let channel = channelCache.get(address)
62
- if (!channel) {
63
- channel = await createGrpcChannel(address)
64
- channelCache.set(address, channel)
65
- }
66
- return channel
67
- }
68
-
69
- /**
70
- * Get a gRPC channel to the alien-runtime using the default env var.
71
- * The channel is cached for reuse across all bindings.
72
- */
73
- export async function getChannel(): Promise<Channel> {
74
- const endpoint = getGrpcEndpoint()
75
- return await getOrCreateChannel(endpoint)
76
- }
77
-
78
- /**
79
- * Close all cached gRPC channels.
80
- * This should be called when shutting down the application.
81
- */
82
- export function closeChannel(): void {
83
- for (const channel of channelCache.values()) {
84
- channel.close()
85
- }
86
- channelCache.clear()
87
- }
88
-
89
- /**
90
- * Reset the cached channels (useful for testing).
91
- */
92
- export function resetChannel(): void {
93
- channelCache.clear()
94
- }
package/src/commands.ts DELETED
@@ -1,76 +0,0 @@
1
- /**
2
- * Command handling for Alien bindings.
3
- *
4
- * Provides ARC command registration and execution.
5
- */
6
-
7
- /**
8
- * Command definition.
9
- */
10
- export interface CommandDefinition {
11
- /** Command name */
12
- name: string
13
- /** Handler function that receives params and returns a result */
14
- handler: (params: unknown) => Promise<unknown>
15
- }
16
-
17
- // Internal storage for commands
18
- const commands: Map<string, CommandDefinition> = new Map()
19
-
20
- /**
21
- * Register an ARC command.
22
- *
23
- * @param name - Command name
24
- * @param handler - Command handler function that receives params and returns a result
25
- *
26
- * @example
27
- * ```typescript
28
- * import { command } from "@alienplatform/bindings"
29
- *
30
- * command("echo", async ({ message }: { message: string }) => {
31
- * return {
32
- * message,
33
- * timestamp: new Date().toISOString(),
34
- * }
35
- * })
36
- *
37
- * command("process-data", async ({ data }: { data: string[] }) => {
38
- * const result = await processData(data)
39
- * return { processed: result.length }
40
- * })
41
- * ```
42
- */
43
- export function command<TParams = unknown, TResult = unknown>(
44
- name: string,
45
- handler: (params: TParams) => Promise<TResult>,
46
- ): void {
47
- commands.set(name, { name, handler: handler as (params: unknown) => Promise<unknown> })
48
- }
49
-
50
- /**
51
- * Get all registered commands.
52
- *
53
- * @internal
54
- */
55
- export function getCommands(): Map<string, CommandDefinition> {
56
- return commands
57
- }
58
-
59
- /**
60
- * Execute an ARC command by name.
61
- *
62
- * @param name - Command name to execute
63
- * @param params - Command parameters
64
- * @returns Command result
65
- *
66
- * @internal
67
- */
68
- export async function runCommand(name: string, params: unknown): Promise<unknown> {
69
- const cmd = commands.get(name)
70
-
71
- if (!cmd) {
72
- throw new Error(`Unknown command: ${name}. Available: ${[...commands.keys()].join(", ")}`)
73
- }
74
-
75
- return await cmd.handler(params)
76
- }
package/src/context.ts DELETED
@@ -1,368 +0,0 @@
1
- /**
2
- * AlienContext - Main entry point for Alien bindings.
3
- *
4
- * Provides access to all bindings and control plane functionality.
5
- */
6
-
7
- import type { StorageEvent } from "@alienplatform/core"
8
- import { AlienError } from "@alienplatform/core"
9
- import type { Channel } from "nice-grpc"
10
- import { createClient } from "nice-grpc"
11
- import { ArtifactRegistry } from "./bindings/artifact-registry.js"
12
- import { Build } from "./bindings/build.js"
13
- import { FunctionBinding } from "./bindings/function.js"
14
- import { Kv } from "./bindings/kv.js"
15
- import { Queue } from "./bindings/queue.js"
16
- import { ServiceAccount } from "./bindings/service-account.js"
17
- import { Storage } from "./bindings/storage.js"
18
- import { Vault } from "./bindings/vault.js"
19
- import { createGrpcChannel, getOrCreateChannel } from "./channel.js"
20
- import { command } from "./commands.js"
21
- import { InvalidBindingConfigError } from "./errors.js"
22
- import {
23
- type CronEvent,
24
- EventLoop,
25
- type QueueMessageEvent,
26
- onCronEvent,
27
- onQueueMessage,
28
- onStorageEvent,
29
- } from "./events.js"
30
- import { ControlServiceDefinition } from "./generated/control.js"
31
- import { wrapGrpcCall } from "./grpc-utils.js"
32
- import type { AlienBindingsConfig, AlienBindingsProvider } from "./types.js"
33
- import { type WaitUntilManager, initWaitUntilManager, waitUntil } from "./wait-until.js"
34
-
35
- /**
36
- * Instance ID for this function instance.
37
- */
38
- function generateInstanceId(): string {
39
- return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`
40
- }
41
-
42
- /**
43
- * AlienContext provides the main entry point for accessing Alien bindings
44
- * and control plane functionality.
45
- *
46
- * @example
47
- * ```typescript
48
- * import { AlienContext } from "@alienplatform/bindings"
49
- *
50
- * // Create context from environment
51
- * const ctx = AlienContext.fromEnv()
52
- *
53
- * // Access bindings
54
- * const bucket = ctx.storage("my-bucket")
55
- * await bucket.put("hello.txt", "Hello, World!")
56
- *
57
- * // Register event handlers
58
- * ctx.onStorageEvent("uploads", async (event) => {
59
- * console.log("File uploaded:", event.key)
60
- * })
61
- *
62
- * // Start the runtime
63
- * await ctx.run()
64
- * ```
65
- */
66
- export class AlienContext implements AlienBindingsProvider {
67
- private readonly channel: Channel
68
- private readonly instanceId: string
69
- private readonly bindingCache = new Map<string, unknown>()
70
- private eventLoop: EventLoop | undefined
71
- private waitUntilManager: WaitUntilManager | undefined
72
-
73
- private constructor(channel: Channel, instanceId?: string) {
74
- this.channel = channel
75
- this.instanceId = instanceId ?? generateInstanceId()
76
- }
77
-
78
- /**
79
- * Create a context from environment variables.
80
- *
81
- * Reads the ALIEN_BINDINGS_GRPC_ADDRESS environment variable.
82
- */
83
- static async fromEnv(): Promise<AlienContext> {
84
- const address = process.env.ALIEN_BINDINGS_GRPC_ADDRESS
85
-
86
- if (!address) {
87
- throw new AlienError(
88
- InvalidBindingConfigError.create({
89
- message: "ALIEN_BINDINGS_GRPC_ADDRESS environment variable is not set",
90
- suggestion:
91
- "Make sure you're running inside an Alien function or set the variable manually",
92
- }),
93
- )
94
- }
95
-
96
- const channel = await getOrCreateChannel(address)
97
- return new AlienContext(channel)
98
- }
99
-
100
- /**
101
- * Create a context with explicit configuration.
102
- */
103
- static async create(config: AlienBindingsConfig): Promise<AlienContext> {
104
- if (!config.grpcAddress) {
105
- throw new AlienError(
106
- InvalidBindingConfigError.create({
107
- message: "gRPC address is required",
108
- suggestion: "Provide grpcAddress in the config",
109
- }),
110
- )
111
- }
112
-
113
- const channel = await createGrpcChannel(config.grpcAddress)
114
- return new AlienContext(channel)
115
- }
116
-
117
- /**
118
- * Create a context for connecting to a remote agent.
119
- *
120
- * @param address - gRPC address of the remote agent
121
- */
122
- // TODO: Wtf? this is completely hallucinated :) See 05-bindings.md.
123
- static async forRemoteAgent(address: string): Promise<AlienContext> {
124
- const channel = await createGrpcChannel(address)
125
- return new AlienContext(channel)
126
- }
127
-
128
- /**
129
- * Get or create a cached binding instance.
130
- */
131
- private getBinding<T>(key: string, factory: () => T): T {
132
- let binding = this.bindingCache.get(key) as T | undefined
133
- if (!binding) {
134
- binding = factory()
135
- this.bindingCache.set(key, binding)
136
- }
137
- return binding
138
- }
139
-
140
- // ============================================================================
141
- // Binding Accessors
142
- // ============================================================================
143
-
144
- /**
145
- * Get a storage binding.
146
- *
147
- * @param name - Binding name
148
- * @returns Storage binding instance
149
- */
150
- storage(name: string): Storage {
151
- return this.getBinding(`storage:${name}`, () => new Storage(this.channel, name))
152
- }
153
-
154
- /**
155
- * Get a KV binding.
156
- *
157
- * @param name - Binding name
158
- * @returns KV binding instance
159
- */
160
- kv(name: string): Kv {
161
- return this.getBinding(`kv:${name}`, () => new Kv(this.channel, name))
162
- }
163
-
164
- /**
165
- * Get a queue binding.
166
- *
167
- * @param name - Binding name
168
- * @returns Queue binding instance
169
- */
170
- queue(name: string): Queue {
171
- return this.getBinding(`queue:${name}`, () => new Queue(this.channel, name))
172
- }
173
-
174
- /**
175
- * Get a vault binding.
176
- *
177
- * @param name - Binding name
178
- * @returns Vault binding instance
179
- */
180
- vault(name: string): Vault {
181
- return this.getBinding(`vault:${name}`, () => new Vault(this.channel, name))
182
- }
183
-
184
- /**
185
- * Get a build binding.
186
- *
187
- * @param name - Binding name
188
- * @returns Build binding instance
189
- */
190
- build(name: string): Build {
191
- return this.getBinding(`build:${name}`, () => new Build(this.channel, name))
192
- }
193
-
194
- /**
195
- * Get an artifact registry binding.
196
- *
197
- * @param name - Binding name
198
- * @returns ArtifactRegistry binding instance
199
- */
200
- artifactRegistry(name: string): ArtifactRegistry {
201
- return this.getBinding(
202
- `artifact-registry:${name}`,
203
- () => new ArtifactRegistry(this.channel, name),
204
- )
205
- }
206
-
207
- /**
208
- * Get a function binding.
209
- *
210
- * @param name - Binding name
211
- * @returns Function binding instance
212
- */
213
- func(name: string): FunctionBinding {
214
- return this.getBinding(`function:${name}`, () => new FunctionBinding(this.channel, name))
215
- }
216
-
217
- /**
218
- * Get a service account binding.
219
- *
220
- * @param name - Binding name
221
- * @returns ServiceAccount binding instance
222
- */
223
- serviceAccount(name: string): ServiceAccount {
224
- return this.getBinding(`service-account:${name}`, () => new ServiceAccount(this.channel, name))
225
- }
226
-
227
- // ============================================================================
228
- // Event Handlers
229
- // ============================================================================
230
-
231
- /**
232
- * Register a storage event handler.
233
- *
234
- * @param bucket - Bucket name
235
- * @param handler - Event handler
236
- * @param options - Handler options
237
- * @returns Unsubscribe function
238
- */
239
- onStorageEvent(
240
- bucket: string,
241
- handler: (event: StorageEvent) => Promise<void>,
242
- options?: { prefix?: string },
243
- ): () => void {
244
- return onStorageEvent(bucket, handler, options)
245
- }
246
-
247
- /**
248
- * Register a cron event handler.
249
- *
250
- * @param schedule - Cron schedule expression
251
- * @param handler - Event handler
252
- * @returns Unsubscribe function
253
- */
254
- onCronEvent(schedule: string, handler: (event: CronEvent) => Promise<void>): () => void {
255
- return onCronEvent(schedule, handler)
256
- }
257
-
258
- /**
259
- * Register a queue message handler.
260
- *
261
- * @param queueName - Queue name
262
- * @param handler - Message handler
263
- * @returns Unsubscribe function
264
- */
265
- onQueueMessage<T = unknown>(
266
- queueName: string,
267
- handler: (message: QueueMessageEvent<T>) => Promise<void>,
268
- ): () => void {
269
- return onQueueMessage(queueName, handler)
270
- }
271
-
272
- // ============================================================================
273
- // Commands
274
- // ============================================================================
275
-
276
- /**
277
- * Register an ARC command.
278
- *
279
- * @param name - Command name
280
- * @param handler - Command handler that receives params and returns a result
281
- */
282
- command<TParams = unknown, TResult = unknown>(
283
- name: string,
284
- handler: (params: TParams) => Promise<TResult>,
285
- ): void {
286
- command(name, handler)
287
- }
288
-
289
- // ============================================================================
290
- // HTTP Server Registration
291
- // ============================================================================
292
-
293
- /**
294
- * Register an HTTP server with the control plane.
295
- *
296
- * @param port - Port the server is listening on
297
- */
298
- async registerHttpServer(port: number): Promise<void> {
299
- const client = createClient(ControlServiceDefinition, this.channel)
300
-
301
- await wrapGrpcCall(
302
- "ControlService",
303
- "RegisterHttpServer",
304
- async () => {
305
- await client.registerHttpServer({ port })
306
- },
307
- {},
308
- )
309
- }
310
-
311
- // ============================================================================
312
- // WaitUntil
313
- // ============================================================================
314
-
315
- /**
316
- * Register a background task.
317
- *
318
- * @param promise - The promise to track
319
- */
320
- waitUntil(promise: Promise<unknown>): void {
321
- waitUntil(promise)
322
- }
323
-
324
- // ============================================================================
325
- // Lifecycle
326
- // ============================================================================
327
-
328
- /**
329
- * Start the Alien runtime.
330
- *
331
- * This initializes event handlers, registers with the control plane,
332
- * and starts processing events.
333
- */
334
- async run(): Promise<void> {
335
- // Initialize wait-until manager
336
- this.waitUntilManager = initWaitUntilManager(this.channel, this.instanceId)
337
-
338
- // Initialize event loop
339
- this.eventLoop = new EventLoop(this.channel, this.instanceId)
340
-
341
- // Register event handlers with the control plane
342
- await this.eventLoop.registerHandlers()
343
-
344
- // Start event loop (handles ARC commands, events, etc.)
345
- await this.eventLoop.start()
346
- }
347
-
348
- /**
349
- * Stop the runtime gracefully.
350
- */
351
- async shutdown(): Promise<void> {
352
- // Stop event loop
353
- this.eventLoop?.stop()
354
-
355
- // Wait for all background tasks
356
- await this.waitUntilManager?.waitForAll()
357
-
358
- // Notify drain complete
359
- const tasks = this.waitUntilManager?.getTasks()
360
- if (tasks) {
361
- const taskArray = Array.from(tasks.values())
362
- const tasksDrained = taskArray.length
363
- const allSuccess = taskArray.every(t => !t.error)
364
- const errorMessage = taskArray.find(t => t.error)?.error?.message
365
- await this.waitUntilManager?.notifyDrainComplete(tasksDrained, allSuccess, errorMessage)
366
- }
367
- }
368
- }