@gcoredev/fastedge-test 0.2.1 → 0.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/bin/fastedge-debug.js +38 -3
- package/dist/fastedge-cli/METADATA.json +1 -1
- package/dist/fastedge-cli/fastedge-run-darwin-arm64 +0 -0
- package/dist/fastedge-cli/fastedge-run-linux-x64 +0 -0
- package/dist/fastedge-cli/fastedge-run.exe +0 -0
- package/dist/lib/index.cjs +59 -28
- package/dist/lib/index.js +62 -29
- package/dist/lib/runner/HostFunctions.d.ts +1 -0
- package/dist/lib/test-framework/index.cjs +59 -28
- package/dist/lib/test-framework/index.js +61 -29
- package/dist/lib/utils/fastedge-cli.d.ts +36 -1
- package/dist/server.js +29 -29
- package/docs/DEBUGGER.md +24 -4
- package/docs/TEST_CONFIG.md +19 -19
- package/docs/TEST_FRAMEWORK.md +7 -7
- package/package.json +2 -2
package/bin/fastedge-debug.js
CHANGED
|
@@ -34,8 +34,43 @@ function resolveAppRoot(startPath) {
|
|
|
34
34
|
return dir;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
// Parse `--project-dir <path>` / `--project-dir=<path>` and strip it from argv
|
|
38
|
+
// before the server import, so the server's own arg handling doesn't see it.
|
|
39
|
+
// When set, it overrides the positional fallback for resolveAppRoot — useful
|
|
40
|
+
// when running from a nested sandbox (e.g. `cd fastedge-test && npm run debug`
|
|
41
|
+
// with the project root one directory up).
|
|
42
|
+
function extractProjectDirFlag(argv) {
|
|
43
|
+
for (let i = 2; i < argv.length; i++) {
|
|
44
|
+
const a = argv[i];
|
|
45
|
+
if (a === "--project-dir" || a === "-C") {
|
|
46
|
+
const value = argv[i + 1];
|
|
47
|
+
if (!value) {
|
|
48
|
+
console.error(`Error: ${a} requires a path argument.`);
|
|
49
|
+
process.exit(2);
|
|
50
|
+
}
|
|
51
|
+
argv.splice(i, 2);
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
const eq = a.startsWith("--project-dir=")
|
|
55
|
+
? a.slice("--project-dir=".length)
|
|
56
|
+
: a.startsWith("-C=")
|
|
57
|
+
? a.slice("-C=".length)
|
|
58
|
+
: null;
|
|
59
|
+
if (eq !== null) {
|
|
60
|
+
argv.splice(i, 1);
|
|
61
|
+
return eq;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const projectDirFlag = extractProjectDirFlag(process.argv);
|
|
68
|
+
const startPath = projectDirFlag
|
|
69
|
+
? resolve(projectDirFlag)
|
|
70
|
+
: process.argv[2]
|
|
71
|
+
? resolve(process.argv[2])
|
|
72
|
+
: process.cwd();
|
|
73
|
+
|
|
74
|
+
process.env.WORKSPACE_PATH = resolveAppRoot(startPath);
|
|
40
75
|
|
|
41
76
|
import("../dist/server.js");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"fastedge_run_version": "v0.16.
|
|
1
|
+
{"fastedge_run_version": "v0.16.7"}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/lib/index.cjs
CHANGED
|
@@ -927,7 +927,13 @@ var HostFunctions = class {
|
|
|
927
927
|
pendingHttpCall = null;
|
|
928
928
|
httpCallResponse = null;
|
|
929
929
|
streamClosed = false;
|
|
930
|
-
// Local response state (from proxy_send_local_response / send_http_response)
|
|
930
|
+
// Local response state (from proxy_send_local_response / send_http_response).
|
|
931
|
+
// `headers` carries the additional headers passed as the 4th argument of
|
|
932
|
+
// `send_http_response`; ProxyWasmRunner merges these into finalResponse at
|
|
933
|
+
// the short-circuit points so they reach the caller alongside any headers
|
|
934
|
+
// accumulated via stream_context.headers.response.add() in the same hook.
|
|
935
|
+
// Stored as tuples to preserve order and duplicate-name semantics (e.g. for
|
|
936
|
+
// multi-value Set-Cookie additions).
|
|
931
937
|
localResponse = null;
|
|
932
938
|
// FastEdge extensions
|
|
933
939
|
secretStore;
|
|
@@ -1277,12 +1283,13 @@ var HostFunctions = class {
|
|
|
1277
1283
|
);
|
|
1278
1284
|
const statusText = this.memory.readString(statusCodePtr, statusCodeLen);
|
|
1279
1285
|
const body = this.memory.readBytes(bodyPtr, bodyLen);
|
|
1286
|
+
let headers = [];
|
|
1280
1287
|
if (headerPairsLen > 0) {
|
|
1281
1288
|
const headerBytes = this.memory.readBytes(headerPairsPtr, headerPairsLen);
|
|
1282
|
-
|
|
1283
|
-
this.logDebug(`send_local_response headers
|
|
1289
|
+
headers = HeaderManager.deserializeBinaryToTuples(headerBytes);
|
|
1290
|
+
this.logDebug(`send_local_response headers: ${JSON.stringify(headers)}`);
|
|
1284
1291
|
}
|
|
1285
|
-
this.localResponse = { statusCode, statusText, body };
|
|
1292
|
+
this.localResponse = { statusCode, statusText, body, headers };
|
|
1286
1293
|
this.logs.push({
|
|
1287
1294
|
level: 1,
|
|
1288
1295
|
message: `local_response status=${statusCode} ${statusText} bodyLen=${body.byteLength} grpc=${grpcStatus}`
|
|
@@ -2076,14 +2083,15 @@ var ProxyWasmRunner = class {
|
|
|
2076
2083
|
const local = this.hostFunctions.getLocalResponse();
|
|
2077
2084
|
const responseHeaders2 = results.onRequestHeaders.output.response.headers;
|
|
2078
2085
|
this.hostFunctions.resetLocalResponse();
|
|
2079
|
-
const
|
|
2086
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
2087
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
2080
2088
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
2081
2089
|
return {
|
|
2082
2090
|
hookResults: results,
|
|
2083
2091
|
finalResponse: {
|
|
2084
2092
|
status: local.statusCode,
|
|
2085
2093
|
statusText: local.statusText,
|
|
2086
|
-
headers:
|
|
2094
|
+
headers: mergedHeaders,
|
|
2087
2095
|
body,
|
|
2088
2096
|
contentType: contentType2,
|
|
2089
2097
|
isBase64: isBase642
|
|
@@ -2119,14 +2127,15 @@ var ProxyWasmRunner = class {
|
|
|
2119
2127
|
const local = this.hostFunctions.getLocalResponse();
|
|
2120
2128
|
const responseHeaders2 = results.onRequestBody.output.response.headers;
|
|
2121
2129
|
this.hostFunctions.resetLocalResponse();
|
|
2122
|
-
const
|
|
2130
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
2131
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
2123
2132
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
2124
2133
|
return {
|
|
2125
2134
|
hookResults: results,
|
|
2126
2135
|
finalResponse: {
|
|
2127
2136
|
status: local.statusCode,
|
|
2128
2137
|
statusText: local.statusText,
|
|
2129
|
-
headers:
|
|
2138
|
+
headers: mergedHeaders,
|
|
2130
2139
|
body,
|
|
2131
2140
|
contentType: contentType2,
|
|
2132
2141
|
isBase64: isBase642
|
|
@@ -2296,16 +2305,17 @@ var ProxyWasmRunner = class {
|
|
|
2296
2305
|
}
|
|
2297
2306
|
if (results.onResponseHeaders.returnCode === 1 && this.hostFunctions.hasLocalResponse()) {
|
|
2298
2307
|
const local = this.hostFunctions.getLocalResponse();
|
|
2299
|
-
const
|
|
2308
|
+
const responseHeaders2 = results.onResponseHeaders.output.response.headers;
|
|
2300
2309
|
this.hostFunctions.resetLocalResponse();
|
|
2301
|
-
const
|
|
2310
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
2311
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
2302
2312
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
2303
2313
|
return {
|
|
2304
2314
|
hookResults: results,
|
|
2305
2315
|
finalResponse: {
|
|
2306
2316
|
status: local.statusCode,
|
|
2307
2317
|
statusText: local.statusText,
|
|
2308
|
-
headers,
|
|
2318
|
+
headers: mergedHeaders,
|
|
2309
2319
|
body,
|
|
2310
2320
|
contentType: contentType2,
|
|
2311
2321
|
isBase64: isBase642
|
|
@@ -2339,16 +2349,17 @@ var ProxyWasmRunner = class {
|
|
|
2339
2349
|
}
|
|
2340
2350
|
if (results.onResponseBody.returnCode === 1 && this.hostFunctions.hasLocalResponse()) {
|
|
2341
2351
|
const local = this.hostFunctions.getLocalResponse();
|
|
2342
|
-
const
|
|
2352
|
+
const responseHeaders2 = results.onResponseBody.output.response.headers;
|
|
2343
2353
|
this.hostFunctions.resetLocalResponse();
|
|
2344
|
-
const
|
|
2354
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
2355
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
2345
2356
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
2346
2357
|
return {
|
|
2347
2358
|
hookResults: results,
|
|
2348
2359
|
finalResponse: {
|
|
2349
2360
|
status: local.statusCode,
|
|
2350
2361
|
statusText: local.statusText,
|
|
2351
|
-
headers,
|
|
2362
|
+
headers: mergedHeaders,
|
|
2352
2363
|
body,
|
|
2353
2364
|
contentType: contentType2,
|
|
2354
2365
|
isBase64: isBase642
|
|
@@ -2723,7 +2734,9 @@ var ProxyWasmRunner = class {
|
|
|
2723
2734
|
}
|
|
2724
2735
|
}
|
|
2725
2736
|
createImports() {
|
|
2726
|
-
const
|
|
2737
|
+
const dictEnv = this.dictionary.getAll();
|
|
2738
|
+
const wasiEnv = Object.keys(dictEnv).length === 0 ? { __FASTEDGE_RUNNER__: "1" } : dictEnv;
|
|
2739
|
+
const wasi = new import_node_wasi.WASI({ version: "preview1", env: wasiEnv });
|
|
2727
2740
|
const wasiImport = wasi.wasiImport;
|
|
2728
2741
|
return {
|
|
2729
2742
|
env: this.hostFunctions.createImports(),
|
|
@@ -2897,19 +2910,37 @@ function getCliBinaryName() {
|
|
|
2897
2910
|
throw new Error(`Unsupported platform: ${import_os.default.platform()}`);
|
|
2898
2911
|
}
|
|
2899
2912
|
}
|
|
2900
|
-
function
|
|
2913
|
+
function getPackageRoot(startDir = _currentDir) {
|
|
2914
|
+
let dir = startDir;
|
|
2915
|
+
while (true) {
|
|
2916
|
+
const pkgPath = (0, import_path2.join)(dir, "package.json");
|
|
2917
|
+
if ((0, import_fs.existsSync)(pkgPath)) {
|
|
2918
|
+
try {
|
|
2919
|
+
const pkg = JSON.parse((0, import_fs.readFileSync)(pkgPath, "utf8"));
|
|
2920
|
+
if (pkg.name === "@gcoredev/fastedge-test") return dir;
|
|
2921
|
+
} catch {
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
const parent = (0, import_path2.dirname)(dir);
|
|
2925
|
+
if (parent === dir) return null;
|
|
2926
|
+
dir = parent;
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
function getBundledCliPaths(startDir = _currentDir) {
|
|
2901
2930
|
const binaryName = getCliBinaryName();
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
(0, import_path2.join)(
|
|
2912
|
-
|
|
2931
|
+
const candidates = [];
|
|
2932
|
+
const root = getPackageRoot(startDir);
|
|
2933
|
+
if (root) {
|
|
2934
|
+
candidates.push(
|
|
2935
|
+
(0, import_path2.join)(root, "dist", "fastedge-cli", binaryName),
|
|
2936
|
+
(0, import_path2.join)(root, "fastedge-run", binaryName)
|
|
2937
|
+
);
|
|
2938
|
+
}
|
|
2939
|
+
candidates.push(
|
|
2940
|
+
(0, import_path2.join)(startDir, "fastedge-cli", binaryName),
|
|
2941
|
+
(0, import_path2.join)(startDir, "..", "fastedge-cli", binaryName)
|
|
2942
|
+
);
|
|
2943
|
+
return candidates;
|
|
2913
2944
|
}
|
|
2914
2945
|
function ensureExecutable(binaryPath) {
|
|
2915
2946
|
if (process.platform !== "win32") {
|
|
@@ -2947,7 +2978,7 @@ async function findFastEdgeRunCli() {
|
|
|
2947
2978
|
} catch (error) {
|
|
2948
2979
|
}
|
|
2949
2980
|
throw new Error(
|
|
2950
|
-
"fastedge-run CLI not found in any of these locations:\n 1. FASTEDGE_RUN_PATH environment variable\n 2. Bundled
|
|
2981
|
+
"fastedge-run CLI not found in any of these locations:\n 1. FASTEDGE_RUN_PATH environment variable\n 2. Bundled inside the @gcoredev/fastedge-test package (dist/fastedge-cli/<binary> when installed, fastedge-run/<binary> in the source tree)\n 3. System PATH (which/where fastedge-run)\n\nTo fix this:\n - Set FASTEDGE_RUN_PATH to a fastedge-run binary you have locally, or\n - Install fastedge-run in PATH: cargo install fastedge-run, or\n - Reinstall @gcoredev/fastedge-test to restore the bundled binary (or, when developing this repo, place the platform binary in fastedge-run/)"
|
|
2951
2982
|
);
|
|
2952
2983
|
}
|
|
2953
2984
|
|
package/dist/lib/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
|
+
|
|
1
3
|
// server/runner/ProxyWasmRunner.ts
|
|
2
4
|
import { WASI } from "node:wasi";
|
|
3
5
|
|
|
@@ -883,7 +885,13 @@ var HostFunctions = class {
|
|
|
883
885
|
pendingHttpCall = null;
|
|
884
886
|
httpCallResponse = null;
|
|
885
887
|
streamClosed = false;
|
|
886
|
-
// Local response state (from proxy_send_local_response / send_http_response)
|
|
888
|
+
// Local response state (from proxy_send_local_response / send_http_response).
|
|
889
|
+
// `headers` carries the additional headers passed as the 4th argument of
|
|
890
|
+
// `send_http_response`; ProxyWasmRunner merges these into finalResponse at
|
|
891
|
+
// the short-circuit points so they reach the caller alongside any headers
|
|
892
|
+
// accumulated via stream_context.headers.response.add() in the same hook.
|
|
893
|
+
// Stored as tuples to preserve order and duplicate-name semantics (e.g. for
|
|
894
|
+
// multi-value Set-Cookie additions).
|
|
887
895
|
localResponse = null;
|
|
888
896
|
// FastEdge extensions
|
|
889
897
|
secretStore;
|
|
@@ -1233,12 +1241,13 @@ var HostFunctions = class {
|
|
|
1233
1241
|
);
|
|
1234
1242
|
const statusText = this.memory.readString(statusCodePtr, statusCodeLen);
|
|
1235
1243
|
const body = this.memory.readBytes(bodyPtr, bodyLen);
|
|
1244
|
+
let headers = [];
|
|
1236
1245
|
if (headerPairsLen > 0) {
|
|
1237
1246
|
const headerBytes = this.memory.readBytes(headerPairsPtr, headerPairsLen);
|
|
1238
|
-
|
|
1239
|
-
this.logDebug(`send_local_response headers
|
|
1247
|
+
headers = HeaderManager.deserializeBinaryToTuples(headerBytes);
|
|
1248
|
+
this.logDebug(`send_local_response headers: ${JSON.stringify(headers)}`);
|
|
1240
1249
|
}
|
|
1241
|
-
this.localResponse = { statusCode, statusText, body };
|
|
1250
|
+
this.localResponse = { statusCode, statusText, body, headers };
|
|
1242
1251
|
this.logs.push({
|
|
1243
1252
|
level: 1,
|
|
1244
1253
|
message: `local_response status=${statusCode} ${statusText} bodyLen=${body.byteLength} grpc=${grpcStatus}`
|
|
@@ -2032,14 +2041,15 @@ var ProxyWasmRunner = class {
|
|
|
2032
2041
|
const local = this.hostFunctions.getLocalResponse();
|
|
2033
2042
|
const responseHeaders2 = results.onRequestHeaders.output.response.headers;
|
|
2034
2043
|
this.hostFunctions.resetLocalResponse();
|
|
2035
|
-
const
|
|
2044
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
2045
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
2036
2046
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
2037
2047
|
return {
|
|
2038
2048
|
hookResults: results,
|
|
2039
2049
|
finalResponse: {
|
|
2040
2050
|
status: local.statusCode,
|
|
2041
2051
|
statusText: local.statusText,
|
|
2042
|
-
headers:
|
|
2052
|
+
headers: mergedHeaders,
|
|
2043
2053
|
body,
|
|
2044
2054
|
contentType: contentType2,
|
|
2045
2055
|
isBase64: isBase642
|
|
@@ -2075,14 +2085,15 @@ var ProxyWasmRunner = class {
|
|
|
2075
2085
|
const local = this.hostFunctions.getLocalResponse();
|
|
2076
2086
|
const responseHeaders2 = results.onRequestBody.output.response.headers;
|
|
2077
2087
|
this.hostFunctions.resetLocalResponse();
|
|
2078
|
-
const
|
|
2088
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
2089
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
2079
2090
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
2080
2091
|
return {
|
|
2081
2092
|
hookResults: results,
|
|
2082
2093
|
finalResponse: {
|
|
2083
2094
|
status: local.statusCode,
|
|
2084
2095
|
statusText: local.statusText,
|
|
2085
|
-
headers:
|
|
2096
|
+
headers: mergedHeaders,
|
|
2086
2097
|
body,
|
|
2087
2098
|
contentType: contentType2,
|
|
2088
2099
|
isBase64: isBase642
|
|
@@ -2252,16 +2263,17 @@ var ProxyWasmRunner = class {
|
|
|
2252
2263
|
}
|
|
2253
2264
|
if (results.onResponseHeaders.returnCode === 1 && this.hostFunctions.hasLocalResponse()) {
|
|
2254
2265
|
const local = this.hostFunctions.getLocalResponse();
|
|
2255
|
-
const
|
|
2266
|
+
const responseHeaders2 = results.onResponseHeaders.output.response.headers;
|
|
2256
2267
|
this.hostFunctions.resetLocalResponse();
|
|
2257
|
-
const
|
|
2268
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
2269
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
2258
2270
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
2259
2271
|
return {
|
|
2260
2272
|
hookResults: results,
|
|
2261
2273
|
finalResponse: {
|
|
2262
2274
|
status: local.statusCode,
|
|
2263
2275
|
statusText: local.statusText,
|
|
2264
|
-
headers,
|
|
2276
|
+
headers: mergedHeaders,
|
|
2265
2277
|
body,
|
|
2266
2278
|
contentType: contentType2,
|
|
2267
2279
|
isBase64: isBase642
|
|
@@ -2295,16 +2307,17 @@ var ProxyWasmRunner = class {
|
|
|
2295
2307
|
}
|
|
2296
2308
|
if (results.onResponseBody.returnCode === 1 && this.hostFunctions.hasLocalResponse()) {
|
|
2297
2309
|
const local = this.hostFunctions.getLocalResponse();
|
|
2298
|
-
const
|
|
2310
|
+
const responseHeaders2 = results.onResponseBody.output.response.headers;
|
|
2299
2311
|
this.hostFunctions.resetLocalResponse();
|
|
2300
|
-
const
|
|
2312
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
2313
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
2301
2314
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
2302
2315
|
return {
|
|
2303
2316
|
hookResults: results,
|
|
2304
2317
|
finalResponse: {
|
|
2305
2318
|
status: local.statusCode,
|
|
2306
2319
|
statusText: local.statusText,
|
|
2307
|
-
headers,
|
|
2320
|
+
headers: mergedHeaders,
|
|
2308
2321
|
body,
|
|
2309
2322
|
contentType: contentType2,
|
|
2310
2323
|
isBase64: isBase642
|
|
@@ -2679,7 +2692,9 @@ var ProxyWasmRunner = class {
|
|
|
2679
2692
|
}
|
|
2680
2693
|
}
|
|
2681
2694
|
createImports() {
|
|
2682
|
-
const
|
|
2695
|
+
const dictEnv = this.dictionary.getAll();
|
|
2696
|
+
const wasiEnv = Object.keys(dictEnv).length === 0 ? { __FASTEDGE_RUNNER__: "1" } : dictEnv;
|
|
2697
|
+
const wasi = new WASI({ version: "preview1", env: wasiEnv });
|
|
2683
2698
|
const wasiImport = wasi.wasiImport;
|
|
2684
2699
|
return {
|
|
2685
2700
|
env: this.hostFunctions.createImports(),
|
|
@@ -2836,7 +2851,7 @@ import { spawn, execSync as execSync2 } from "child_process";
|
|
|
2836
2851
|
|
|
2837
2852
|
// server/utils/fastedge-cli.ts
|
|
2838
2853
|
import { execSync } from "child_process";
|
|
2839
|
-
import { existsSync, chmodSync } from "fs";
|
|
2854
|
+
import { existsSync, chmodSync, readFileSync } from "fs";
|
|
2840
2855
|
import { join, dirname } from "path";
|
|
2841
2856
|
import { fileURLToPath } from "url";
|
|
2842
2857
|
import os from "os";
|
|
@@ -2853,19 +2868,37 @@ function getCliBinaryName() {
|
|
|
2853
2868
|
throw new Error(`Unsupported platform: ${os.platform()}`);
|
|
2854
2869
|
}
|
|
2855
2870
|
}
|
|
2856
|
-
function
|
|
2871
|
+
function getPackageRoot(startDir = _currentDir) {
|
|
2872
|
+
let dir = startDir;
|
|
2873
|
+
while (true) {
|
|
2874
|
+
const pkgPath = join(dir, "package.json");
|
|
2875
|
+
if (existsSync(pkgPath)) {
|
|
2876
|
+
try {
|
|
2877
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
2878
|
+
if (pkg.name === "@gcoredev/fastedge-test") return dir;
|
|
2879
|
+
} catch {
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
const parent = dirname(dir);
|
|
2883
|
+
if (parent === dir) return null;
|
|
2884
|
+
dir = parent;
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2887
|
+
function getBundledCliPaths(startDir = _currentDir) {
|
|
2857
2888
|
const binaryName = getCliBinaryName();
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
join(
|
|
2868
|
-
|
|
2889
|
+
const candidates = [];
|
|
2890
|
+
const root = getPackageRoot(startDir);
|
|
2891
|
+
if (root) {
|
|
2892
|
+
candidates.push(
|
|
2893
|
+
join(root, "dist", "fastedge-cli", binaryName),
|
|
2894
|
+
join(root, "fastedge-run", binaryName)
|
|
2895
|
+
);
|
|
2896
|
+
}
|
|
2897
|
+
candidates.push(
|
|
2898
|
+
join(startDir, "fastedge-cli", binaryName),
|
|
2899
|
+
join(startDir, "..", "fastedge-cli", binaryName)
|
|
2900
|
+
);
|
|
2901
|
+
return candidates;
|
|
2869
2902
|
}
|
|
2870
2903
|
function ensureExecutable(binaryPath) {
|
|
2871
2904
|
if (process.platform !== "win32") {
|
|
@@ -2903,7 +2936,7 @@ async function findFastEdgeRunCli() {
|
|
|
2903
2936
|
} catch (error) {
|
|
2904
2937
|
}
|
|
2905
2938
|
throw new Error(
|
|
2906
|
-
"fastedge-run CLI not found in any of these locations:\n 1. FASTEDGE_RUN_PATH environment variable\n 2. Bundled
|
|
2939
|
+
"fastedge-run CLI not found in any of these locations:\n 1. FASTEDGE_RUN_PATH environment variable\n 2. Bundled inside the @gcoredev/fastedge-test package (dist/fastedge-cli/<binary> when installed, fastedge-run/<binary> in the source tree)\n 3. System PATH (which/where fastedge-run)\n\nTo fix this:\n - Set FASTEDGE_RUN_PATH to a fastedge-run binary you have locally, or\n - Install fastedge-run in PATH: cargo install fastedge-run, or\n - Reinstall @gcoredev/fastedge-test to restore the bundled binary (or, when developing this repo, place the platform binary in fastedge-run/)"
|
|
2907
2940
|
);
|
|
2908
2941
|
}
|
|
2909
2942
|
|
|
@@ -19324,7 +19324,13 @@ var HostFunctions = class {
|
|
|
19324
19324
|
pendingHttpCall = null;
|
|
19325
19325
|
httpCallResponse = null;
|
|
19326
19326
|
streamClosed = false;
|
|
19327
|
-
// Local response state (from proxy_send_local_response / send_http_response)
|
|
19327
|
+
// Local response state (from proxy_send_local_response / send_http_response).
|
|
19328
|
+
// `headers` carries the additional headers passed as the 4th argument of
|
|
19329
|
+
// `send_http_response`; ProxyWasmRunner merges these into finalResponse at
|
|
19330
|
+
// the short-circuit points so they reach the caller alongside any headers
|
|
19331
|
+
// accumulated via stream_context.headers.response.add() in the same hook.
|
|
19332
|
+
// Stored as tuples to preserve order and duplicate-name semantics (e.g. for
|
|
19333
|
+
// multi-value Set-Cookie additions).
|
|
19328
19334
|
localResponse = null;
|
|
19329
19335
|
// FastEdge extensions
|
|
19330
19336
|
secretStore;
|
|
@@ -19674,12 +19680,13 @@ var HostFunctions = class {
|
|
|
19674
19680
|
);
|
|
19675
19681
|
const statusText = this.memory.readString(statusCodePtr, statusCodeLen);
|
|
19676
19682
|
const body = this.memory.readBytes(bodyPtr, bodyLen);
|
|
19683
|
+
let headers = [];
|
|
19677
19684
|
if (headerPairsLen > 0) {
|
|
19678
19685
|
const headerBytes = this.memory.readBytes(headerPairsPtr, headerPairsLen);
|
|
19679
|
-
|
|
19680
|
-
this.logDebug(`send_local_response headers
|
|
19686
|
+
headers = HeaderManager.deserializeBinaryToTuples(headerBytes);
|
|
19687
|
+
this.logDebug(`send_local_response headers: ${JSON.stringify(headers)}`);
|
|
19681
19688
|
}
|
|
19682
|
-
this.localResponse = { statusCode, statusText, body };
|
|
19689
|
+
this.localResponse = { statusCode, statusText, body, headers };
|
|
19683
19690
|
this.logs.push({
|
|
19684
19691
|
level: 1,
|
|
19685
19692
|
message: `local_response status=${statusCode} ${statusText} bodyLen=${body.byteLength} grpc=${grpcStatus}`
|
|
@@ -20473,14 +20480,15 @@ var ProxyWasmRunner = class {
|
|
|
20473
20480
|
const local = this.hostFunctions.getLocalResponse();
|
|
20474
20481
|
const responseHeaders2 = results.onRequestHeaders.output.response.headers;
|
|
20475
20482
|
this.hostFunctions.resetLocalResponse();
|
|
20476
|
-
const
|
|
20483
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
20484
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
20477
20485
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
20478
20486
|
return {
|
|
20479
20487
|
hookResults: results,
|
|
20480
20488
|
finalResponse: {
|
|
20481
20489
|
status: local.statusCode,
|
|
20482
20490
|
statusText: local.statusText,
|
|
20483
|
-
headers:
|
|
20491
|
+
headers: mergedHeaders,
|
|
20484
20492
|
body,
|
|
20485
20493
|
contentType: contentType2,
|
|
20486
20494
|
isBase64: isBase642
|
|
@@ -20516,14 +20524,15 @@ var ProxyWasmRunner = class {
|
|
|
20516
20524
|
const local = this.hostFunctions.getLocalResponse();
|
|
20517
20525
|
const responseHeaders2 = results.onRequestBody.output.response.headers;
|
|
20518
20526
|
this.hostFunctions.resetLocalResponse();
|
|
20519
|
-
const
|
|
20527
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
20528
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
20520
20529
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
20521
20530
|
return {
|
|
20522
20531
|
hookResults: results,
|
|
20523
20532
|
finalResponse: {
|
|
20524
20533
|
status: local.statusCode,
|
|
20525
20534
|
statusText: local.statusText,
|
|
20526
|
-
headers:
|
|
20535
|
+
headers: mergedHeaders,
|
|
20527
20536
|
body,
|
|
20528
20537
|
contentType: contentType2,
|
|
20529
20538
|
isBase64: isBase642
|
|
@@ -20693,16 +20702,17 @@ var ProxyWasmRunner = class {
|
|
|
20693
20702
|
}
|
|
20694
20703
|
if (results.onResponseHeaders.returnCode === 1 && this.hostFunctions.hasLocalResponse()) {
|
|
20695
20704
|
const local = this.hostFunctions.getLocalResponse();
|
|
20696
|
-
const
|
|
20705
|
+
const responseHeaders2 = results.onResponseHeaders.output.response.headers;
|
|
20697
20706
|
this.hostFunctions.resetLocalResponse();
|
|
20698
|
-
const
|
|
20707
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
20708
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
20699
20709
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
20700
20710
|
return {
|
|
20701
20711
|
hookResults: results,
|
|
20702
20712
|
finalResponse: {
|
|
20703
20713
|
status: local.statusCode,
|
|
20704
20714
|
statusText: local.statusText,
|
|
20705
|
-
headers,
|
|
20715
|
+
headers: mergedHeaders,
|
|
20706
20716
|
body,
|
|
20707
20717
|
contentType: contentType2,
|
|
20708
20718
|
isBase64: isBase642
|
|
@@ -20736,16 +20746,17 @@ var ProxyWasmRunner = class {
|
|
|
20736
20746
|
}
|
|
20737
20747
|
if (results.onResponseBody.returnCode === 1 && this.hostFunctions.hasLocalResponse()) {
|
|
20738
20748
|
const local = this.hostFunctions.getLocalResponse();
|
|
20739
|
-
const
|
|
20749
|
+
const responseHeaders2 = results.onResponseBody.output.response.headers;
|
|
20740
20750
|
this.hostFunctions.resetLocalResponse();
|
|
20741
|
-
const
|
|
20751
|
+
const mergedHeaders = local.headers.length > 0 ? HeaderManager.appendMerge(responseHeaders2, HeaderManager.tuplesToRecord(local.headers)) : responseHeaders2;
|
|
20752
|
+
const contentType2 = HeaderManager.firstValue(mergedHeaders["content-type"]) || "text/plain";
|
|
20742
20753
|
const { body, isBase64: isBase642 } = encodeLocalResponseBody(local.body, contentType2);
|
|
20743
20754
|
return {
|
|
20744
20755
|
hookResults: results,
|
|
20745
20756
|
finalResponse: {
|
|
20746
20757
|
status: local.statusCode,
|
|
20747
20758
|
statusText: local.statusText,
|
|
20748
|
-
headers,
|
|
20759
|
+
headers: mergedHeaders,
|
|
20749
20760
|
body,
|
|
20750
20761
|
contentType: contentType2,
|
|
20751
20762
|
isBase64: isBase642
|
|
@@ -21120,7 +21131,9 @@ var ProxyWasmRunner = class {
|
|
|
21120
21131
|
}
|
|
21121
21132
|
}
|
|
21122
21133
|
createImports() {
|
|
21123
|
-
const
|
|
21134
|
+
const dictEnv = this.dictionary.getAll();
|
|
21135
|
+
const wasiEnv = Object.keys(dictEnv).length === 0 ? { __FASTEDGE_RUNNER__: "1" } : dictEnv;
|
|
21136
|
+
const wasi = new import_node_wasi.WASI({ version: "preview1", env: wasiEnv });
|
|
21124
21137
|
const wasiImport = wasi.wasiImport;
|
|
21125
21138
|
return {
|
|
21126
21139
|
env: this.hostFunctions.createImports(),
|
|
@@ -21294,19 +21307,37 @@ function getCliBinaryName() {
|
|
|
21294
21307
|
throw new Error(`Unsupported platform: ${import_os.default.platform()}`);
|
|
21295
21308
|
}
|
|
21296
21309
|
}
|
|
21297
|
-
function
|
|
21310
|
+
function getPackageRoot(startDir = _currentDir) {
|
|
21311
|
+
let dir = startDir;
|
|
21312
|
+
while (true) {
|
|
21313
|
+
const pkgPath = (0, import_path2.join)(dir, "package.json");
|
|
21314
|
+
if ((0, import_fs.existsSync)(pkgPath)) {
|
|
21315
|
+
try {
|
|
21316
|
+
const pkg = JSON.parse((0, import_fs.readFileSync)(pkgPath, "utf8"));
|
|
21317
|
+
if (pkg.name === "@gcoredev/fastedge-test") return dir;
|
|
21318
|
+
} catch {
|
|
21319
|
+
}
|
|
21320
|
+
}
|
|
21321
|
+
const parent = (0, import_path2.dirname)(dir);
|
|
21322
|
+
if (parent === dir) return null;
|
|
21323
|
+
dir = parent;
|
|
21324
|
+
}
|
|
21325
|
+
}
|
|
21326
|
+
function getBundledCliPaths(startDir = _currentDir) {
|
|
21298
21327
|
const binaryName = getCliBinaryName();
|
|
21299
|
-
|
|
21300
|
-
|
|
21301
|
-
|
|
21302
|
-
|
|
21303
|
-
|
|
21304
|
-
|
|
21305
|
-
|
|
21306
|
-
|
|
21307
|
-
|
|
21308
|
-
(0, import_path2.join)(
|
|
21309
|
-
|
|
21328
|
+
const candidates = [];
|
|
21329
|
+
const root = getPackageRoot(startDir);
|
|
21330
|
+
if (root) {
|
|
21331
|
+
candidates.push(
|
|
21332
|
+
(0, import_path2.join)(root, "dist", "fastedge-cli", binaryName),
|
|
21333
|
+
(0, import_path2.join)(root, "fastedge-run", binaryName)
|
|
21334
|
+
);
|
|
21335
|
+
}
|
|
21336
|
+
candidates.push(
|
|
21337
|
+
(0, import_path2.join)(startDir, "fastedge-cli", binaryName),
|
|
21338
|
+
(0, import_path2.join)(startDir, "..", "fastedge-cli", binaryName)
|
|
21339
|
+
);
|
|
21340
|
+
return candidates;
|
|
21310
21341
|
}
|
|
21311
21342
|
function ensureExecutable(binaryPath) {
|
|
21312
21343
|
if (process.platform !== "win32") {
|
|
@@ -21344,7 +21375,7 @@ async function findFastEdgeRunCli() {
|
|
|
21344
21375
|
} catch (error) {
|
|
21345
21376
|
}
|
|
21346
21377
|
throw new Error(
|
|
21347
|
-
"fastedge-run CLI not found in any of these locations:\n 1. FASTEDGE_RUN_PATH environment variable\n 2. Bundled
|
|
21378
|
+
"fastedge-run CLI not found in any of these locations:\n 1. FASTEDGE_RUN_PATH environment variable\n 2. Bundled inside the @gcoredev/fastedge-test package (dist/fastedge-cli/<binary> when installed, fastedge-run/<binary> in the source tree)\n 3. System PATH (which/where fastedge-run)\n\nTo fix this:\n - Set FASTEDGE_RUN_PATH to a fastedge-run binary you have locally, or\n - Install fastedge-run in PATH: cargo install fastedge-run, or\n - Reinstall @gcoredev/fastedge-test to restore the bundled binary (or, when developing this repo, place the platform binary in fastedge-run/)"
|
|
21348
21379
|
);
|
|
21349
21380
|
}
|
|
21350
21381
|
|