buildonce 0.32.0 → 0.33.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 +7 -5
- package/lib/index.d.ts +20 -6
- package/lib/index.js +111 -7
- package/package.json +2 -2
- package/prebuilds/darwin-arm64/libonce.dylib +0 -0
- package/prebuilds/darwin-x64/libonce.dylib +0 -0
- package/prebuilds/linux-arm64/libonce.so +0 -0
- package/prebuilds/linux-x64/libonce.so +0 -0
- package/prebuilds/win32-x64/once.dll +0 -0
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Once JavaScript
|
|
1
|
+
# Once JavaScript Software Development Kit
|
|
2
2
|
|
|
3
3
|
`buildonce` exposes Once primitives to Node.js. It loads the same
|
|
4
|
-
native Once library used by the other
|
|
4
|
+
native Once library used by the other language libraries and does not expose script
|
|
5
5
|
execution.
|
|
6
6
|
|
|
7
7
|
```js
|
|
@@ -19,6 +19,8 @@ async function example() {
|
|
|
19
19
|
The package looks for a bundled native library under `prebuilds/`. Set
|
|
20
20
|
`ONCE_LIBRARY_PATH` to load a custom `libonce` build.
|
|
21
21
|
|
|
22
|
-
`
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
Use `new Cache({ workspaceRoot })` to share the effective provider configured
|
|
23
|
+
for a repository, or `new Cache({ localCacheRoot })` for isolation. Use
|
|
24
|
+
`putFile` and `getBlobToFile` for large payloads so the host does not need to
|
|
25
|
+
hold their complete contents in JavaScript memory. `ActionKey` builds a stable
|
|
26
|
+
digest from ordered, labeled inputs.
|
package/lib/index.d.ts
CHANGED
|
@@ -14,21 +14,28 @@ export interface CacheStats {
|
|
|
14
14
|
|
|
15
15
|
export class OnceError extends Error {}
|
|
16
16
|
|
|
17
|
+
export interface CacheOptions {
|
|
18
|
+
localCacheRoot?: string;
|
|
19
|
+
workspaceRoot?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
17
22
|
export class Cache {
|
|
23
|
+
constructor(options?: CacheOptions);
|
|
18
24
|
version(): string;
|
|
19
25
|
/**
|
|
20
|
-
* Strings
|
|
26
|
+
* Strings use Unicode Transformation Format, 8-bit before hashing.
|
|
21
27
|
*/
|
|
22
28
|
digest(bytes: Buffer | Uint8Array | string): string;
|
|
23
29
|
/**
|
|
24
|
-
* Strings
|
|
30
|
+
* Strings use Unicode Transformation Format, 8-bit before being stored.
|
|
25
31
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* streaming native ABI.
|
|
32
|
+
* Use putFile for large blobs to avoid loading the complete payload into
|
|
33
|
+
* JavaScript memory.
|
|
29
34
|
*/
|
|
30
35
|
putBlob(bytes: Buffer | Uint8Array | string): Promise<string>;
|
|
36
|
+
putFile(path: string): Promise<string>;
|
|
31
37
|
getBlob(digest: string): Promise<Buffer>;
|
|
38
|
+
getBlobToFile(digest: string, path: string): Promise<number>;
|
|
32
39
|
hasBlob(digest: string): Promise<boolean>;
|
|
33
40
|
putActionResult(result: ActionResult, actionDigest: string): Promise<boolean>;
|
|
34
41
|
getActionResult(actionDigest: string): Promise<ActionResult | null>;
|
|
@@ -36,7 +43,14 @@ export class Cache {
|
|
|
36
43
|
stats(): Promise<CacheStats>;
|
|
37
44
|
}
|
|
38
45
|
|
|
46
|
+
export class ActionKey {
|
|
47
|
+
constructor(namespace: string);
|
|
48
|
+
addBytes(label: string, bytes: Buffer | Uint8Array | string): this;
|
|
49
|
+
addDigest(label: string, digest: string): this;
|
|
50
|
+
digest(): string;
|
|
51
|
+
}
|
|
52
|
+
|
|
39
53
|
/**
|
|
40
|
-
* Strings
|
|
54
|
+
* Strings use Unicode Transformation Format, 8-bit before hashing.
|
|
41
55
|
*/
|
|
42
56
|
export function digest(bytes: Buffer | Uint8Array | string): string;
|
package/lib/index.js
CHANGED
|
@@ -15,6 +15,26 @@ const native = loadNative();
|
|
|
15
15
|
const DIGEST_PATTERN = /^[0-9a-f]{64}$/;
|
|
16
16
|
|
|
17
17
|
class Cache {
|
|
18
|
+
constructor(options = {}) {
|
|
19
|
+
if (options == null || typeof options !== "object" || Array.isArray(options)) {
|
|
20
|
+
throw new TypeError("Cache options must be an object");
|
|
21
|
+
}
|
|
22
|
+
const { localCacheRoot, workspaceRoot } = options;
|
|
23
|
+
if (localCacheRoot != null && workspaceRoot != null) {
|
|
24
|
+
throw new TypeError("localCacheRoot and workspaceRoot cannot be used together");
|
|
25
|
+
}
|
|
26
|
+
if (localCacheRoot != null && typeof localCacheRoot !== "string") {
|
|
27
|
+
throw new TypeError("localCacheRoot must be a string");
|
|
28
|
+
}
|
|
29
|
+
if (workspaceRoot != null && typeof workspaceRoot !== "string") {
|
|
30
|
+
throw new TypeError("workspaceRoot must be a string");
|
|
31
|
+
}
|
|
32
|
+
this.selection = {
|
|
33
|
+
...(localCacheRoot == null ? {} : { local_cache_root: localCacheRoot }),
|
|
34
|
+
...(workspaceRoot == null ? {} : { workspace_root: workspaceRoot }),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
18
38
|
version() {
|
|
19
39
|
return native.once_version() || "";
|
|
20
40
|
}
|
|
@@ -28,19 +48,43 @@ class Cache {
|
|
|
28
48
|
const buffer = toBuffer(bytes, "Cache#putBlob bytes");
|
|
29
49
|
return decodeRequest(
|
|
30
50
|
native.once_cache_put_blob_json,
|
|
31
|
-
{ bytes: Array.from(buffer) },
|
|
51
|
+
{ ...this.selection, bytes: Array.from(buffer) },
|
|
32
52
|
);
|
|
33
53
|
}
|
|
34
54
|
|
|
55
|
+
async putFile(filePath) {
|
|
56
|
+
validatePath(filePath, "filePath");
|
|
57
|
+
return decodeRequest(native.once_cache_put_file_json, {
|
|
58
|
+
...this.selection,
|
|
59
|
+
path: filePath,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
35
63
|
async getBlob(digest) {
|
|
36
64
|
validateDigest(digest, "digest");
|
|
37
|
-
const response = decodeRequest(native.once_cache_get_blob_json, {
|
|
65
|
+
const response = decodeRequest(native.once_cache_get_blob_json, {
|
|
66
|
+
...this.selection,
|
|
67
|
+
digest,
|
|
68
|
+
});
|
|
38
69
|
return Buffer.from(response.bytes);
|
|
39
70
|
}
|
|
40
71
|
|
|
72
|
+
async getBlobToFile(digest, filePath) {
|
|
73
|
+
validateDigest(digest, "digest");
|
|
74
|
+
validatePath(filePath, "filePath");
|
|
75
|
+
return decodeRequest(native.once_cache_get_blob_to_file_json, {
|
|
76
|
+
...this.selection,
|
|
77
|
+
digest,
|
|
78
|
+
path: filePath,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
41
82
|
async hasBlob(digest) {
|
|
42
83
|
validateDigest(digest, "digest");
|
|
43
|
-
return decodeRequest(native.once_cache_has_blob_json, {
|
|
84
|
+
return decodeRequest(native.once_cache_has_blob_json, {
|
|
85
|
+
...this.selection,
|
|
86
|
+
digest,
|
|
87
|
+
});
|
|
44
88
|
}
|
|
45
89
|
|
|
46
90
|
async putActionResult(result, actionDigest) {
|
|
@@ -48,6 +92,7 @@ class Cache {
|
|
|
48
92
|
return decodeRequest(
|
|
49
93
|
native.once_cache_put_action_result_json,
|
|
50
94
|
{
|
|
95
|
+
...this.selection,
|
|
51
96
|
action_digest: actionDigest,
|
|
52
97
|
result: actionResultToNative(result),
|
|
53
98
|
},
|
|
@@ -58,7 +103,7 @@ class Cache {
|
|
|
58
103
|
validateDigest(actionDigest, "actionDigest");
|
|
59
104
|
const result = decodeRequest(
|
|
60
105
|
native.once_cache_get_action_result_json,
|
|
61
|
-
{ action_digest: actionDigest },
|
|
106
|
+
{ ...this.selection, action_digest: actionDigest },
|
|
62
107
|
);
|
|
63
108
|
return result === null ? null : actionResultFromNative(result);
|
|
64
109
|
}
|
|
@@ -67,12 +112,12 @@ class Cache {
|
|
|
67
112
|
validateDigest(actionDigest, "actionDigest");
|
|
68
113
|
return decodeRequest(
|
|
69
114
|
native.once_cache_forget_action_json,
|
|
70
|
-
{ action_digest: actionDigest },
|
|
115
|
+
{ ...this.selection, action_digest: actionDigest },
|
|
71
116
|
);
|
|
72
117
|
}
|
|
73
118
|
|
|
74
119
|
async stats() {
|
|
75
|
-
const stats = decodeRequest(native.once_cache_stats_json,
|
|
120
|
+
const stats = decodeRequest(native.once_cache_stats_json, this.selection);
|
|
76
121
|
return {
|
|
77
122
|
blobCount: stats.blob_count,
|
|
78
123
|
blobBytes: stats.blob_bytes,
|
|
@@ -82,6 +127,37 @@ class Cache {
|
|
|
82
127
|
}
|
|
83
128
|
}
|
|
84
129
|
|
|
130
|
+
class ActionKey {
|
|
131
|
+
constructor(namespace) {
|
|
132
|
+
if (typeof namespace !== "string") {
|
|
133
|
+
throw new TypeError("ActionKey namespace must be a string");
|
|
134
|
+
}
|
|
135
|
+
this.namespace = namespace;
|
|
136
|
+
this.inputs = [];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
addBytes(label, bytes) {
|
|
140
|
+
validateLabel(label);
|
|
141
|
+
const buffer = toBuffer(bytes, "ActionKey#addBytes bytes");
|
|
142
|
+
this.inputs.push({ kind: "bytes", label, bytes: Array.from(buffer) });
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
addDigest(label, digest) {
|
|
147
|
+
validateLabel(label);
|
|
148
|
+
validateDigest(digest, "digest");
|
|
149
|
+
this.inputs.push({ kind: "digest", label, digest });
|
|
150
|
+
return this;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
digest() {
|
|
154
|
+
return decodeRequest(native.once_action_key_json, {
|
|
155
|
+
namespace: this.namespace,
|
|
156
|
+
inputs: this.inputs,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
85
161
|
function digest(bytes) {
|
|
86
162
|
return new Cache().digest(bytes);
|
|
87
163
|
}
|
|
@@ -103,7 +179,9 @@ function decodeResponse(pointer) {
|
|
|
103
179
|
try {
|
|
104
180
|
response = JSON.parse(pointer);
|
|
105
181
|
} catch (error) {
|
|
106
|
-
throw new OnceError(
|
|
182
|
+
throw new OnceError(
|
|
183
|
+
`native Once response must be valid JavaScript Object Notation: ${error.message}`,
|
|
184
|
+
);
|
|
107
185
|
}
|
|
108
186
|
if (response.status === "ok") {
|
|
109
187
|
return response.value;
|
|
@@ -135,6 +213,18 @@ function validateDigest(value, name) {
|
|
|
135
213
|
}
|
|
136
214
|
}
|
|
137
215
|
|
|
216
|
+
function validateLabel(value) {
|
|
217
|
+
if (typeof value !== "string") {
|
|
218
|
+
throw new TypeError("ActionKey input label must be a string");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function validatePath(value, name) {
|
|
223
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
224
|
+
throw new TypeError(`${name} must be a non-empty string`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
138
228
|
function toBuffer(bytes, name) {
|
|
139
229
|
if (Buffer.isBuffer(bytes)) {
|
|
140
230
|
return bytes;
|
|
@@ -159,16 +249,29 @@ function loadNative() {
|
|
|
159
249
|
"const void *",
|
|
160
250
|
"size_t",
|
|
161
251
|
]),
|
|
252
|
+
once_action_key_json: library.func("once_action_key_json", onceString, [
|
|
253
|
+
"str",
|
|
254
|
+
]),
|
|
162
255
|
once_cache_put_blob_json: library.func(
|
|
163
256
|
"once_cache_put_blob_json",
|
|
164
257
|
onceString,
|
|
165
258
|
["str"],
|
|
166
259
|
),
|
|
260
|
+
once_cache_put_file_json: library.func(
|
|
261
|
+
"once_cache_put_file_json",
|
|
262
|
+
onceString,
|
|
263
|
+
["str"],
|
|
264
|
+
),
|
|
167
265
|
once_cache_get_blob_json: library.func(
|
|
168
266
|
"once_cache_get_blob_json",
|
|
169
267
|
onceString,
|
|
170
268
|
["str"],
|
|
171
269
|
),
|
|
270
|
+
once_cache_get_blob_to_file_json: library.func(
|
|
271
|
+
"once_cache_get_blob_to_file_json",
|
|
272
|
+
onceString,
|
|
273
|
+
["str"],
|
|
274
|
+
),
|
|
172
275
|
once_cache_has_blob_json: library.func(
|
|
173
276
|
"once_cache_has_blob_json",
|
|
174
277
|
onceString,
|
|
@@ -229,6 +332,7 @@ function libraryName() {
|
|
|
229
332
|
}
|
|
230
333
|
|
|
231
334
|
module.exports = {
|
|
335
|
+
ActionKey,
|
|
232
336
|
Cache,
|
|
233
337
|
OnceError,
|
|
234
338
|
digest,
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|