@vercel/functions 2.2.2 → 2.2.3
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 +6 -0
- package/cache/build-client.d.ts +18 -0
- package/cache/build-client.js +121 -0
- package/cache/in-memory-cache.d.ts +1 -3
- package/cache/in-memory-cache.js +1 -6
- package/cache/index.d.ts +11 -0
- package/cache/index.js +84 -18
- package/cache/types.d.ts +1 -5
- package/docs/interfaces/index.RuntimeCache.md +8 -10
- package/docs/modules/index.md +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class BuildCache {
|
|
2
|
+
private readonly endpoint;
|
|
3
|
+
private readonly headers;
|
|
4
|
+
private readonly onError?;
|
|
5
|
+
constructor({ endpoint, headers, onError, }: {
|
|
6
|
+
endpoint: string;
|
|
7
|
+
headers: Record<string, string>;
|
|
8
|
+
onError?: (error: Error) => void;
|
|
9
|
+
});
|
|
10
|
+
get: (key: string) => Promise<unknown>;
|
|
11
|
+
set: (key: string, value: unknown, options?: {
|
|
12
|
+
name?: string;
|
|
13
|
+
ttl?: number;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
}) => Promise<void>;
|
|
16
|
+
delete: (key: string) => Promise<void>;
|
|
17
|
+
expireTag: (tag: string | string[]) => Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var build_client_exports = {};
|
|
20
|
+
__export(build_client_exports, {
|
|
21
|
+
BuildCache: () => BuildCache
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(build_client_exports);
|
|
24
|
+
var import_index = require("./index");
|
|
25
|
+
class BuildCache {
|
|
26
|
+
constructor({
|
|
27
|
+
endpoint,
|
|
28
|
+
headers,
|
|
29
|
+
onError
|
|
30
|
+
}) {
|
|
31
|
+
this.get = async (key) => {
|
|
32
|
+
try {
|
|
33
|
+
const res = await fetch(`${this.endpoint}${key}`, {
|
|
34
|
+
headers: this.headers,
|
|
35
|
+
method: "GET"
|
|
36
|
+
});
|
|
37
|
+
if (res.status === 404) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
if (res.status === 200) {
|
|
41
|
+
const cacheState = res.headers.get(
|
|
42
|
+
import_index.HEADERS_VERCEL_CACHE_STATE
|
|
43
|
+
);
|
|
44
|
+
if (cacheState !== import_index.PkgCacheState.Fresh) {
|
|
45
|
+
res.body?.cancel?.();
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return await res.json();
|
|
49
|
+
} else {
|
|
50
|
+
throw new Error(`Failed to get cache: ${res.statusText}`);
|
|
51
|
+
}
|
|
52
|
+
} catch (error) {
|
|
53
|
+
this.onError?.(error);
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
this.set = async (key, value, options) => {
|
|
58
|
+
try {
|
|
59
|
+
const optionalHeaders = {};
|
|
60
|
+
if (options?.ttl) {
|
|
61
|
+
optionalHeaders[import_index.HEADERS_VERCEL_REVALIDATE] = options.ttl.toString();
|
|
62
|
+
}
|
|
63
|
+
if (options?.tags && options.tags.length > 0) {
|
|
64
|
+
optionalHeaders[import_index.HEADERS_VERCEL_CACHE_TAGS] = options.tags.join(",");
|
|
65
|
+
}
|
|
66
|
+
if (options?.name) {
|
|
67
|
+
optionalHeaders[import_index.HEADERS_VERCEL_CACHE_ITEM_NAME] = options.name;
|
|
68
|
+
}
|
|
69
|
+
const res = await fetch(`${this.endpoint}${key}`, {
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: {
|
|
72
|
+
...this.headers,
|
|
73
|
+
...optionalHeaders
|
|
74
|
+
},
|
|
75
|
+
body: JSON.stringify(value)
|
|
76
|
+
});
|
|
77
|
+
if (res.status !== 200) {
|
|
78
|
+
throw new Error(`Failed to set cache: ${res.status} ${res.statusText}`);
|
|
79
|
+
}
|
|
80
|
+
} catch (error) {
|
|
81
|
+
this.onError?.(error);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
this.delete = async (key) => {
|
|
85
|
+
try {
|
|
86
|
+
const res = await fetch(`${this.endpoint}${key}`, {
|
|
87
|
+
method: "DELETE",
|
|
88
|
+
headers: this.headers
|
|
89
|
+
});
|
|
90
|
+
if (res.status !== 200) {
|
|
91
|
+
throw new Error(`Failed to delete cache: ${res.statusText}`);
|
|
92
|
+
}
|
|
93
|
+
} catch (error) {
|
|
94
|
+
this.onError?.(error);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
this.expireTag = async (tag) => {
|
|
98
|
+
try {
|
|
99
|
+
if (Array.isArray(tag)) {
|
|
100
|
+
tag = tag.join(",");
|
|
101
|
+
}
|
|
102
|
+
const res = await fetch(`${this.endpoint}revalidate?tags=${tag}`, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: this.headers
|
|
105
|
+
});
|
|
106
|
+
if (res.status !== 200) {
|
|
107
|
+
throw new Error(`Failed to revalidate tag: ${res.statusText}`);
|
|
108
|
+
}
|
|
109
|
+
} catch (error) {
|
|
110
|
+
this.onError?.(error);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
this.endpoint = endpoint;
|
|
114
|
+
this.headers = headers;
|
|
115
|
+
this.onError = onError;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
119
|
+
0 && (module.exports = {
|
|
120
|
+
BuildCache
|
|
121
|
+
});
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { RuntimeCache } from './types';
|
|
2
2
|
export declare class InMemoryCache implements RuntimeCache {
|
|
3
3
|
private cache;
|
|
4
|
-
get(key: string
|
|
5
|
-
tags?: string[];
|
|
6
|
-
}): Promise<unknown | null>;
|
|
4
|
+
get(key: string): Promise<unknown | null>;
|
|
7
5
|
set(key: string, value: unknown, options?: {
|
|
8
6
|
ttl?: number;
|
|
9
7
|
tags?: string[];
|
package/cache/in-memory-cache.js
CHANGED
|
@@ -25,18 +25,13 @@ class InMemoryCache {
|
|
|
25
25
|
constructor() {
|
|
26
26
|
this.cache = {};
|
|
27
27
|
}
|
|
28
|
-
async get(key
|
|
28
|
+
async get(key) {
|
|
29
29
|
const entry = this.cache[key];
|
|
30
30
|
if (entry) {
|
|
31
31
|
if (entry.ttl && entry.lastModified + entry.ttl * 1e3 < Date.now()) {
|
|
32
32
|
await this.delete(key);
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
|
-
if (options?.tags) {
|
|
36
|
-
for (const tag of options.tags) {
|
|
37
|
-
entry.tags.add(tag);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
35
|
return entry.value;
|
|
41
36
|
}
|
|
42
37
|
return null;
|
package/cache/index.d.ts
CHANGED
|
@@ -14,3 +14,14 @@ import { CacheOptions, RuntimeCache } from './types';
|
|
|
14
14
|
* @throws {Error} If no cache is available in the context and `InMemoryCache` cannot be created.
|
|
15
15
|
*/
|
|
16
16
|
export declare const getCache: (cacheOptions?: CacheOptions) => RuntimeCache;
|
|
17
|
+
export declare enum PkgCacheState {
|
|
18
|
+
Fresh = "fresh",
|
|
19
|
+
Stale = "stale",
|
|
20
|
+
Expired = "expired",
|
|
21
|
+
NotFound = "notFound",
|
|
22
|
+
Error = "error"
|
|
23
|
+
}
|
|
24
|
+
export declare const HEADERS_VERCEL_CACHE_STATE = "x-vercel-cache-state";
|
|
25
|
+
export declare const HEADERS_VERCEL_REVALIDATE = "x-vercel-revalidate";
|
|
26
|
+
export declare const HEADERS_VERCEL_CACHE_TAGS = "x-vercel-cache-tags";
|
|
27
|
+
export declare const HEADERS_VERCEL_CACHE_ITEM_NAME = "x-vercel-cache-item-name";
|
package/cache/index.js
CHANGED
|
@@ -18,11 +18,17 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var cache_exports = {};
|
|
20
20
|
__export(cache_exports, {
|
|
21
|
+
HEADERS_VERCEL_CACHE_ITEM_NAME: () => HEADERS_VERCEL_CACHE_ITEM_NAME,
|
|
22
|
+
HEADERS_VERCEL_CACHE_STATE: () => HEADERS_VERCEL_CACHE_STATE,
|
|
23
|
+
HEADERS_VERCEL_CACHE_TAGS: () => HEADERS_VERCEL_CACHE_TAGS,
|
|
24
|
+
HEADERS_VERCEL_REVALIDATE: () => HEADERS_VERCEL_REVALIDATE,
|
|
25
|
+
PkgCacheState: () => PkgCacheState,
|
|
21
26
|
getCache: () => getCache
|
|
22
27
|
});
|
|
23
28
|
module.exports = __toCommonJS(cache_exports);
|
|
24
29
|
var import_get_context = require("../get-context");
|
|
25
30
|
var import_in_memory_cache = require("./in-memory-cache");
|
|
31
|
+
var import_build_client = require("./build-client");
|
|
26
32
|
const defaultKeyHashFunction = (key) => {
|
|
27
33
|
let hash = 5381;
|
|
28
34
|
for (let i = 0; i < key.length; i++) {
|
|
@@ -32,31 +38,37 @@ const defaultKeyHashFunction = (key) => {
|
|
|
32
38
|
};
|
|
33
39
|
const defaultNamespaceSeparator = "$";
|
|
34
40
|
let inMemoryCacheInstance = null;
|
|
41
|
+
let buildCacheInstance = null;
|
|
35
42
|
const getCache = (cacheOptions) => {
|
|
36
43
|
const resolveCache = () => {
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"Runtime Cache unavailable in this environment. Falling back to in-memory cache."
|
|
44
|
+
let cache;
|
|
45
|
+
if ((0, import_get_context.getContext)().cache) {
|
|
46
|
+
cache = (0, import_get_context.getContext)().cache;
|
|
47
|
+
} else {
|
|
48
|
+
cache = getCacheImplementation(
|
|
49
|
+
process.env.SUSPENSE_CACHE_DEBUG === "true"
|
|
44
50
|
);
|
|
45
51
|
}
|
|
46
|
-
return
|
|
52
|
+
return cache;
|
|
47
53
|
};
|
|
54
|
+
return wrapWithKeyTransformation(
|
|
55
|
+
resolveCache,
|
|
56
|
+
createKeyTransformer(cacheOptions)
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
function createKeyTransformer(cacheOptions) {
|
|
48
60
|
const hashFunction = cacheOptions?.keyHashFunction || defaultKeyHashFunction;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
return `${prefix}${hashFunction(key)}`;
|
|
61
|
+
return (key) => {
|
|
62
|
+
if (!cacheOptions?.namespace)
|
|
63
|
+
return hashFunction(key);
|
|
64
|
+
const separator = cacheOptions.namespaceSeparator || defaultNamespaceSeparator;
|
|
65
|
+
return `${cacheOptions.namespace}${separator}${hashFunction(key)}`;
|
|
56
66
|
};
|
|
67
|
+
}
|
|
68
|
+
function wrapWithKeyTransformation(resolveCache, makeKey) {
|
|
57
69
|
return {
|
|
58
|
-
get: (key
|
|
59
|
-
return resolveCache().get(makeKey(key)
|
|
70
|
+
get: (key) => {
|
|
71
|
+
return resolveCache().get(makeKey(key));
|
|
60
72
|
},
|
|
61
73
|
set: (key, value, options) => {
|
|
62
74
|
return resolveCache().set(makeKey(key), value, options);
|
|
@@ -68,8 +80,62 @@ const getCache = (cacheOptions) => {
|
|
|
68
80
|
return resolveCache().expireTag(tag);
|
|
69
81
|
}
|
|
70
82
|
};
|
|
71
|
-
}
|
|
83
|
+
}
|
|
84
|
+
function getCacheImplementation(debug) {
|
|
85
|
+
if (!inMemoryCacheInstance) {
|
|
86
|
+
inMemoryCacheInstance = new import_in_memory_cache.InMemoryCache();
|
|
87
|
+
}
|
|
88
|
+
if (process.env.RUNTIME_CACHE_DISABLE_BUILD_CACHE === "true") {
|
|
89
|
+
debug && console.log("Using InMemoryCache as build cache is disabled");
|
|
90
|
+
return inMemoryCacheInstance;
|
|
91
|
+
}
|
|
92
|
+
const { RUNTIME_CACHE_ENDPOINT, RUNTIME_CACHE_HEADERS } = process.env;
|
|
93
|
+
if (debug) {
|
|
94
|
+
console.log("Runtime cache environment variables:", {
|
|
95
|
+
RUNTIME_CACHE_ENDPOINT,
|
|
96
|
+
RUNTIME_CACHE_HEADERS
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
if (!RUNTIME_CACHE_ENDPOINT || !RUNTIME_CACHE_HEADERS) {
|
|
100
|
+
console.warn(
|
|
101
|
+
"Runtime Cache unavailable in this environment. Falling back to in-memory cache."
|
|
102
|
+
);
|
|
103
|
+
return inMemoryCacheInstance;
|
|
104
|
+
}
|
|
105
|
+
if (!buildCacheInstance) {
|
|
106
|
+
let parsedHeaders = {};
|
|
107
|
+
try {
|
|
108
|
+
parsedHeaders = JSON.parse(RUNTIME_CACHE_HEADERS);
|
|
109
|
+
} catch (e) {
|
|
110
|
+
console.error("Failed to parse RUNTIME_CACHE_HEADERS:", e);
|
|
111
|
+
return inMemoryCacheInstance;
|
|
112
|
+
}
|
|
113
|
+
buildCacheInstance = new import_build_client.BuildCache({
|
|
114
|
+
endpoint: RUNTIME_CACHE_ENDPOINT,
|
|
115
|
+
headers: parsedHeaders,
|
|
116
|
+
onError: (error) => console.error(error)
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return buildCacheInstance;
|
|
120
|
+
}
|
|
121
|
+
var PkgCacheState = /* @__PURE__ */ ((PkgCacheState2) => {
|
|
122
|
+
PkgCacheState2["Fresh"] = "fresh";
|
|
123
|
+
PkgCacheState2["Stale"] = "stale";
|
|
124
|
+
PkgCacheState2["Expired"] = "expired";
|
|
125
|
+
PkgCacheState2["NotFound"] = "notFound";
|
|
126
|
+
PkgCacheState2["Error"] = "error";
|
|
127
|
+
return PkgCacheState2;
|
|
128
|
+
})(PkgCacheState || {});
|
|
129
|
+
const HEADERS_VERCEL_CACHE_STATE = "x-vercel-cache-state";
|
|
130
|
+
const HEADERS_VERCEL_REVALIDATE = "x-vercel-revalidate";
|
|
131
|
+
const HEADERS_VERCEL_CACHE_TAGS = "x-vercel-cache-tags";
|
|
132
|
+
const HEADERS_VERCEL_CACHE_ITEM_NAME = "x-vercel-cache-item-name";
|
|
72
133
|
// Annotate the CommonJS export names for ESM import in node:
|
|
73
134
|
0 && (module.exports = {
|
|
135
|
+
HEADERS_VERCEL_CACHE_ITEM_NAME,
|
|
136
|
+
HEADERS_VERCEL_CACHE_STATE,
|
|
137
|
+
HEADERS_VERCEL_CACHE_TAGS,
|
|
138
|
+
HEADERS_VERCEL_REVALIDATE,
|
|
139
|
+
PkgCacheState,
|
|
74
140
|
getCache
|
|
75
141
|
});
|
package/cache/types.d.ts
CHANGED
|
@@ -13,13 +13,9 @@ export interface RuntimeCache {
|
|
|
13
13
|
* Retrieves a value from the cache.
|
|
14
14
|
*
|
|
15
15
|
* @param {string} key - The key of the value to retrieve.
|
|
16
|
-
* @param {Object} [options] - Optional settings for the cache entry.
|
|
17
|
-
* @param {string[]} [options.tags] - Optional tags to associate wit the cache entry.
|
|
18
16
|
* @returns {Promise<unknown | null>} A promise that resolves to the value, or null if not found.
|
|
19
17
|
*/
|
|
20
|
-
get: (key: string
|
|
21
|
-
tags?: string[];
|
|
22
|
-
}) => Promise<unknown | null>;
|
|
18
|
+
get: (key: string) => Promise<unknown | null>;
|
|
23
19
|
/**
|
|
24
20
|
* Sets a value in the cache.
|
|
25
21
|
*
|
|
@@ -67,27 +67,25 @@ A promise that resolves when the cache entries expiration request is received.
|
|
|
67
67
|
|
|
68
68
|
#### Defined in
|
|
69
69
|
|
|
70
|
-
[packages/functions/src/cache/types.ts:
|
|
70
|
+
[packages/functions/src/cache/types.ts:44](https://github.com/vercel/vercel/blob/main/packages/functions/src/cache/types.ts#L44)
|
|
71
71
|
|
|
72
72
|
---
|
|
73
73
|
|
|
74
74
|
### get
|
|
75
75
|
|
|
76
|
-
• **get**: (`key`: `string
|
|
76
|
+
• **get**: (`key`: `string`) => [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<`unknown`\>
|
|
77
77
|
|
|
78
78
|
#### Type declaration
|
|
79
79
|
|
|
80
|
-
▸ (`key
|
|
80
|
+
▸ (`key`): [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)<`unknown`\>
|
|
81
81
|
|
|
82
82
|
Retrieves a value from the cache.
|
|
83
83
|
|
|
84
84
|
##### Parameters
|
|
85
85
|
|
|
86
|
-
| Name
|
|
87
|
-
|
|
|
88
|
-
| `key`
|
|
89
|
-
| `options?` | `Object` | Optional settings for the cache entry. |
|
|
90
|
-
| `options.tags?` | `string`[] | Optional tags to associate wit the cache entry. |
|
|
86
|
+
| Name | Type | Description |
|
|
87
|
+
| :---- | :------- | :-------------------------------- |
|
|
88
|
+
| `key` | `string` | The key of the value to retrieve. |
|
|
91
89
|
|
|
92
90
|
##### Returns
|
|
93
91
|
|
|
@@ -97,7 +95,7 @@ A promise that resolves to the value, or null if not found.
|
|
|
97
95
|
|
|
98
96
|
#### Defined in
|
|
99
97
|
|
|
100
|
-
[packages/functions/src/cache/types.ts:
|
|
98
|
+
[packages/functions/src/cache/types.ts:19](https://github.com/vercel/vercel/blob/main/packages/functions/src/cache/types.ts#L19)
|
|
101
99
|
|
|
102
100
|
---
|
|
103
101
|
|
|
@@ -130,4 +128,4 @@ A promise that resolves when the value is set.
|
|
|
130
128
|
|
|
131
129
|
#### Defined in
|
|
132
130
|
|
|
133
|
-
[packages/functions/src/cache/types.ts:
|
|
131
|
+
[packages/functions/src/cache/types.ts:32](https://github.com/vercel/vercel/blob/main/packages/functions/src/cache/types.ts#L32)
|
package/docs/modules/index.md
CHANGED
|
@@ -99,7 +99,7 @@ An instance of the Vercel Runtime Cache.
|
|
|
99
99
|
|
|
100
100
|
#### Defined in
|
|
101
101
|
|
|
102
|
-
[packages/functions/src/cache/index.ts:
|
|
102
|
+
[packages/functions/src/cache/index.ts:33](https://github.com/vercel/vercel/blob/main/packages/functions/src/cache/index.ts#L33)
|
|
103
103
|
|
|
104
104
|
---
|
|
105
105
|
|