@replohq/sdk 2.18.0 → 2.18.1
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/lib/buildMetadata.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const BUILD_METADATA = {
|
|
2
2
|
"packageName": "@replohq/sdk",
|
|
3
|
-
"version": "2.18.
|
|
3
|
+
"version": "2.18.1",
|
|
4
4
|
"branch": "HEAD",
|
|
5
|
-
"commit": "
|
|
6
|
-
"builtAt": "2026-11-
|
|
5
|
+
"commit": "31098580021d6a05449acd44d0850054eec6e0ec",
|
|
6
|
+
"builtAt": "2026-11-02T23:35:33.205Z"
|
|
7
7
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CanopyError } from "../lib/canopy-error";
|
|
2
|
+
/** A loader argument that can't be sent to canopy-api, such as a function. */
|
|
3
|
+
export declare class LoaderArgsError extends CanopyError {
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Finds the first function in a loader's args. JSON drops functions silently,
|
|
7
|
+
* so canopy-api would receive the args without that key and reject them. The
|
|
8
|
+
* usual cause is a value exported from a "use client" file and imported into a
|
|
9
|
+
* server component: on the server, every such export is a client reference
|
|
10
|
+
* (a function), never the value itself.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getLoaderArgsError({ loaderKey, args, }: {
|
|
13
|
+
loaderKey: string;
|
|
14
|
+
args: Record<string, unknown>;
|
|
15
|
+
}): LoaderArgsError | null;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CanopyError } from "../lib/canopy-error";
|
|
2
|
+
const CLIENT_REFERENCE_TAG = Symbol.for("react.client.reference");
|
|
3
|
+
class LoaderArgsError extends CanopyError {
|
|
4
|
+
}
|
|
5
|
+
function findFunctionArg(value, path, seen) {
|
|
6
|
+
if (typeof value === "function") {
|
|
7
|
+
return {
|
|
8
|
+
path,
|
|
9
|
+
isClientReference: Reflect.get(value, "$$typeof") === CLIENT_REFERENCE_TAG
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
if (typeof value !== "object" || value === null || seen.has(value) || typeof Reflect.get(value, "toJSON") === "function") {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
seen.add(value);
|
|
16
|
+
for (const [key, child] of Object.entries(value)) {
|
|
17
|
+
const childPath = Array.isArray(value) ? `${path}[${key}]` : `${path}.${key}`;
|
|
18
|
+
const found = findFunctionArg(child, childPath, seen);
|
|
19
|
+
if (found !== null) {
|
|
20
|
+
return found;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
function getLoaderArgsError({
|
|
26
|
+
loaderKey,
|
|
27
|
+
args
|
|
28
|
+
}) {
|
|
29
|
+
const found = findFunctionArg(args, "args", /* @__PURE__ */ new Set());
|
|
30
|
+
if (found === null) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const what = found.isClientReference ? "a client reference, not a value" : "a function";
|
|
34
|
+
return new LoaderArgsError({
|
|
35
|
+
message: `[Replo] Loader ${loaderKey}: ${found.path} is ${what}, so it can't be sent to the loader. It was probably imported from a "use client" file into a server component. Move the value into a module without "use client" and import it from both places.`,
|
|
36
|
+
additionalData: {
|
|
37
|
+
loaderKey,
|
|
38
|
+
path: found.path,
|
|
39
|
+
isClientReference: found.isClientReference
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
LoaderArgsError,
|
|
45
|
+
getLoaderArgsError
|
|
46
|
+
};
|
|
@@ -21,6 +21,9 @@ export declare class LoaderOutputError extends CanopyError {
|
|
|
21
21
|
*
|
|
22
22
|
* Malformed output is logged with the loader key and the failing paths, then
|
|
23
23
|
* rejected with a `LoaderOutputError`; callers decide whether to fail soft.
|
|
24
|
+
* Args holding a function are logged and rejected with a `LoaderArgsError`
|
|
25
|
+
* before any request, since JSON would drop them and canopy-api would reject
|
|
26
|
+
* the rest. The log matters because `PrefetchedLoaders` swallows rejections.
|
|
24
27
|
*/
|
|
25
28
|
export declare function fetchValidatedLoaderOutput({ loaderKey, args, }: {
|
|
26
29
|
loaderKey: string;
|
package/loaders/loader-output.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
smileRewardsOutputSchema,
|
|
10
10
|
smileVipTiersOutputSchema
|
|
11
11
|
} from "./integration-loader-schemas";
|
|
12
|
+
import { getLoaderArgsError } from "./loader-args";
|
|
12
13
|
import { DATA_LOADER_KEYS } from "./loader-keys";
|
|
13
14
|
import {
|
|
14
15
|
contentfulEntriesLoaderOutputSchema,
|
|
@@ -93,6 +94,11 @@ async function fetchValidatedLoaderOutput({
|
|
|
93
94
|
loaderKey,
|
|
94
95
|
args
|
|
95
96
|
}) {
|
|
97
|
+
const argsError = getLoaderArgsError({ loaderKey, args });
|
|
98
|
+
if (argsError !== null) {
|
|
99
|
+
console.error(argsError.message);
|
|
100
|
+
throw argsError;
|
|
101
|
+
}
|
|
96
102
|
const gateway = await getCanopyApiGateway();
|
|
97
103
|
const { data } = await gateway.invokeLoader({ loaderKey, args });
|
|
98
104
|
const knownKey = dataLoaderKeySchema.safeParse(loaderKey);
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@replohq/sdk",
|
|
3
|
-
"version": "2.18.
|
|
3
|
+
"version": "2.18.1",
|
|
4
4
|
"reploBuild": {
|
|
5
5
|
"packageName": "@replohq/sdk",
|
|
6
|
-
"version": "2.18.
|
|
6
|
+
"version": "2.18.1",
|
|
7
7
|
"branch": "HEAD",
|
|
8
|
-
"commit": "
|
|
9
|
-
"builtAt": "2026-11-
|
|
8
|
+
"commit": "31098580021d6a05449acd44d0850054eec6e0ec",
|
|
9
|
+
"builtAt": "2026-11-02T23:35:33.205Z"
|
|
10
10
|
},
|
|
11
11
|
"description": "Replo SDK — cart, analytics, and data loaders for agent-built Next.js sites.",
|
|
12
12
|
"license": "SEE LICENSE IN LICENSE",
|