effect-vercel 0.4.0 → 0.5.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/README.md +25 -1
- package/dist/Functions.d.ts +14 -0
- package/dist/Functions.js +34 -0
- package/dist/Functions.js.map +1 -0
- package/dist/RuntimeCache.js +1 -1
- package/package.json +5 -3
- package/src/Functions.ts +34 -0
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ import * as AiGateway from "effect-vercel/AiGateway"
|
|
|
11
11
|
| ------------------------------------ | ------------------------------------------------------------------------------- |
|
|
12
12
|
| `effect-vercel/AiGateway` | [Vercel AI Gateway](https://vercel.com/docs/ai-gateway) for Effect AI |
|
|
13
13
|
| `effect-vercel/AiGatewayCredentials` | How AI Gateway requests authenticate |
|
|
14
|
+
| `effect-vercel/Functions` | Bindings for `@vercel/functions`: `waitUntil` |
|
|
14
15
|
| `effect-vercel/Oidc` | The OIDC token Vercel issues to a deployment |
|
|
15
16
|
| `effect-vercel/RuntimeCache` | [Runtime Cache](https://vercel.com/docs/runtime-cache) for Effect `Persistence` |
|
|
16
17
|
|
|
@@ -19,7 +20,7 @@ import * as AiGateway from "effect-vercel/AiGateway"
|
|
|
19
20
|
```sh
|
|
20
21
|
pnpm add effect-vercel effect
|
|
21
22
|
pnpm add @effect/ai-anthropic # only for effect-vercel/AiGateway
|
|
22
|
-
pnpm add @vercel/functions # only for effect-vercel/RuntimeCache
|
|
23
|
+
pnpm add @vercel/functions # only for effect-vercel/Functions and RuntimeCache
|
|
23
24
|
```
|
|
24
25
|
|
|
25
26
|
## AI Gateway
|
|
@@ -120,6 +121,29 @@ unset. It fails with an `OidcError` when neither is set.
|
|
|
120
121
|
It reads the token on every run, since it rotates per request. It does not refresh an
|
|
121
122
|
expired local token; re-run `vercel env pull`.
|
|
122
123
|
|
|
124
|
+
## Functions
|
|
125
|
+
|
|
126
|
+
`Functions.waitUntil(fiber)` keeps the Function running until `fiber` ends, as `waitUntil`
|
|
127
|
+
from `@vercel/functions` does for a promise. Use it to finish work after the response is sent.
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
import * as Functions from "effect-vercel/Functions"
|
|
131
|
+
import { Effect } from "effect"
|
|
132
|
+
|
|
133
|
+
const handler = Effect.gen(function* () {
|
|
134
|
+
yield* Effect.forkDetach(sendReceipt).pipe(Effect.tap(Functions.waitUntil))
|
|
135
|
+
return new Response("OK")
|
|
136
|
+
})
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
- Fork with `Effect.forkDetach`, or into a scope that outlives the request. A child fiber is
|
|
140
|
+
interrupted when the request fiber ends, whatever `waitUntil` says.
|
|
141
|
+
- The fiber keeps the request's services. Acquire resources it needs inside its own
|
|
142
|
+
`Effect.scoped`, since the request's resources may be released first.
|
|
143
|
+
- Failures are not reported. Handle or log them in the forked effect.
|
|
144
|
+
- Vercel stops the work when the Function reaches its maximum duration.
|
|
145
|
+
- Off Vercel, `waitUntil` does nothing and the fiber runs in the background.
|
|
146
|
+
|
|
123
147
|
## Runtime Cache
|
|
124
148
|
|
|
125
149
|
`RuntimeCache.layer` provides Effect's `Persistence`, stored in the Vercel Runtime Cache.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Effect, Fiber } from "effect";
|
|
2
|
+
//#region src/Functions.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Keeps the Function running until `fiber` ends, as `waitUntil` from
|
|
5
|
+
* `@vercel/functions` does for a promise. Off Vercel it does nothing.
|
|
6
|
+
*
|
|
7
|
+
* The fiber must outlive the request fiber, so fork it with
|
|
8
|
+
* `Effect.forkDetach` or into a scope that outlives the request. A child
|
|
9
|
+
* fiber is interrupted when the request fiber ends. Failures are not
|
|
10
|
+
* reported, so handle them in the forked effect.
|
|
11
|
+
*/
|
|
12
|
+
export declare const waitUntil: <A, E>(fiber: Fiber.Fiber<A, E>) => Effect.Effect<void>;
|
|
13
|
+
//#endregion
|
|
14
|
+
//# sourceMappingURL=Functions.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { waitUntil as waitUntil$1 } from "@vercel/functions";
|
|
3
|
+
//#region src/Functions.ts
|
|
4
|
+
/**
|
|
5
|
+
* Effect bindings for `@vercel/functions`.
|
|
6
|
+
*
|
|
7
|
+
* `waitUntil` keeps the Function running until a fiber ends, so work forked
|
|
8
|
+
* during a request can finish after the response is sent.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import * as Functions from "effect-vercel/Functions"
|
|
13
|
+
* import { Effect } from "effect"
|
|
14
|
+
*
|
|
15
|
+
* const handler = Effect.gen(function* () {
|
|
16
|
+
* yield* Effect.forkDetach(sendReceipt).pipe(Effect.tap(Functions.waitUntil))
|
|
17
|
+
* return new Response("OK")
|
|
18
|
+
* })
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Keeps the Function running until `fiber` ends, as `waitUntil` from
|
|
23
|
+
* `@vercel/functions` does for a promise. Off Vercel it does nothing.
|
|
24
|
+
*
|
|
25
|
+
* The fiber must outlive the request fiber, so fork it with
|
|
26
|
+
* `Effect.forkDetach` or into a scope that outlives the request. A child
|
|
27
|
+
* fiber is interrupted when the request fiber ends. Failures are not
|
|
28
|
+
* reported, so handle them in the forked effect.
|
|
29
|
+
*/
|
|
30
|
+
const waitUntil = (fiber) => Effect.sync(() => waitUntil$1(new Promise((resolve) => fiber.addObserver(() => resolve()))));
|
|
31
|
+
//#endregion
|
|
32
|
+
export { waitUntil };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=Functions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Functions.js","names":["vercelWaitUntil"],"sources":["../src/Functions.ts"],"sourcesContent":["/**\n * Effect bindings for `@vercel/functions`.\n *\n * `waitUntil` keeps the Function running until a fiber ends, so work forked\n * during a request can finish after the response is sent.\n *\n * @example\n * ```ts\n * import * as Functions from \"effect-vercel/Functions\"\n * import { Effect } from \"effect\"\n *\n * const handler = Effect.gen(function* () {\n * yield* Effect.forkDetach(sendReceipt).pipe(Effect.tap(Functions.waitUntil))\n * return new Response(\"OK\")\n * })\n * ```\n */\n\nimport { waitUntil as vercelWaitUntil } from \"@vercel/functions\"\nimport { Effect, type Fiber } from \"effect\"\n\n/**\n * Keeps the Function running until `fiber` ends, as `waitUntil` from\n * `@vercel/functions` does for a promise. Off Vercel it does nothing.\n *\n * The fiber must outlive the request fiber, so fork it with\n * `Effect.forkDetach` or into a scope that outlives the request. A child\n * fiber is interrupted when the request fiber ends. Failures are not\n * reported, so handle them in the forked effect.\n */\nexport const waitUntil = <A, E>(fiber: Fiber.Fiber<A, E>): Effect.Effect<void> =>\n Effect.sync(() =>\n vercelWaitUntil(new Promise<void>((resolve) => fiber.addObserver(() => resolve()))),\n )\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAa,aAAmB,UAC9B,OAAO,WACLA,YAAgB,IAAI,SAAe,YAAY,MAAM,kBAAkB,QAAQ,CAAC,CAAC,CAAC,CACpF"}
|
package/dist/RuntimeCache.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Duration, Effect, Layer } from "effect";
|
|
2
|
-
import { createHash } from "node:crypto";
|
|
3
2
|
import { getCache } from "@vercel/functions";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
4
|
import { Persistence } from "effect/persistence";
|
|
5
5
|
//#region src/RuntimeCache.ts
|
|
6
6
|
/**
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effect-vercel",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Effect integrations for Vercel: AI Gateway, OIDC, Runtime Cache",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Effect integrations for Vercel: AI Gateway, OIDC, Runtime Cache, waitUntil",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-gateway",
|
|
7
7
|
"effect",
|
|
8
8
|
"effect-ai",
|
|
9
9
|
"oidc",
|
|
10
10
|
"runtime-cache",
|
|
11
|
-
"vercel"
|
|
11
|
+
"vercel",
|
|
12
|
+
"wait-until"
|
|
12
13
|
],
|
|
13
14
|
"homepage": "https://github.com/duailibe/effect-vercel#readme",
|
|
14
15
|
"bugs": {
|
|
@@ -29,6 +30,7 @@
|
|
|
29
30
|
"exports": {
|
|
30
31
|
"./AiGateway": "./dist/AiGateway.js",
|
|
31
32
|
"./AiGatewayCredentials": "./dist/AiGatewayCredentials.js",
|
|
33
|
+
"./Functions": "./dist/Functions.js",
|
|
32
34
|
"./Oidc": "./dist/Oidc.js",
|
|
33
35
|
"./RuntimeCache": "./dist/RuntimeCache.js",
|
|
34
36
|
"./package.json": "./package.json"
|
package/src/Functions.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effect bindings for `@vercel/functions`.
|
|
3
|
+
*
|
|
4
|
+
* `waitUntil` keeps the Function running until a fiber ends, so work forked
|
|
5
|
+
* during a request can finish after the response is sent.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import * as Functions from "effect-vercel/Functions"
|
|
10
|
+
* import { Effect } from "effect"
|
|
11
|
+
*
|
|
12
|
+
* const handler = Effect.gen(function* () {
|
|
13
|
+
* yield* Effect.forkDetach(sendReceipt).pipe(Effect.tap(Functions.waitUntil))
|
|
14
|
+
* return new Response("OK")
|
|
15
|
+
* })
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { waitUntil as vercelWaitUntil } from "@vercel/functions"
|
|
20
|
+
import { Effect, type Fiber } from "effect"
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Keeps the Function running until `fiber` ends, as `waitUntil` from
|
|
24
|
+
* `@vercel/functions` does for a promise. Off Vercel it does nothing.
|
|
25
|
+
*
|
|
26
|
+
* The fiber must outlive the request fiber, so fork it with
|
|
27
|
+
* `Effect.forkDetach` or into a scope that outlives the request. A child
|
|
28
|
+
* fiber is interrupted when the request fiber ends. Failures are not
|
|
29
|
+
* reported, so handle them in the forked effect.
|
|
30
|
+
*/
|
|
31
|
+
export const waitUntil = <A, E>(fiber: Fiber.Fiber<A, E>): Effect.Effect<void> =>
|
|
32
|
+
Effect.sync(() =>
|
|
33
|
+
vercelWaitUntil(new Promise<void>((resolve) => fiber.addObserver(() => resolve()))),
|
|
34
|
+
)
|