@gcoredev/proxy-wasm-sdk-as 1.0.2 → 1.2.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/assembly/exports.ts +157 -51
- package/assembly/fastedge/env.ts +14 -0
- package/assembly/fastedge/index.ts +4 -0
- package/assembly/fastedge/kvStore.ts +228 -0
- package/assembly/fastedge/secrets.ts +51 -0
- package/assembly/fastedge/utils/index.ts +2 -0
- package/assembly/fastedge/utils/listParser.ts +70 -0
- package/assembly/fastedge/utils/runtime.ts +31 -0
- package/assembly/imports.ts +69 -0
- package/assembly/index.ts +41 -13
- package/assembly/runtime.ts +22 -5
- package/package.json +4 -4
- package/assembly/fastedge.ts +0 -66
package/assembly/exports.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
getBaseContext,
|
|
3
|
+
getContext,
|
|
4
|
+
getRootContext,
|
|
5
|
+
ensureContext,
|
|
6
|
+
ensureRootContext,
|
|
7
|
+
deleteContext,
|
|
8
|
+
PeerTypeValues,
|
|
9
|
+
} from "./runtime";
|
|
2
10
|
|
|
3
11
|
///// CALLS IN
|
|
4
12
|
type FilterStatus = i32;
|
|
@@ -10,17 +18,26 @@ type GrpcStatus = i32;
|
|
|
10
18
|
type WasmOnDoneResult = u32;
|
|
11
19
|
|
|
12
20
|
// Calls in.
|
|
13
|
-
export function proxy_abi_version_0_2_1(): void {
|
|
21
|
+
export function proxy_abi_version_0_2_1(): void {}
|
|
14
22
|
|
|
15
|
-
export function proxy_on_vm_start(
|
|
23
|
+
export function proxy_on_vm_start(
|
|
24
|
+
root_context_id: u32,
|
|
25
|
+
configuration_size: u32
|
|
26
|
+
): u32 {
|
|
16
27
|
let root_context = getRootContext(root_context_id);
|
|
17
28
|
return root_context.onStart(configuration_size) ? 1 : 0;
|
|
18
29
|
}
|
|
19
|
-
export function proxy_validate_configuration(
|
|
30
|
+
export function proxy_validate_configuration(
|
|
31
|
+
root_context_id: u32,
|
|
32
|
+
configuration_size: u32
|
|
33
|
+
): u32 {
|
|
20
34
|
let root_context = getRootContext(root_context_id);
|
|
21
35
|
return root_context.validateConfiguration(configuration_size) ? 1 : 0;
|
|
22
36
|
}
|
|
23
|
-
export function proxy_on_configure(
|
|
37
|
+
export function proxy_on_configure(
|
|
38
|
+
root_context_id: u32,
|
|
39
|
+
configuration_size: u32
|
|
40
|
+
): u32 {
|
|
24
41
|
let root_context = getRootContext(root_context_id);
|
|
25
42
|
return root_context.onConfigure(configuration_size) ? 1 : 0;
|
|
26
43
|
}
|
|
@@ -28,7 +45,11 @@ export function proxy_on_tick(root_context_id: u32): void {
|
|
|
28
45
|
let root_context = getRootContext(root_context_id);
|
|
29
46
|
root_context.onTick();
|
|
30
47
|
}
|
|
31
|
-
export function proxy_on_foreign_function(
|
|
48
|
+
export function proxy_on_foreign_function(
|
|
49
|
+
root_context_id: u32,
|
|
50
|
+
function_id: u32,
|
|
51
|
+
data_size: u32
|
|
52
|
+
): void {
|
|
32
53
|
// TODO: implement me
|
|
33
54
|
}
|
|
34
55
|
|
|
@@ -37,7 +58,10 @@ export function proxy_on_queue_ready(root_context_id: u32, token: u32): void {
|
|
|
37
58
|
root_context.onQueueReady(token);
|
|
38
59
|
}
|
|
39
60
|
// Stream calls.
|
|
40
|
-
export function proxy_on_context_create(
|
|
61
|
+
export function proxy_on_context_create(
|
|
62
|
+
context_id: u32,
|
|
63
|
+
root_context_id: u32
|
|
64
|
+
): void {
|
|
41
65
|
if (root_context_id != 0) {
|
|
42
66
|
ensureContext(context_id, root_context_id);
|
|
43
67
|
} else {
|
|
@@ -45,77 +69,159 @@ export function proxy_on_context_create(context_id: u32, root_context_id: u32):
|
|
|
45
69
|
}
|
|
46
70
|
}
|
|
47
71
|
|
|
48
|
-
export function proxy_on_request_headers(
|
|
72
|
+
export function proxy_on_request_headers(
|
|
73
|
+
context_id: u32,
|
|
74
|
+
headers: u32,
|
|
75
|
+
end_of_stream: u32
|
|
76
|
+
): FilterHeadersStatus {
|
|
49
77
|
let ctx = getContext(context_id);
|
|
50
|
-
return ctx.onRequestHeaders(
|
|
51
|
-
|
|
52
|
-
|
|
78
|
+
return ctx.onRequestHeaders(
|
|
79
|
+
headers,
|
|
80
|
+
end_of_stream != 0
|
|
81
|
+
) as FilterHeadersStatus;
|
|
82
|
+
}
|
|
83
|
+
export function proxy_on_request_body(
|
|
84
|
+
context_id: u32,
|
|
85
|
+
body_buffer_length: u32,
|
|
86
|
+
end_of_stream: u32
|
|
87
|
+
): FilterDataStatus {
|
|
53
88
|
let ctx = getContext(context_id);
|
|
54
|
-
return ctx.onRequestBody(
|
|
55
|
-
|
|
56
|
-
|
|
89
|
+
return ctx.onRequestBody(
|
|
90
|
+
body_buffer_length,
|
|
91
|
+
end_of_stream != 0
|
|
92
|
+
) as FilterDataStatus;
|
|
93
|
+
}
|
|
94
|
+
export function proxy_on_request_trailers(
|
|
95
|
+
context_id: u32,
|
|
96
|
+
trailers: u32
|
|
97
|
+
): FilterTrailersStatus {
|
|
57
98
|
let ctx = getContext(context_id);
|
|
58
99
|
return ctx.onRequestTrailers(trailers) as FilterTrailersStatus;
|
|
59
100
|
}
|
|
60
|
-
export function proxy_on_request_metadata(
|
|
101
|
+
export function proxy_on_request_metadata(
|
|
102
|
+
context_id: u32,
|
|
103
|
+
nelements: u32
|
|
104
|
+
): FilterMetadataStatus {
|
|
61
105
|
let ctx = getContext(context_id);
|
|
62
106
|
return ctx.onRequestMetadata(nelements) as FilterMetadataStatus;
|
|
63
107
|
}
|
|
64
|
-
export function proxy_on_response_headers(
|
|
108
|
+
export function proxy_on_response_headers(
|
|
109
|
+
context_id: u32,
|
|
110
|
+
headers: u32,
|
|
111
|
+
end_of_stream: u32
|
|
112
|
+
): FilterHeadersStatus {
|
|
65
113
|
let ctx = getContext(context_id);
|
|
66
|
-
return ctx.onResponseHeaders(
|
|
67
|
-
|
|
68
|
-
|
|
114
|
+
return ctx.onResponseHeaders(
|
|
115
|
+
headers,
|
|
116
|
+
end_of_stream != 0
|
|
117
|
+
) as FilterHeadersStatus;
|
|
118
|
+
}
|
|
119
|
+
export function proxy_on_response_body(
|
|
120
|
+
context_id: u32,
|
|
121
|
+
body_buffer_length: u32,
|
|
122
|
+
end_of_stream: u32
|
|
123
|
+
): FilterDataStatus {
|
|
69
124
|
let ctx = getContext(context_id);
|
|
70
|
-
return ctx.onResponseBody(
|
|
71
|
-
|
|
72
|
-
|
|
125
|
+
return ctx.onResponseBody(
|
|
126
|
+
body_buffer_length,
|
|
127
|
+
end_of_stream != 0
|
|
128
|
+
) as FilterDataStatus;
|
|
129
|
+
}
|
|
130
|
+
export function proxy_on_response_trailers(
|
|
131
|
+
context_id: u32,
|
|
132
|
+
trailers: u32
|
|
133
|
+
): FilterTrailersStatus {
|
|
73
134
|
let ctx = getContext(context_id);
|
|
74
135
|
return ctx.onResponseTrailers(trailers) as FilterTrailersStatus;
|
|
75
136
|
}
|
|
76
|
-
export function proxy_on_response_metadata(
|
|
137
|
+
export function proxy_on_response_metadata(
|
|
138
|
+
context_id: u32,
|
|
139
|
+
nelements: u32
|
|
140
|
+
): FilterMetadataStatus {
|
|
77
141
|
let ctx = getContext(context_id);
|
|
78
142
|
return ctx.onResponseMetadata(nelements) as FilterMetadataStatus;
|
|
79
143
|
}
|
|
80
144
|
|
|
81
145
|
// HTTP/gRPC.
|
|
82
|
-
export function proxy_on_http_call_response(
|
|
146
|
+
export function proxy_on_http_call_response(
|
|
147
|
+
context_id: u32,
|
|
148
|
+
token: u32,
|
|
149
|
+
headers: u32,
|
|
150
|
+
body_size: u32,
|
|
151
|
+
trailers: u32
|
|
152
|
+
): void {
|
|
83
153
|
let ctx = getRootContext(context_id);
|
|
84
154
|
ctx.onHttpCallResponse(token, headers, body_size, trailers);
|
|
85
155
|
}
|
|
86
|
-
export function proxy_on_grpc_receive_initial_metadata(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
156
|
+
export function proxy_on_grpc_receive_initial_metadata(
|
|
157
|
+
context_id: u32,
|
|
158
|
+
token: u32,
|
|
159
|
+
headers: u32
|
|
160
|
+
): void {
|
|
161
|
+
getRootContext(context_id).on_grpc_receive_initial_metadata(token, headers);
|
|
162
|
+
}
|
|
163
|
+
export function proxy_on_grpc_trailing_metadata(
|
|
164
|
+
context_id: u32,
|
|
165
|
+
token: u32,
|
|
166
|
+
trailers: u32
|
|
167
|
+
): void {
|
|
168
|
+
getRootContext(context_id).on_grpc_trailing_metadata(token, trailers);
|
|
169
|
+
}
|
|
170
|
+
export function proxy_on_grpc_receive(
|
|
171
|
+
context_id: u32,
|
|
172
|
+
token: u32,
|
|
173
|
+
response_size: u32
|
|
174
|
+
): void {
|
|
175
|
+
getRootContext(context_id).on_grpc_receive(token, response_size);
|
|
176
|
+
}
|
|
177
|
+
export function proxy_on_grpc_close(
|
|
178
|
+
context_id: u32,
|
|
179
|
+
token: u32,
|
|
180
|
+
status_code: u32
|
|
181
|
+
): void {
|
|
182
|
+
getRootContext(context_id).on_grpc_close(token, status_code);
|
|
97
183
|
}
|
|
98
184
|
|
|
99
185
|
// NETWORK_FILTER support (TCP and, perhaps one day, UDP).
|
|
100
|
-
export function proxy_on_downstream_data(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
186
|
+
export function proxy_on_downstream_data(
|
|
187
|
+
context_id: u32,
|
|
188
|
+
body_buffer_length: u32,
|
|
189
|
+
end_of_stream: u32
|
|
190
|
+
): FilterStatus {
|
|
191
|
+
let ctx = getContext(context_id);
|
|
192
|
+
return ctx.onDownstreamData(
|
|
193
|
+
body_buffer_length,
|
|
194
|
+
end_of_stream != 0
|
|
195
|
+
) as FilterStatus;
|
|
196
|
+
}
|
|
197
|
+
export function proxy_on_upstream_data(
|
|
198
|
+
context_id: u32,
|
|
199
|
+
body_buffer_length: u32,
|
|
200
|
+
end_of_stream: u32
|
|
201
|
+
): FilterStatus {
|
|
202
|
+
let ctx = getContext(context_id);
|
|
203
|
+
return ctx.onUpstreamData(
|
|
204
|
+
body_buffer_length,
|
|
205
|
+
end_of_stream != 0
|
|
206
|
+
) as FilterStatus;
|
|
207
|
+
}
|
|
208
|
+
export function proxy_on_upstream_connection_close(
|
|
209
|
+
context_id: u32,
|
|
210
|
+
peer_type: u32
|
|
211
|
+
): void {
|
|
212
|
+
let ctx = getContext(context_id);
|
|
213
|
+
ctx.onUpstreamConnectionClose(peer_type as PeerTypeValues);
|
|
111
214
|
}
|
|
112
|
-
export function proxy_on_downstream_connection_close(
|
|
113
|
-
|
|
114
|
-
|
|
215
|
+
export function proxy_on_downstream_connection_close(
|
|
216
|
+
context_id: u32,
|
|
217
|
+
peer_type: u32
|
|
218
|
+
): void {
|
|
219
|
+
let ctx = getContext(context_id);
|
|
220
|
+
ctx.onDownstreamConnectionClose(peer_type as PeerTypeValues);
|
|
115
221
|
}
|
|
116
222
|
export function proxy_on_new_connection(context_id: u32): FilterStatus {
|
|
117
|
-
|
|
118
|
-
|
|
223
|
+
let ctx = getContext(context_id);
|
|
224
|
+
return ctx.onNewConnection() as FilterStatus;
|
|
119
225
|
}
|
|
120
226
|
|
|
121
227
|
// The stream/vm has completed.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function to get the value for the provided environment variable name.
|
|
3
|
+
* @param {string} name - The name of the environment variable.
|
|
4
|
+
* @returns {string} The value of the environment variable.
|
|
5
|
+
*/
|
|
6
|
+
function getEnvVar(name: string): string {
|
|
7
|
+
const hasKey = process.env.has(name);
|
|
8
|
+
if (hasKey) {
|
|
9
|
+
return process.env.get(name);
|
|
10
|
+
}
|
|
11
|
+
return "";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { getEnvVar };
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import * as imports from "../imports";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
globalArrayBufferReference,
|
|
5
|
+
Reference,
|
|
6
|
+
WasmResultValues,
|
|
7
|
+
} from "../runtime";
|
|
8
|
+
import { ItemParser, StringParser, parseBufferToList } from "./utils";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* KvStore provides access to the FastEdge Key-Value store
|
|
12
|
+
*/
|
|
13
|
+
export class KvStore {
|
|
14
|
+
private handle: u32;
|
|
15
|
+
|
|
16
|
+
private constructor(handle: u32) {
|
|
17
|
+
this.handle = handle;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Opens a connection to the specified KV store
|
|
22
|
+
* @param storeName - The name of the KV store to open
|
|
23
|
+
* @returns A new KvStore instance or null if the store cannot be opened
|
|
24
|
+
*/
|
|
25
|
+
static open(storeName: string): KvStore | null {
|
|
26
|
+
const buffer = String.UTF8.encode(storeName);
|
|
27
|
+
const returnHandlerRef = new Reference<u32>();
|
|
28
|
+
|
|
29
|
+
const status = imports.proxy_kv_store_open(
|
|
30
|
+
changetype<usize>(buffer),
|
|
31
|
+
buffer.byteLength,
|
|
32
|
+
returnHandlerRef.ptr() as u32
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
if (status == WasmResultValues.Ok) {
|
|
36
|
+
return new KvStore(returnHandlerRef.data);
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Retrieves the value associated with the given key from the KV store.
|
|
43
|
+
* @param {string} key The key to retrieve the value for.
|
|
44
|
+
* @returns {ArrayBuffer | null} The value associated with the key, or null if not found.
|
|
45
|
+
*/
|
|
46
|
+
get(key: string): ArrayBuffer | null {
|
|
47
|
+
const buffer = String.UTF8.encode(key);
|
|
48
|
+
const status = imports.proxy_kv_store_get(
|
|
49
|
+
this.getHandle(),
|
|
50
|
+
changetype<usize>(buffer),
|
|
51
|
+
buffer.byteLength,
|
|
52
|
+
globalArrayBufferReference.bufferPtr(),
|
|
53
|
+
globalArrayBufferReference.sizePtr()
|
|
54
|
+
);
|
|
55
|
+
if (status == WasmResultValues.Ok) {
|
|
56
|
+
return globalArrayBufferReference.toArrayBuffer();
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Retrieves all key prefix matches from the KV store.
|
|
63
|
+
* @param {string} pattern The prefix pattern to match keys against. e.g. 'foo*' ( Must include wildcard )
|
|
64
|
+
* @returns {Array<string>} The keys matching the pattern, or empty array if none found.
|
|
65
|
+
*/
|
|
66
|
+
scan(pattern: string): Array<string> {
|
|
67
|
+
const match = String.UTF8.encode(pattern);
|
|
68
|
+
const status = imports.proxy_kv_store_scan(
|
|
69
|
+
this.getHandle(),
|
|
70
|
+
changetype<usize>(match),
|
|
71
|
+
match.byteLength,
|
|
72
|
+
globalArrayBufferReference.bufferPtr(),
|
|
73
|
+
globalArrayBufferReference.sizePtr()
|
|
74
|
+
);
|
|
75
|
+
if (status == WasmResultValues.Ok) {
|
|
76
|
+
return parseBufferToList<string>(
|
|
77
|
+
globalArrayBufferReference.toArrayBuffer(),
|
|
78
|
+
new StringParser()
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
return new Array<string>();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Retrieves all the values from ZSet with scores between the given range.
|
|
86
|
+
* @param {string} key The key for the Sorted Set.
|
|
87
|
+
* @param {f64} min The minimum score for the range.
|
|
88
|
+
* @param {f64} max The maximum score for the range.
|
|
89
|
+
* @returns {Array<ValueScoreTuple>} Array of [value, score] tuples within range for the key, or an empty array if none found.
|
|
90
|
+
*/
|
|
91
|
+
zrangeByScore(key: string, min: f64, max: f64): Array<ValueScoreTuple> {
|
|
92
|
+
const keyBuffer = String.UTF8.encode(key);
|
|
93
|
+
const status = imports.proxy_kv_store_zrange_by_score(
|
|
94
|
+
this.getHandle(),
|
|
95
|
+
changetype<usize>(keyBuffer),
|
|
96
|
+
keyBuffer.byteLength,
|
|
97
|
+
min,
|
|
98
|
+
max,
|
|
99
|
+
globalArrayBufferReference.bufferPtr(),
|
|
100
|
+
globalArrayBufferReference.sizePtr()
|
|
101
|
+
);
|
|
102
|
+
if (status == WasmResultValues.Ok) {
|
|
103
|
+
return parseBufferToList<ValueScoreTuple>(
|
|
104
|
+
globalArrayBufferReference.toArrayBuffer(),
|
|
105
|
+
new ValueScoreTupleParser()
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
return new Array<ValueScoreTuple>();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Retrieves all value prefix matches from the KV ZSet.
|
|
113
|
+
* @param {string} key The key for the Sorted Set.
|
|
114
|
+
* @param {string} pattern The prefix pattern to match values against. e.g. 'foo*' ( Must include wildcard )
|
|
115
|
+
* @returns {Array<ValueScoreTuple>} Array of [value, score] tuples which match the prefix pattern, or an empty array if none found.
|
|
116
|
+
*/
|
|
117
|
+
zscan(key: string, pattern: string): Array<ValueScoreTuple> {
|
|
118
|
+
const match = String.UTF8.encode(pattern);
|
|
119
|
+
const keyBuffer = String.UTF8.encode(key);
|
|
120
|
+
const status = imports.proxy_kv_store_zscan(
|
|
121
|
+
this.getHandle(),
|
|
122
|
+
changetype<usize>(keyBuffer),
|
|
123
|
+
keyBuffer.byteLength,
|
|
124
|
+
changetype<usize>(match),
|
|
125
|
+
match.byteLength,
|
|
126
|
+
globalArrayBufferReference.bufferPtr(),
|
|
127
|
+
globalArrayBufferReference.sizePtr()
|
|
128
|
+
);
|
|
129
|
+
if (status == WasmResultValues.Ok) {
|
|
130
|
+
return parseBufferToList<ValueScoreTuple>(
|
|
131
|
+
globalArrayBufferReference.toArrayBuffer(),
|
|
132
|
+
new ValueScoreTupleParser()
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
return new Array<ValueScoreTuple>();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Checks if a given item exists within the KV stores Bloom Filter.
|
|
140
|
+
* @param {string} key The key for the Bloom Filter.
|
|
141
|
+
* @param {string} item The item to check for existence.
|
|
142
|
+
* @returns {boolean} True if the item exists, false otherwise.
|
|
143
|
+
*/
|
|
144
|
+
bfExists(key: string, item: string): boolean {
|
|
145
|
+
const keyBuffer = String.UTF8.encode(key);
|
|
146
|
+
const itemBuffer = String.UTF8.encode(item);
|
|
147
|
+
const returnHandlerRef = new Reference<u32>();
|
|
148
|
+
|
|
149
|
+
const status = imports.proxy_kv_store_bf_exists(
|
|
150
|
+
this.getHandle(),
|
|
151
|
+
changetype<usize>(keyBuffer),
|
|
152
|
+
keyBuffer.byteLength,
|
|
153
|
+
changetype<usize>(itemBuffer),
|
|
154
|
+
itemBuffer.byteLength,
|
|
155
|
+
returnHandlerRef.ptr() as u32
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
if (status == WasmResultValues.Ok) {
|
|
159
|
+
return returnHandlerRef.data != 0;
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Gets the handle of this KV store instance
|
|
166
|
+
* @returns The handle
|
|
167
|
+
*/
|
|
168
|
+
getHandle(): u32 {
|
|
169
|
+
return this.handle;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export class ValueScoreTuple {
|
|
174
|
+
value: ArrayBuffer;
|
|
175
|
+
score: number;
|
|
176
|
+
|
|
177
|
+
constructor(value: ArrayBuffer, score: number) {
|
|
178
|
+
this.value = value;
|
|
179
|
+
this.score = score;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ValueScoreTuple parser implementation
|
|
184
|
+
class ValueScoreTupleParser extends ItemParser<ValueScoreTuple> {
|
|
185
|
+
parseItem(
|
|
186
|
+
buffer: ArrayBuffer,
|
|
187
|
+
dataIndex: u32,
|
|
188
|
+
itemSize: u32
|
|
189
|
+
): ValueScoreTuple | null {
|
|
190
|
+
// Each item contains value bytes + 8-byte f64 score
|
|
191
|
+
const scoreSize: u32 = 8; // f64 = 8 bytes
|
|
192
|
+
if (itemSize < scoreSize) {
|
|
193
|
+
// Invalid item, skip
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const valueSize = itemSize - scoreSize;
|
|
198
|
+
|
|
199
|
+
// Extract value data
|
|
200
|
+
const valueData = buffer.slice(
|
|
201
|
+
<i32>dataIndex,
|
|
202
|
+
<i32>(dataIndex + valueSize)
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
// Extract score data (last 8 bytes of the item)
|
|
206
|
+
const scoreData = buffer.slice(
|
|
207
|
+
<i32>(dataIndex + valueSize),
|
|
208
|
+
<i32>(dataIndex + itemSize)
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
// Convert score bytes to f64 (little-endian)
|
|
212
|
+
const scoreBytes = new Uint8Array(scoreSize);
|
|
213
|
+
const sourceScoreBytes = Uint8Array.wrap(scoreData);
|
|
214
|
+
for (let j: u32 = 0; j < scoreSize; j++) {
|
|
215
|
+
scoreBytes[j] = sourceScoreBytes[j];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Convert little-endian bytes to f64
|
|
219
|
+
const scoreView = new DataView(scoreBytes.buffer);
|
|
220
|
+
const score = scoreView.getFloat64(0, true); // true = little-endian
|
|
221
|
+
|
|
222
|
+
return new ValueScoreTuple(valueData, score);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
createEmptyArray(): Array<ValueScoreTuple> {
|
|
226
|
+
return new Array<ValueScoreTuple>();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as imports from "../imports";
|
|
2
|
+
|
|
3
|
+
import { globalArrayBufferReference, WasmResultValues } from "../runtime";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Function to get the value for the provided secret variable name.
|
|
7
|
+
* @param {string} name - The name of the secret variable.
|
|
8
|
+
* @returns {string} The value of the secret variable.
|
|
9
|
+
*/
|
|
10
|
+
function getSecretVar(name: string): string {
|
|
11
|
+
const buffer = String.UTF8.encode(name);
|
|
12
|
+
const status = imports.proxy_get_secret(
|
|
13
|
+
changetype<usize>(buffer),
|
|
14
|
+
buffer.byteLength,
|
|
15
|
+
globalArrayBufferReference.bufferPtr(),
|
|
16
|
+
globalArrayBufferReference.sizePtr()
|
|
17
|
+
);
|
|
18
|
+
if (status == WasmResultValues.Ok) {
|
|
19
|
+
const arrBuff = globalArrayBufferReference.toArrayBuffer();
|
|
20
|
+
if (arrBuff.byteLength > 0) {
|
|
21
|
+
return String.UTF8.decode(arrBuff);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return "";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Function to get the value for the provided secret variable name from a specific slot.
|
|
29
|
+
* @param {string} name - The name of the secret variable.
|
|
30
|
+
* @param {u32} effectiveAt - The slot index of the secret. (effectiveAt >= secret_slots.slot)
|
|
31
|
+
* @returns {string} The value of the secret variable.
|
|
32
|
+
*/
|
|
33
|
+
function getSecretVarEffectiveAt(name: string, effectiveAt: u32): string {
|
|
34
|
+
const buffer = String.UTF8.encode(name);
|
|
35
|
+
const status = imports.proxy_get_effective_at_secret(
|
|
36
|
+
changetype<usize>(buffer),
|
|
37
|
+
buffer.byteLength,
|
|
38
|
+
effectiveAt,
|
|
39
|
+
globalArrayBufferReference.bufferPtr(),
|
|
40
|
+
globalArrayBufferReference.sizePtr()
|
|
41
|
+
);
|
|
42
|
+
if (status == WasmResultValues.Ok) {
|
|
43
|
+
const arrBuff = globalArrayBufferReference.toArrayBuffer();
|
|
44
|
+
if (arrBuff.byteLength > 0) {
|
|
45
|
+
return String.UTF8.decode(arrBuff);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { getSecretVar, getSecretVarEffectiveAt };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Abstract base class for item parsers
|
|
2
|
+
abstract class ItemParser<T> {
|
|
3
|
+
abstract parseItem(
|
|
4
|
+
buffer: ArrayBuffer,
|
|
5
|
+
dataIndex: u32,
|
|
6
|
+
itemSize: u32
|
|
7
|
+
): T | null;
|
|
8
|
+
abstract createEmptyArray(): Array<T>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// String parser implementation
|
|
12
|
+
class StringParser extends ItemParser<string> {
|
|
13
|
+
parseItem(buffer: ArrayBuffer, dataIndex: u32, itemSize: u32): string | null {
|
|
14
|
+
// Extract string data
|
|
15
|
+
const stringData = buffer.slice(
|
|
16
|
+
<i32>dataIndex,
|
|
17
|
+
<i32>(dataIndex + itemSize)
|
|
18
|
+
);
|
|
19
|
+
return String.UTF8.decode(stringData);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
createEmptyArray(): Array<string> {
|
|
23
|
+
return new Array<string>();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Generic deserialization function
|
|
28
|
+
function parseBufferToList<T>(
|
|
29
|
+
buffer: ArrayBuffer,
|
|
30
|
+
parser: ItemParser<T>
|
|
31
|
+
): Array<T> {
|
|
32
|
+
// Check if buffer is valid
|
|
33
|
+
if (!buffer || buffer.byteLength === 0) {
|
|
34
|
+
return parser.createEmptyArray();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Read number of items
|
|
38
|
+
const numItems = Uint32Array.wrap(buffer, 0, 1)[0];
|
|
39
|
+
|
|
40
|
+
if (numItems === 0) {
|
|
41
|
+
return parser.createEmptyArray();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Read sizes array
|
|
45
|
+
const sizes = Uint32Array.wrap(buffer, sizeof<u32>(), numItems);
|
|
46
|
+
|
|
47
|
+
// Start of actual data
|
|
48
|
+
let dataIndex: u32 = sizeof<u32>() * (1 + numItems);
|
|
49
|
+
const result = parser.createEmptyArray();
|
|
50
|
+
|
|
51
|
+
for (let i: u32 = 0; i < numItems; i++) {
|
|
52
|
+
const itemSize = sizes[i];
|
|
53
|
+
|
|
54
|
+
if (dataIndex + itemSize > <u32>buffer.byteLength) {
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const item = parser.parseItem(buffer, dataIndex, itemSize);
|
|
59
|
+
if (item !== null) {
|
|
60
|
+
result.push(item);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Move to next item (including null terminator if present)
|
|
64
|
+
dataIndex += itemSize + 1; // +1 for null terminator
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { ItemParser, StringParser, parseBufferToList };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { get_current_time_nanoseconds, LogLevelValues } from "../../runtime";
|
|
2
|
+
|
|
3
|
+
let logLevel: LogLevelValues = LogLevelValues.info;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Sets the logging level, proxy_get_log_level is not yet implemented in FastEdge.
|
|
7
|
+
* @param {LogLevelValues} level The logging level to set.
|
|
8
|
+
* @returns {void}
|
|
9
|
+
*/
|
|
10
|
+
function setLogLevel(level: LogLevelValues): void {
|
|
11
|
+
logLevel = level;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Temporary fix for proxy_log not being implemented in FastEdge.
|
|
16
|
+
* The function relies on @assemblyscript/wasi-shim to print to standard output.
|
|
17
|
+
* @param {LogLevelValues} level The logging level to use.
|
|
18
|
+
* @param {string} logMessage The logging message to log.
|
|
19
|
+
* @returns {void}
|
|
20
|
+
*/
|
|
21
|
+
function log(level: LogLevelValues, logMessage: string): void {
|
|
22
|
+
if (level >= logLevel) {
|
|
23
|
+
process.stdout.write(logMessage + "\n");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getCurrentTime(): u64 {
|
|
28
|
+
return get_current_time_nanoseconds() / 1_000_000; // Convert nanoseconds to milliseconds
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { getCurrentTime, log, LogLevelValues, setLogLevel };
|
package/assembly/imports.ts
CHANGED
|
@@ -124,6 +124,10 @@ export declare function proxy_get_buffer_bytes(typ: BufferType, start: u32, leng
|
|
|
124
124
|
// @ts-ignore: decorator
|
|
125
125
|
@external("env", "proxy_get_buffer_status")
|
|
126
126
|
export declare function proxy_get_buffer_status(typ: BufferType, length_ptr: ptr<usize>, flags_ptr: ptr<u32>): WasmResult;
|
|
127
|
+
// @ts-ignore: decorator
|
|
128
|
+
@external("env", "proxy_set_buffer_bytes")
|
|
129
|
+
export declare function proxy_set_buffer_bytes(typ: BufferType, start: u32, length: u32, ptr: ptr<ptr<char>>, size: ptr<usize>): WasmResult;
|
|
130
|
+
|
|
127
131
|
|
|
128
132
|
// HTTP
|
|
129
133
|
// @ts-ignore: decorator
|
|
@@ -197,3 +201,68 @@ export declare function proxy_get_effective_at_secret(
|
|
|
197
201
|
return_value_size: usize
|
|
198
202
|
): u32;
|
|
199
203
|
|
|
204
|
+
|
|
205
|
+
// KV Store
|
|
206
|
+
// @ts-ignore: decorator
|
|
207
|
+
@external("env", "proxy_kv_store_open")
|
|
208
|
+
export declare function proxy_kv_store_open(
|
|
209
|
+
key_data: usize,
|
|
210
|
+
key_size: usize,
|
|
211
|
+
return_handle: u32
|
|
212
|
+
): u32;
|
|
213
|
+
|
|
214
|
+
// @ts-ignore: decorator
|
|
215
|
+
@external("env", "proxy_kv_store_get")
|
|
216
|
+
export declare function proxy_kv_store_get(
|
|
217
|
+
handle: u32,
|
|
218
|
+
key_data: usize,
|
|
219
|
+
key_size: usize,
|
|
220
|
+
return_value_data: usize,
|
|
221
|
+
return_value_size: usize,
|
|
222
|
+
): u32;
|
|
223
|
+
|
|
224
|
+
// @ts-ignore: decorator
|
|
225
|
+
@external("env", "proxy_kv_store_scan")
|
|
226
|
+
export declare function proxy_kv_store_scan(
|
|
227
|
+
handle: u32,
|
|
228
|
+
pattern_data: usize,
|
|
229
|
+
pattern_size: usize,
|
|
230
|
+
return_value_data: usize,
|
|
231
|
+
return_value_size: usize,
|
|
232
|
+
): u32;
|
|
233
|
+
|
|
234
|
+
// @ts-ignore: decorator
|
|
235
|
+
@external("env", "proxy_kv_store_zrange_by_score")
|
|
236
|
+
export declare function proxy_kv_store_zrange_by_score(
|
|
237
|
+
handle: u32,
|
|
238
|
+
key_data: usize,
|
|
239
|
+
key_size: usize,
|
|
240
|
+
min: f64,
|
|
241
|
+
max: f64,
|
|
242
|
+
return_value_data: usize,
|
|
243
|
+
return_value_size: usize,
|
|
244
|
+
): u32;
|
|
245
|
+
|
|
246
|
+
// @ts-ignore: decorator
|
|
247
|
+
@external("env", "proxy_kv_store_zscan")
|
|
248
|
+
export declare function proxy_kv_store_zscan(
|
|
249
|
+
handle: u32,
|
|
250
|
+
key_data: usize,
|
|
251
|
+
key_size: usize,
|
|
252
|
+
pattern_data: usize,
|
|
253
|
+
pattern_size: usize,
|
|
254
|
+
return_value_data: usize,
|
|
255
|
+
return_value_size: usize,
|
|
256
|
+
): u32;
|
|
257
|
+
|
|
258
|
+
// @ts-ignore: decorator
|
|
259
|
+
@external("env", "proxy_kv_store_bf_exists")
|
|
260
|
+
export declare function proxy_kv_store_bf_exists(
|
|
261
|
+
handle: u32,
|
|
262
|
+
key_data: usize,
|
|
263
|
+
key_size: usize,
|
|
264
|
+
item_data: usize,
|
|
265
|
+
item_size: usize,
|
|
266
|
+
return_handle: u32,
|
|
267
|
+
): u32;
|
|
268
|
+
|
package/assembly/index.ts
CHANGED
|
@@ -1,15 +1,43 @@
|
|
|
1
1
|
export {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
2
|
+
BaseContext,
|
|
3
|
+
BufferTypeValues,
|
|
4
|
+
call_foreign_function,
|
|
5
|
+
Context,
|
|
6
|
+
continue_request,
|
|
7
|
+
continue_response,
|
|
8
|
+
Counter,
|
|
9
|
+
dequeue_shared_queue,
|
|
10
|
+
enqueue_shared_queue,
|
|
11
|
+
FilterDataStatusValues,
|
|
12
|
+
FilterHeadersStatusValues,
|
|
13
|
+
FilterMetadataStatusValues,
|
|
14
|
+
FilterStatusValues,
|
|
15
|
+
FilterTrailersStatusValues,
|
|
16
|
+
Gauge,
|
|
17
|
+
get_buffer_bytes,
|
|
18
|
+
get_current_time_nanoseconds,
|
|
19
|
+
get_property,
|
|
20
|
+
get_shared_data,
|
|
21
|
+
GetSharedData,
|
|
22
|
+
GrpcStatusValues,
|
|
23
|
+
HeaderPair,
|
|
24
|
+
Headers,
|
|
25
|
+
Histogram,
|
|
26
|
+
HttpCallback,
|
|
27
|
+
log,
|
|
28
|
+
LogLevelValues,
|
|
29
|
+
makeHeaderPair,
|
|
30
|
+
proxy_set_effective_context,
|
|
31
|
+
register_shared_queue,
|
|
32
|
+
registerRootContext,
|
|
33
|
+
resolve_shared_queue,
|
|
34
|
+
RootContext,
|
|
35
|
+
send_http_response,
|
|
36
|
+
send_local_response,
|
|
37
|
+
set_buffer_bytes,
|
|
38
|
+
set_property,
|
|
39
|
+
set_shared_data,
|
|
40
|
+
set_tick_period_milliseconds,
|
|
41
|
+
stream_context,
|
|
42
|
+
WasmResultValues,
|
|
15
43
|
} from "./runtime";
|
package/assembly/runtime.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { free } from "./malloc";
|
|
|
3
3
|
|
|
4
4
|
import { log as wasiLog } from "./fastedge";
|
|
5
5
|
|
|
6
|
+
|
|
6
7
|
// abort function.
|
|
7
8
|
// use with:
|
|
8
9
|
// --use abort=index/abort_proc_exit
|
|
@@ -32,7 +33,6 @@ function CHECK_RESULT(c: imports.WasmResult): void {
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
/////////////// Access helpers
|
|
35
|
-
|
|
36
36
|
export class Reference<T> {
|
|
37
37
|
data: T;
|
|
38
38
|
|
|
@@ -55,8 +55,12 @@ class ArrayBufferReference {
|
|
|
55
55
|
return changetype<usize>(this) + offsetof<ArrayBufferReference>("buffer");
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Before calling toArrayBuffer below, you must call out to the host to fill in the values.
|
|
60
|
+
* toArrayBuffer below **must** be called once and only once.
|
|
61
|
+
* Host code used malloc to allocate this buffer.
|
|
62
|
+
* This method consumes the buffer and handles memory cleanup automatically.
|
|
63
|
+
*/
|
|
60
64
|
toArrayBuffer(): ArrayBuffer {
|
|
61
65
|
if (this.size == 0) {
|
|
62
66
|
return new ArrayBuffer(0);
|
|
@@ -71,6 +75,8 @@ class ArrayBufferReference {
|
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
|
|
78
|
+
|
|
79
|
+
|
|
74
80
|
export const globalArrayBufferReference = new ArrayBufferReference();
|
|
75
81
|
let globalU32Ref = new Reference<u32>();
|
|
76
82
|
let globalLogLevelRef = new Reference<imports.LogLevel>();
|
|
@@ -256,8 +262,12 @@ export function get_current_time_nanoseconds(): u64 {
|
|
|
256
262
|
|
|
257
263
|
export function get_property(path: string): ArrayBuffer {
|
|
258
264
|
let buffer = String.UTF8.encode(path);
|
|
259
|
-
|
|
260
|
-
|
|
265
|
+
const result = imports.proxy_get_property(changetype<usize>(buffer), buffer.byteLength, globalArrayBufferReference.bufferPtr(), globalArrayBufferReference.sizePtr());
|
|
266
|
+
CHECK_RESULT(result);
|
|
267
|
+
if (result == WasmResultValues.Ok) {
|
|
268
|
+
return globalArrayBufferReference.toArrayBuffer();
|
|
269
|
+
}
|
|
270
|
+
return new ArrayBuffer(0); // result == WasmResultValues.NotFound
|
|
261
271
|
}
|
|
262
272
|
|
|
263
273
|
export function set_property(path: string, data: ArrayBuffer): WasmResultValues {
|
|
@@ -627,6 +637,11 @@ export function get_buffer_bytes(typ: BufferTypeValues, start: u32, length: u32)
|
|
|
627
637
|
return new ArrayBuffer(0);
|
|
628
638
|
}
|
|
629
639
|
|
|
640
|
+
export function set_buffer_bytes(typ: BufferTypeValues, start: u32, length: u32, value: ArrayBuffer): WasmResultValues {
|
|
641
|
+
const result = imports.proxy_set_buffer_bytes(typ, start, length, changetype<usize>(value), value.byteLength);
|
|
642
|
+
return result
|
|
643
|
+
}
|
|
644
|
+
|
|
630
645
|
// returning tuples is not supported.
|
|
631
646
|
class BufferStatusResult {
|
|
632
647
|
result: WasmResultValues;
|
|
@@ -1117,3 +1132,5 @@ export function registerRootContext(
|
|
|
1117
1132
|
name: string): void {
|
|
1118
1133
|
root_context_factory = context_factory;
|
|
1119
1134
|
}
|
|
1135
|
+
|
|
1136
|
+
|
package/package.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"name": "@gcoredev/proxy-wasm-sdk-as",
|
|
3
|
+
"description": "Use this SDK to write extensions for the proxy WASM ABI",
|
|
4
|
+
"version": "1.2.0",
|
|
5
|
+
"main": "assembly/index.ts",
|
|
2
6
|
"scripts": {
|
|
3
7
|
"asbuild:debug": "asc assembly/index.ts --target debug",
|
|
4
8
|
"asbuild:release": "asc assembly/index.ts --target release",
|
|
@@ -15,10 +19,6 @@
|
|
|
15
19
|
"minimist": ">=1.2.2",
|
|
16
20
|
"typedoc": "^0.27.7"
|
|
17
21
|
},
|
|
18
|
-
"name": "@gcoredev/proxy-wasm-sdk-as",
|
|
19
|
-
"description": "Use this SDK to write extensions for the proxy WASM ABI",
|
|
20
|
-
"version": "1.0.2",
|
|
21
|
-
"main": "assembly/index.ts",
|
|
22
22
|
"directories": {
|
|
23
23
|
"doc": "docs"
|
|
24
24
|
},
|
package/assembly/fastedge.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import * as imports from "./imports";
|
|
2
|
-
|
|
3
|
-
import { globalArrayBufferReference, LogLevelValues } from "./runtime";
|
|
4
|
-
|
|
5
|
-
let logLevel: LogLevelValues = LogLevelValues.info;
|
|
6
|
-
|
|
7
|
-
export function setLogLevel(level: LogLevelValues): void {
|
|
8
|
-
logLevel = level;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function log(level: LogLevelValues, logMessage: string): void {
|
|
12
|
-
// Temporary fix for proxy_log not being implemented in fastedge:
|
|
13
|
-
// relies on @assemblyscript/wasi-shim to print to standard output
|
|
14
|
-
if (level >= logLevel) {
|
|
15
|
-
process.stdout.write(logMessage + "\n");
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function getEnvVar(key: string): string {
|
|
20
|
-
const hasKey = process.env.has(key);
|
|
21
|
-
if (hasKey) {
|
|
22
|
-
return process.env.get(key);
|
|
23
|
-
}
|
|
24
|
-
return "";
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function getSecretVar(key: string): string {
|
|
28
|
-
const buffer = String.UTF8.encode(key);
|
|
29
|
-
const status = imports.proxy_get_secret(
|
|
30
|
-
changetype<usize>(buffer),
|
|
31
|
-
buffer.byteLength,
|
|
32
|
-
globalArrayBufferReference.bufferPtr(),
|
|
33
|
-
globalArrayBufferReference.sizePtr()
|
|
34
|
-
);
|
|
35
|
-
if (status != 0) {
|
|
36
|
-
// Something went wrong - returns 0 with an empty ArrayBuffer if not found
|
|
37
|
-
return "";
|
|
38
|
-
}
|
|
39
|
-
const arrBuff = globalArrayBufferReference.toArrayBuffer();
|
|
40
|
-
if (arrBuff.byteLength == 0) {
|
|
41
|
-
return ""; // Not found
|
|
42
|
-
}
|
|
43
|
-
return String.UTF8.decode(arrBuff);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function getSecretVarEffectiveAt(key: string, at: u32): string {
|
|
47
|
-
const buffer = String.UTF8.encode(key);
|
|
48
|
-
const status = imports.proxy_get_effective_at_secret(
|
|
49
|
-
changetype<usize>(buffer),
|
|
50
|
-
buffer.byteLength,
|
|
51
|
-
at,
|
|
52
|
-
globalArrayBufferReference.bufferPtr(),
|
|
53
|
-
globalArrayBufferReference.sizePtr()
|
|
54
|
-
);
|
|
55
|
-
if (status != 0) {
|
|
56
|
-
// Something went wrong - returns 0 with an empty ArrayBuffer if not found
|
|
57
|
-
return "";
|
|
58
|
-
}
|
|
59
|
-
const arrBuff = globalArrayBufferReference.toArrayBuffer();
|
|
60
|
-
if (arrBuff.byteLength == 0) {
|
|
61
|
-
return ""; // Not found
|
|
62
|
-
}
|
|
63
|
-
return String.UTF8.decode(arrBuff);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export { LogLevelValues };
|