@financedistrict/saleor-agentic-commerce-nextjs 0.1.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/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +54 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/ucp-headers.d.ts +39 -0
- package/dist/middleware/ucp-headers.d.ts.map +1 -0
- package/dist/middleware/ucp-headers.js +53 -0
- package/dist/middleware/ucp-headers.js.map +1 -0
- package/dist/routes/acp-routes.d.ts +62 -0
- package/dist/routes/acp-routes.d.ts.map +1 -0
- package/dist/routes/acp-routes.js +274 -0
- package/dist/routes/acp-routes.js.map +1 -0
- package/dist/routes/ucp-routes.d.ts +76 -0
- package/dist/routes/ucp-routes.d.ts.map +1 -0
- package/dist/routes/ucp-routes.js +281 -0
- package/dist/routes/ucp-routes.js.map +1 -0
- package/package.json +74 -0
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic Commerce Configuration
|
|
3
|
+
*
|
|
4
|
+
* Creates and configures the agentic commerce instance that route handlers
|
|
5
|
+
* and middleware use. Merchants call createAgenticCommerce() once in their
|
|
6
|
+
* storefront code and export the instance.
|
|
7
|
+
*/
|
|
8
|
+
import { SaleorClient, PaymentHandlerRegistry, type PaymentHandlerAdapter, type FormatterContext } from "@financedistrict/saleor-agentic-commerce-core";
|
|
9
|
+
export type AgenticCommerceConfig = {
|
|
10
|
+
/** Saleor GraphQL API URL (e.g., "https://api.store.com/graphql/") */
|
|
11
|
+
saleorApiUrl: string;
|
|
12
|
+
/** Saleor App Token with MANAGE_CHECKOUTS, MANAGE_ORDERS permissions */
|
|
13
|
+
saleorAuthToken: string;
|
|
14
|
+
/** Default Saleor channel slug */
|
|
15
|
+
channel?: string;
|
|
16
|
+
/** Storefront public URL (e.g., "https://store.com") */
|
|
17
|
+
storefrontUrl: string;
|
|
18
|
+
/** Store display name */
|
|
19
|
+
storeName: string;
|
|
20
|
+
/** Store description */
|
|
21
|
+
storeDescription?: string;
|
|
22
|
+
/** UCP protocol version (default: "2026-04-08") */
|
|
23
|
+
ucpVersion?: string;
|
|
24
|
+
/** ACP protocol version (default: "2026-01-30") */
|
|
25
|
+
acpVersion?: string;
|
|
26
|
+
/** API key for ACP Bearer token authentication */
|
|
27
|
+
acpApiKey?: string;
|
|
28
|
+
/** Payment handler adapters to register */
|
|
29
|
+
paymentHandlers?: PaymentHandlerAdapter[];
|
|
30
|
+
};
|
|
31
|
+
export type AgenticCommerceInstance = {
|
|
32
|
+
saleorClient: SaleorClient;
|
|
33
|
+
paymentHandlers: PaymentHandlerRegistry;
|
|
34
|
+
formatterContext: FormatterContext;
|
|
35
|
+
config: Required<Pick<AgenticCommerceConfig, "storefrontUrl" | "storeName" | "ucpVersion" | "acpVersion">> & Pick<AgenticCommerceConfig, "storeDescription" | "acpApiKey">;
|
|
36
|
+
};
|
|
37
|
+
export declare function createAgenticCommerce(config: AgenticCommerceConfig): AgenticCommerceInstance;
|
|
38
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EAEtB,MAAM,+CAA+C,CAAA;AAMtD,MAAM,MAAM,qBAAqB,GAAG;IAClC,sEAAsE;IACtE,YAAY,EAAE,MAAM,CAAA;IACpB,wEAAwE;IACxE,eAAe,EAAE,MAAM,CAAA;IACvB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,aAAa,EAAE,MAAM,CAAA;IACrB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,wBAAwB;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,eAAe,CAAC,EAAE,qBAAqB,EAAE,CAAA;CAC1C,CAAA;AAMD,MAAM,MAAM,uBAAuB,GAAG;IACpC,YAAY,EAAE,YAAY,CAAA;IAC1B,eAAe,EAAE,sBAAsB,CAAA;IACvC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,qBAAqB,EAAE,eAAe,GAAG,WAAW,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC,GACxG,IAAI,CAAC,qBAAqB,EAAE,kBAAkB,GAAG,WAAW,CAAC,CAAA;CAChE,CAAA;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,uBAAuB,CA6C5F"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic Commerce Configuration
|
|
3
|
+
*
|
|
4
|
+
* Creates and configures the agentic commerce instance that route handlers
|
|
5
|
+
* and middleware use. Merchants call createAgenticCommerce() once in their
|
|
6
|
+
* storefront code and export the instance.
|
|
7
|
+
*/
|
|
8
|
+
import { SaleorClient, PaymentHandlerRegistry, } from "@financedistrict/saleor-agentic-commerce-core";
|
|
9
|
+
export function createAgenticCommerce(config) {
|
|
10
|
+
// Validate required config
|
|
11
|
+
if (!config.saleorApiUrl)
|
|
12
|
+
throw new Error("saleorApiUrl is required");
|
|
13
|
+
if (!config.saleorAuthToken)
|
|
14
|
+
throw new Error("saleorAuthToken is required");
|
|
15
|
+
if (!config.storefrontUrl)
|
|
16
|
+
throw new Error("storefrontUrl is required");
|
|
17
|
+
if (!config.storeName)
|
|
18
|
+
throw new Error("storeName is required");
|
|
19
|
+
const ucpVersion = config.ucpVersion || "2026-04-08";
|
|
20
|
+
const acpVersion = config.acpVersion || "2026-01-30";
|
|
21
|
+
// Create Saleor client
|
|
22
|
+
const saleorClient = new SaleorClient({
|
|
23
|
+
apiUrl: config.saleorApiUrl,
|
|
24
|
+
authToken: config.saleorAuthToken,
|
|
25
|
+
channel: config.channel,
|
|
26
|
+
});
|
|
27
|
+
// Create and populate payment handler registry
|
|
28
|
+
const paymentHandlers = new PaymentHandlerRegistry();
|
|
29
|
+
for (const handler of config.paymentHandlers || []) {
|
|
30
|
+
paymentHandlers.registerAdapter(handler);
|
|
31
|
+
}
|
|
32
|
+
// Create formatter context
|
|
33
|
+
const formatterContext = {
|
|
34
|
+
storeName: config.storeName,
|
|
35
|
+
storefrontUrl: config.storefrontUrl,
|
|
36
|
+
ucpVersion,
|
|
37
|
+
acpVersion,
|
|
38
|
+
paymentHandlers,
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
saleorClient,
|
|
42
|
+
paymentHandlers,
|
|
43
|
+
formatterContext,
|
|
44
|
+
config: {
|
|
45
|
+
storefrontUrl: config.storefrontUrl,
|
|
46
|
+
storeName: config.storeName,
|
|
47
|
+
storeDescription: config.storeDescription,
|
|
48
|
+
ucpVersion,
|
|
49
|
+
acpVersion,
|
|
50
|
+
acpApiKey: config.acpApiKey,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EACZ,sBAAsB,GAIvB,MAAM,+CAA+C,CAAA;AAyCtD,MAAM,UAAU,qBAAqB,CAAC,MAA6B;IACjE,2BAA2B;IAC3B,IAAI,CAAC,MAAM,CAAC,YAAY;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;IACrE,IAAI,CAAC,MAAM,CAAC,eAAe;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAC3E,IAAI,CAAC,MAAM,CAAC,aAAa;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;IACvE,IAAI,CAAC,MAAM,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;IAE/D,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,YAAY,CAAA;IACpD,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,YAAY,CAAA;IAEpD,uBAAuB;IACvB,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC;QACpC,MAAM,EAAE,MAAM,CAAC,YAAY;QAC3B,SAAS,EAAE,MAAM,CAAC,eAAe;QACjC,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAA;IAEF,+CAA+C;IAC/C,MAAM,eAAe,GAAG,IAAI,sBAAsB,EAAE,CAAA;IACpD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,eAAe,IAAI,EAAE,EAAE,CAAC;QACnD,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;IAC1C,CAAC;IAED,2BAA2B;IAC3B,MAAM,gBAAgB,GAAqB;QACzC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,UAAU;QACV,UAAU;QACV,eAAe;KAChB,CAAA;IAED,OAAO;QACL,YAAY;QACZ,eAAe;QACf,gBAAgB;QAChB,MAAM,EAAE;YACN,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,UAAU;YACV,UAAU;YACV,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B;KACF,CAAA;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @financedistrict/saleor-agentic-commerce-nextjs
|
|
3
|
+
*
|
|
4
|
+
* Drop-in Next.js integration for Saleor agentic commerce.
|
|
5
|
+
* Provides route handlers, middleware, and configuration.
|
|
6
|
+
*/
|
|
7
|
+
export { createAgenticCommerce } from "./config.js";
|
|
8
|
+
export type { AgenticCommerceConfig, AgenticCommerceInstance } from "./config.js";
|
|
9
|
+
export { createUcpRoutes } from "./routes/ucp-routes.js";
|
|
10
|
+
export { createAcpRoutes } from "./routes/acp-routes.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,YAAY,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAEjF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @financedistrict/saleor-agentic-commerce-nextjs
|
|
3
|
+
*
|
|
4
|
+
* Drop-in Next.js integration for Saleor agentic commerce.
|
|
5
|
+
* Provides route handlers, middleware, and configuration.
|
|
6
|
+
*/
|
|
7
|
+
export { createAgenticCommerce } from "./config.js";
|
|
8
|
+
export { createUcpRoutes } from "./routes/ucp-routes.js";
|
|
9
|
+
export { createAcpRoutes } from "./routes/acp-routes.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAGnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UCP Header Middleware
|
|
3
|
+
*
|
|
4
|
+
* Parses and validates UCP-specific headers from incoming requests.
|
|
5
|
+
* Used by route handlers to extract agent profile, request IDs,
|
|
6
|
+
* and idempotency keys.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Parsed UCP request headers.
|
|
10
|
+
*/
|
|
11
|
+
export type UcpRequestHeaders = {
|
|
12
|
+
/** Agent profile URL from UCP-Agent header */
|
|
13
|
+
agentProfile: string | null;
|
|
14
|
+
/** Request ID for tracing */
|
|
15
|
+
requestId: string | null;
|
|
16
|
+
/** Idempotency key for state-modifying operations */
|
|
17
|
+
idempotencyKey: string | null;
|
|
18
|
+
/** Content digest for body verification */
|
|
19
|
+
contentDigest: string | null;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Extract UCP-specific headers from a request.
|
|
23
|
+
*
|
|
24
|
+
* UCP-Agent header format: profile="https://agent.example/.well-known/ucp"
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseUcpHeaders(request: Request): UcpRequestHeaders;
|
|
27
|
+
/**
|
|
28
|
+
* Validate that required UCP headers are present for state-modifying operations.
|
|
29
|
+
* Returns an error message if validation fails, null if OK.
|
|
30
|
+
*/
|
|
31
|
+
export declare function validateUcpHeaders(headers: UcpRequestHeaders, options?: {
|
|
32
|
+
requireAgent?: boolean;
|
|
33
|
+
requireIdempotency?: boolean;
|
|
34
|
+
}): string | null;
|
|
35
|
+
/**
|
|
36
|
+
* Create standard UCP response headers.
|
|
37
|
+
*/
|
|
38
|
+
export declare function ucpResponseHeaders(requestId?: string | null): Record<string, string>;
|
|
39
|
+
//# sourceMappingURL=ucp-headers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ucp-headers.d.ts","sourceRoot":"","sources":["../../src/middleware/ucp-headers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,8CAA8C;IAC9C,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,6BAA6B;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,qDAAqD;IACrD,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,2CAA2C;IAC3C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B,CAAA;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,iBAAiB,CAgBnE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,iBAAiB,EAC1B,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAO,GACrE,MAAM,GAAG,IAAI,CAQf;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQpF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UCP Header Middleware
|
|
3
|
+
*
|
|
4
|
+
* Parses and validates UCP-specific headers from incoming requests.
|
|
5
|
+
* Used by route handlers to extract agent profile, request IDs,
|
|
6
|
+
* and idempotency keys.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Extract UCP-specific headers from a request.
|
|
10
|
+
*
|
|
11
|
+
* UCP-Agent header format: profile="https://agent.example/.well-known/ucp"
|
|
12
|
+
*/
|
|
13
|
+
export function parseUcpHeaders(request) {
|
|
14
|
+
const agentHeader = request.headers.get("UCP-Agent");
|
|
15
|
+
let agentProfile = null;
|
|
16
|
+
if (agentHeader) {
|
|
17
|
+
// Parse RFC 8941 Dictionary format: profile="url"
|
|
18
|
+
const match = agentHeader.match(/profile="([^"]+)"/);
|
|
19
|
+
agentProfile = match ? match[1] : agentHeader;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
agentProfile,
|
|
23
|
+
requestId: request.headers.get("Request-Id") || request.headers.get("X-Request-Id"),
|
|
24
|
+
idempotencyKey: request.headers.get("Idempotency-Key"),
|
|
25
|
+
contentDigest: request.headers.get("Content-Digest"),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validate that required UCP headers are present for state-modifying operations.
|
|
30
|
+
* Returns an error message if validation fails, null if OK.
|
|
31
|
+
*/
|
|
32
|
+
export function validateUcpHeaders(headers, options = {}) {
|
|
33
|
+
if (options.requireAgent && !headers.agentProfile) {
|
|
34
|
+
return "UCP-Agent header is required";
|
|
35
|
+
}
|
|
36
|
+
if (options.requireIdempotency && !headers.idempotencyKey) {
|
|
37
|
+
return "Idempotency-Key header is required";
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create standard UCP response headers.
|
|
43
|
+
*/
|
|
44
|
+
export function ucpResponseHeaders(requestId) {
|
|
45
|
+
const headers = {
|
|
46
|
+
"Content-Type": "application/json",
|
|
47
|
+
};
|
|
48
|
+
if (requestId) {
|
|
49
|
+
headers["Request-Id"] = requestId;
|
|
50
|
+
}
|
|
51
|
+
return headers;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=ucp-headers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ucp-headers.js","sourceRoot":"","sources":["../../src/middleware/ucp-headers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACpD,IAAI,YAAY,GAAkB,IAAI,CAAA;IAEtC,IAAI,WAAW,EAAE,CAAC;QAChB,kDAAkD;QAClD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAA;QACpD,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAA;IAC/C,CAAC;IAED,OAAO;QACL,YAAY;QACZ,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QACnF,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACtD,aAAa,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;KACrD,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAA0B,EAC1B,UAAoE,EAAE;IAEtE,IAAI,OAAO,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QAClD,OAAO,8BAA8B,CAAA;IACvC,CAAC;IACD,IAAI,OAAO,CAAC,kBAAkB,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC1D,OAAO,oCAAoC,CAAA;IAC7C,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAyB;IAC1D,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;KACnC,CAAA;IACD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;IACnC,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACP Route Handlers
|
|
3
|
+
*
|
|
4
|
+
* Creates Next.js App Router route handlers for all ACP endpoints.
|
|
5
|
+
* Based on ACP spec version 2026-01-30.
|
|
6
|
+
* https://github.com/agentic-commerce-protocol/agentic-commerce-protocol/tree/main/spec/2026-01-30
|
|
7
|
+
*
|
|
8
|
+
* Endpoints:
|
|
9
|
+
* - POST /api/acp/checkout_sessions — Create checkout session
|
|
10
|
+
* - POST /api/acp/checkout_sessions/[id] — Update checkout session
|
|
11
|
+
* - GET /api/acp/checkout_sessions/[id] — Get checkout session
|
|
12
|
+
* - POST /api/acp/checkout_sessions/[id]/complete — Complete checkout session
|
|
13
|
+
* - POST /api/acp/checkout_sessions/[id]/cancel — Cancel checkout session
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* ```ts
|
|
17
|
+
* // src/lib/agentic-commerce.ts
|
|
18
|
+
* export const agenticCommerce = createAgenticCommerce({ ... })
|
|
19
|
+
* export const acpRoutes = createAcpRoutes(agenticCommerce)
|
|
20
|
+
*
|
|
21
|
+
* // src/app/api/acp/checkout_sessions/route.ts
|
|
22
|
+
* export { POST } from '@/lib/agentic-commerce'
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
import type { AgenticCommerceInstance } from "../config.js";
|
|
26
|
+
export type AcpRouteHandlers = {
|
|
27
|
+
/** POST /api/acp/checkout_sessions */
|
|
28
|
+
checkoutSessions: {
|
|
29
|
+
POST: (request: Request) => Promise<Response>;
|
|
30
|
+
};
|
|
31
|
+
/** GET, POST /api/acp/checkout_sessions/[id] */
|
|
32
|
+
checkoutSession: {
|
|
33
|
+
GET: (request: Request, context: {
|
|
34
|
+
params: Promise<{
|
|
35
|
+
id: string;
|
|
36
|
+
}>;
|
|
37
|
+
}) => Promise<Response>;
|
|
38
|
+
POST: (request: Request, context: {
|
|
39
|
+
params: Promise<{
|
|
40
|
+
id: string;
|
|
41
|
+
}>;
|
|
42
|
+
}) => Promise<Response>;
|
|
43
|
+
};
|
|
44
|
+
/** POST /api/acp/checkout_sessions/[id]/complete */
|
|
45
|
+
checkoutSessionComplete: {
|
|
46
|
+
POST: (request: Request, context: {
|
|
47
|
+
params: Promise<{
|
|
48
|
+
id: string;
|
|
49
|
+
}>;
|
|
50
|
+
}) => Promise<Response>;
|
|
51
|
+
};
|
|
52
|
+
/** POST /api/acp/checkout_sessions/[id]/cancel */
|
|
53
|
+
checkoutSessionCancel: {
|
|
54
|
+
POST: (request: Request, context: {
|
|
55
|
+
params: Promise<{
|
|
56
|
+
id: string;
|
|
57
|
+
}>;
|
|
58
|
+
}) => Promise<Response>;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
export declare function createAcpRoutes(instance: AgenticCommerceInstance): AcpRouteHandlers;
|
|
62
|
+
//# sourceMappingURL=acp-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-routes.d.ts","sourceRoot":"","sources":["../../src/routes/acp-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAUH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AAE3D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,sCAAsC;IACtC,gBAAgB,EAAE;QAChB,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;KAC9C,CAAA;IACD,gDAAgD;IAChD,eAAe,EAAE;QACf,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAAE,MAAM,EAAE,OAAO,CAAC;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC1F,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAAE,MAAM,EAAE,OAAO,CAAC;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;KAC5F,CAAA;IACD,oDAAoD;IACpD,uBAAuB,EAAE;QACvB,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAAE,MAAM,EAAE,OAAO,CAAC;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;KAC5F,CAAA;IACD,kDAAkD;IAClD,qBAAqB,EAAE;QACrB,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAAE,MAAM,EAAE,OAAO,CAAC;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;KAC5F,CAAA;CACF,CAAA;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,uBAAuB,GAAG,gBAAgB,CA6RnF"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACP Route Handlers
|
|
3
|
+
*
|
|
4
|
+
* Creates Next.js App Router route handlers for all ACP endpoints.
|
|
5
|
+
* Based on ACP spec version 2026-01-30.
|
|
6
|
+
* https://github.com/agentic-commerce-protocol/agentic-commerce-protocol/tree/main/spec/2026-01-30
|
|
7
|
+
*
|
|
8
|
+
* Endpoints:
|
|
9
|
+
* - POST /api/acp/checkout_sessions — Create checkout session
|
|
10
|
+
* - POST /api/acp/checkout_sessions/[id] — Update checkout session
|
|
11
|
+
* - GET /api/acp/checkout_sessions/[id] — Get checkout session
|
|
12
|
+
* - POST /api/acp/checkout_sessions/[id]/complete — Complete checkout session
|
|
13
|
+
* - POST /api/acp/checkout_sessions/[id]/cancel — Cancel checkout session
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* ```ts
|
|
17
|
+
* // src/lib/agentic-commerce.ts
|
|
18
|
+
* export const agenticCommerce = createAgenticCommerce({ ... })
|
|
19
|
+
* export const acpRoutes = createAcpRoutes(agenticCommerce)
|
|
20
|
+
*
|
|
21
|
+
* // src/app/api/acp/checkout_sessions/route.ts
|
|
22
|
+
* export { POST } from '@/lib/agentic-commerce'
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
import { formatAcpCheckoutSession, formatAcpCompleteResponse, formatAcpError, acpToSaleorAddress, metadataToRecord, recordToMetadataInput, } from "@financedistrict/saleor-agentic-commerce-core";
|
|
26
|
+
export function createAcpRoutes(instance) {
|
|
27
|
+
const { saleorClient, paymentHandlers, formatterContext, config } = instance;
|
|
28
|
+
function acpError(code, message, status) {
|
|
29
|
+
return Response.json(formatAcpError({ code, message, httpStatus: status }), { status });
|
|
30
|
+
}
|
|
31
|
+
function validateApiKey(request) {
|
|
32
|
+
if (!config.acpApiKey)
|
|
33
|
+
return true; // No key configured = open access
|
|
34
|
+
const auth = request.headers.get("Authorization");
|
|
35
|
+
return auth === `Bearer ${config.acpApiKey}`;
|
|
36
|
+
}
|
|
37
|
+
function endpointBaseUrl(request) {
|
|
38
|
+
const url = new URL(request.url);
|
|
39
|
+
return `${url.origin}/api/acp`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Shared helper: prepare payment handlers and store metadata on checkout.
|
|
43
|
+
* Returns the final checkout with updated metadata.
|
|
44
|
+
*/
|
|
45
|
+
async function preparePaymentAndRefetch(checkoutId, checkout, baseUrl) {
|
|
46
|
+
const totalAmount = Math.round(checkout.totalPrice.gross.amount * 100);
|
|
47
|
+
const metadata = metadataToRecord(checkout.privateMetadata);
|
|
48
|
+
const prepareResults = await paymentHandlers.prepareCheckoutPayment({
|
|
49
|
+
checkoutId,
|
|
50
|
+
total: totalAmount,
|
|
51
|
+
currencyCode: checkout.totalPrice.gross.currency,
|
|
52
|
+
checkoutBaseUrl: `${baseUrl}/checkout_sessions`,
|
|
53
|
+
storeName: config.storeName,
|
|
54
|
+
checkoutMetadata: metadata,
|
|
55
|
+
});
|
|
56
|
+
const metadataUpdates = recordToMetadataInput(prepareResults);
|
|
57
|
+
if (metadataUpdates.length > 0) {
|
|
58
|
+
await saleorClient.updatePrivateMetadata(checkoutId, metadataUpdates);
|
|
59
|
+
}
|
|
60
|
+
const updatedCheckout = await saleorClient.getCheckout(checkoutId);
|
|
61
|
+
return updatedCheckout.ok ? updatedCheckout.data : checkout;
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
// =====================================================
|
|
65
|
+
// Create Checkout — POST /api/acp/checkout_sessions
|
|
66
|
+
// =====================================================
|
|
67
|
+
checkoutSessions: {
|
|
68
|
+
async POST(request) {
|
|
69
|
+
if (!validateApiKey(request)) {
|
|
70
|
+
return acpError("unauthorized", "Invalid or missing API key", 401);
|
|
71
|
+
}
|
|
72
|
+
let body;
|
|
73
|
+
try {
|
|
74
|
+
body = await request.json();
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return acpError("invalid_body", "Request body must be valid JSON", 400);
|
|
78
|
+
}
|
|
79
|
+
const lineItems = body.line_items;
|
|
80
|
+
if (!Array.isArray(lineItems) || lineItems.length === 0) {
|
|
81
|
+
return acpError("missing", "line_items array is required", 400);
|
|
82
|
+
}
|
|
83
|
+
// Map ACP line items to Saleor checkout lines
|
|
84
|
+
// ACP spec: line_items[].item.id, line_items[].quantity
|
|
85
|
+
const lines = lineItems.map((li) => ({
|
|
86
|
+
variantId: li.item?.id || li.id,
|
|
87
|
+
quantity: li.quantity || 1,
|
|
88
|
+
}));
|
|
89
|
+
// Extract buyer info
|
|
90
|
+
const email = body.buyer?.email;
|
|
91
|
+
// Extract fulfillment address from fulfillment_details
|
|
92
|
+
const shippingAddress = body.fulfillment_details?.address
|
|
93
|
+
? acpToSaleorAddress(body.fulfillment_details.address)
|
|
94
|
+
: undefined;
|
|
95
|
+
const billingAddress = body.billing_address
|
|
96
|
+
? acpToSaleorAddress(body.billing_address)
|
|
97
|
+
: undefined;
|
|
98
|
+
// Create Saleor checkout
|
|
99
|
+
const checkoutResult = await saleorClient.createCheckout({
|
|
100
|
+
lines,
|
|
101
|
+
email,
|
|
102
|
+
shippingAddress,
|
|
103
|
+
billingAddress,
|
|
104
|
+
});
|
|
105
|
+
if (!checkoutResult.ok) {
|
|
106
|
+
return acpError("checkout_create_failed", checkoutResult.error, 422);
|
|
107
|
+
}
|
|
108
|
+
const baseUrl = endpointBaseUrl(request);
|
|
109
|
+
const finalCheckout = await preparePaymentAndRefetch(checkoutResult.data.id, checkoutResult.data, baseUrl);
|
|
110
|
+
const session = formatAcpCheckoutSession(formatterContext, finalCheckout);
|
|
111
|
+
return Response.json(session, { status: 201 });
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
// =====================================================
|
|
115
|
+
// Get/Update Checkout Session
|
|
116
|
+
// =====================================================
|
|
117
|
+
checkoutSession: {
|
|
118
|
+
async GET(request, context) {
|
|
119
|
+
if (!validateApiKey(request)) {
|
|
120
|
+
return acpError("unauthorized", "Invalid or missing API key", 401);
|
|
121
|
+
}
|
|
122
|
+
const { id } = await context.params;
|
|
123
|
+
const result = await saleorClient.getCheckout(id);
|
|
124
|
+
if (!result.ok)
|
|
125
|
+
return acpError("not_found", result.error, 404);
|
|
126
|
+
const session = formatAcpCheckoutSession(formatterContext, result.data);
|
|
127
|
+
return Response.json(session);
|
|
128
|
+
},
|
|
129
|
+
// ACP spec: Update uses POST (not PUT)
|
|
130
|
+
async POST(request, context) {
|
|
131
|
+
if (!validateApiKey(request)) {
|
|
132
|
+
return acpError("unauthorized", "Invalid or missing API key", 401);
|
|
133
|
+
}
|
|
134
|
+
const { id } = await context.params;
|
|
135
|
+
let body;
|
|
136
|
+
try {
|
|
137
|
+
body = await request.json();
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return acpError("invalid_body", "Request body must be valid JSON", 400);
|
|
141
|
+
}
|
|
142
|
+
// Update buyer email
|
|
143
|
+
if (body.buyer?.email) {
|
|
144
|
+
const result = await saleorClient.updateCheckoutEmail(id, body.buyer.email);
|
|
145
|
+
if (!result.ok)
|
|
146
|
+
return acpError("invalid", result.error, 422);
|
|
147
|
+
}
|
|
148
|
+
// Update fulfillment details (address)
|
|
149
|
+
if (body.fulfillment_details?.address) {
|
|
150
|
+
const addr = acpToSaleorAddress(body.fulfillment_details.address);
|
|
151
|
+
const result = await saleorClient.updateCheckoutShippingAddress(id, addr);
|
|
152
|
+
if (!result.ok)
|
|
153
|
+
return acpError("invalid", result.error, 422);
|
|
154
|
+
}
|
|
155
|
+
// Update billing address
|
|
156
|
+
if (body.billing_address) {
|
|
157
|
+
const addr = acpToSaleorAddress(body.billing_address);
|
|
158
|
+
const result = await saleorClient.updateCheckoutBillingAddress(id, addr);
|
|
159
|
+
if (!result.ok)
|
|
160
|
+
return acpError("invalid", result.error, 422);
|
|
161
|
+
}
|
|
162
|
+
// Update selected fulfillment option
|
|
163
|
+
if (body.selected_fulfillment_options && Array.isArray(body.selected_fulfillment_options)) {
|
|
164
|
+
const selected = body.selected_fulfillment_options[0];
|
|
165
|
+
if (selected?.option_id) {
|
|
166
|
+
const result = await saleorClient.updateCheckoutDeliveryMethod(id, selected.option_id);
|
|
167
|
+
if (!result.ok)
|
|
168
|
+
return acpError("invalid", result.error, 422);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Update line items if provided
|
|
172
|
+
if (body.line_items && Array.isArray(body.line_items)) {
|
|
173
|
+
const lines = body.line_items.map((li) => ({
|
|
174
|
+
variantId: li.item?.id || li.id,
|
|
175
|
+
quantity: li.quantity || 1,
|
|
176
|
+
}));
|
|
177
|
+
const result = await saleorClient.updateCheckoutLines(id, lines);
|
|
178
|
+
if (!result.ok)
|
|
179
|
+
return acpError("invalid", result.error, 422);
|
|
180
|
+
}
|
|
181
|
+
// Re-fetch and prepare payment
|
|
182
|
+
const checkoutResult = await saleorClient.getCheckout(id);
|
|
183
|
+
if (!checkoutResult.ok)
|
|
184
|
+
return acpError("not_found", checkoutResult.error, 404);
|
|
185
|
+
const baseUrl = endpointBaseUrl(request);
|
|
186
|
+
const finalCheckout = await preparePaymentAndRefetch(id, checkoutResult.data, baseUrl);
|
|
187
|
+
const session = formatAcpCheckoutSession(formatterContext, finalCheckout);
|
|
188
|
+
return Response.json(session);
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
// =====================================================
|
|
192
|
+
// Complete Checkout — returns full session + order
|
|
193
|
+
// =====================================================
|
|
194
|
+
checkoutSessionComplete: {
|
|
195
|
+
async POST(request, context) {
|
|
196
|
+
if (!validateApiKey(request)) {
|
|
197
|
+
return acpError("unauthorized", "Invalid or missing API key", 401);
|
|
198
|
+
}
|
|
199
|
+
const { id } = await context.params;
|
|
200
|
+
let body;
|
|
201
|
+
try {
|
|
202
|
+
body = await request.json();
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return acpError("invalid_body", "Request body must be valid JSON", 400);
|
|
206
|
+
}
|
|
207
|
+
// ACP spec payment_data: { handler_id, instrument: { type, credential: { type, token } }, billing_address? }
|
|
208
|
+
const paymentData = body.payment_data;
|
|
209
|
+
if (!paymentData) {
|
|
210
|
+
return acpError("missing", "payment_data is required", 400);
|
|
211
|
+
}
|
|
212
|
+
// Update billing address if provided
|
|
213
|
+
if (paymentData.billing_address) {
|
|
214
|
+
const addr = acpToSaleorAddress(paymentData.billing_address);
|
|
215
|
+
await saleorClient.updateCheckoutBillingAddress(id, addr);
|
|
216
|
+
}
|
|
217
|
+
// Fetch checkout for metadata
|
|
218
|
+
const checkoutResult = await saleorClient.getCheckout(id);
|
|
219
|
+
if (!checkoutResult.ok)
|
|
220
|
+
return acpError("not_found", checkoutResult.error, 404);
|
|
221
|
+
const checkout = checkoutResult.data;
|
|
222
|
+
const metadata = metadataToRecord(checkout.privateMetadata);
|
|
223
|
+
// Determine the payment handler to use
|
|
224
|
+
const handlerId = paymentData.handler_id || "xyz.fd.prism_payment";
|
|
225
|
+
// Extract credential from instrument
|
|
226
|
+
const credential = paymentData.instrument?.credential || paymentData.credential;
|
|
227
|
+
// Settle payment via the appropriate handler
|
|
228
|
+
const settleResult = await paymentHandlers.settlePayment({
|
|
229
|
+
checkoutId: id,
|
|
230
|
+
handlerId,
|
|
231
|
+
credential,
|
|
232
|
+
checkoutMetadata: metadata,
|
|
233
|
+
});
|
|
234
|
+
if (!settleResult.success) {
|
|
235
|
+
return acpError("payment_declined", settleResult.error || "Payment settlement failed", 422);
|
|
236
|
+
}
|
|
237
|
+
// Complete checkout in Saleor
|
|
238
|
+
const orderResult = await saleorClient.completeCheckout(id);
|
|
239
|
+
if (!orderResult.ok)
|
|
240
|
+
return acpError("processing_error", orderResult.error, 422);
|
|
241
|
+
// Return full session with completed status + order
|
|
242
|
+
const response = formatAcpCompleteResponse(formatterContext, checkout, orderResult.data);
|
|
243
|
+
return Response.json(response);
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
// =====================================================
|
|
247
|
+
// Cancel Checkout — returns full session with canceled status
|
|
248
|
+
// =====================================================
|
|
249
|
+
checkoutSessionCancel: {
|
|
250
|
+
async POST(request, context) {
|
|
251
|
+
if (!validateApiKey(request)) {
|
|
252
|
+
return acpError("unauthorized", "Invalid or missing API key", 401);
|
|
253
|
+
}
|
|
254
|
+
const { id } = await context.params;
|
|
255
|
+
// Verify checkout exists
|
|
256
|
+
const result = await saleorClient.getCheckout(id);
|
|
257
|
+
if (!result.ok)
|
|
258
|
+
return acpError("not_found", result.error, 404);
|
|
259
|
+
// Mark as canceled via metadata
|
|
260
|
+
await saleorClient.updatePrivateMetadata(id, [
|
|
261
|
+
{ key: "acp_canceled", value: "true" },
|
|
262
|
+
{ key: "acp_canceled_at", value: new Date().toISOString() },
|
|
263
|
+
]);
|
|
264
|
+
// Return full session with canceled status
|
|
265
|
+
const session = formatAcpCheckoutSession(formatterContext, result.data);
|
|
266
|
+
return Response.json({
|
|
267
|
+
...session,
|
|
268
|
+
status: "canceled",
|
|
269
|
+
});
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=acp-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-routes.js","sourceRoot":"","sources":["../../src/routes/acp-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UCP Route Handlers
|
|
3
|
+
*
|
|
4
|
+
* Creates Next.js App Router route handlers for all UCP endpoints.
|
|
5
|
+
* Based on UCP spec version 2026-04-08.
|
|
6
|
+
* https://ucp.dev/2026-04-08/specification/overview
|
|
7
|
+
*
|
|
8
|
+
* Endpoints:
|
|
9
|
+
* - GET /.well-known/ucp — Discovery profile
|
|
10
|
+
* - POST /api/ucp/checkout-sessions — Create checkout
|
|
11
|
+
* - GET /api/ucp/checkout-sessions/[id] — Get checkout
|
|
12
|
+
* - PUT /api/ucp/checkout-sessions/[id] — Update checkout
|
|
13
|
+
* - POST /api/ucp/checkout-sessions/[id]/complete — Complete checkout
|
|
14
|
+
* - POST /api/ucp/checkout-sessions/[id]/cancel — Cancel checkout
|
|
15
|
+
* - GET /api/ucp/orders/[id] — Get order
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ```ts
|
|
19
|
+
* // src/lib/agentic-commerce.ts
|
|
20
|
+
* export const agenticCommerce = createAgenticCommerce({ ... })
|
|
21
|
+
* export const ucpRoutes = createUcpRoutes(agenticCommerce)
|
|
22
|
+
*
|
|
23
|
+
* // src/app/.well-known/ucp/route.ts
|
|
24
|
+
* export { GET } from '@/lib/agentic-commerce'
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
import type { AgenticCommerceInstance } from "../config.js";
|
|
28
|
+
export type UcpRouteHandlers = {
|
|
29
|
+
/** GET /.well-known/ucp */
|
|
30
|
+
discovery: {
|
|
31
|
+
GET: (request: Request) => Promise<Response>;
|
|
32
|
+
};
|
|
33
|
+
/** POST /api/ucp/checkout-sessions */
|
|
34
|
+
checkoutSessions: {
|
|
35
|
+
POST: (request: Request) => Promise<Response>;
|
|
36
|
+
};
|
|
37
|
+
/** GET, PUT /api/ucp/checkout-sessions/[id] */
|
|
38
|
+
checkoutSession: {
|
|
39
|
+
GET: (request: Request, context: {
|
|
40
|
+
params: Promise<{
|
|
41
|
+
id: string;
|
|
42
|
+
}>;
|
|
43
|
+
}) => Promise<Response>;
|
|
44
|
+
PUT: (request: Request, context: {
|
|
45
|
+
params: Promise<{
|
|
46
|
+
id: string;
|
|
47
|
+
}>;
|
|
48
|
+
}) => Promise<Response>;
|
|
49
|
+
};
|
|
50
|
+
/** POST /api/ucp/checkout-sessions/[id]/complete */
|
|
51
|
+
checkoutSessionComplete: {
|
|
52
|
+
POST: (request: Request, context: {
|
|
53
|
+
params: Promise<{
|
|
54
|
+
id: string;
|
|
55
|
+
}>;
|
|
56
|
+
}) => Promise<Response>;
|
|
57
|
+
};
|
|
58
|
+
/** POST /api/ucp/checkout-sessions/[id]/cancel */
|
|
59
|
+
checkoutSessionCancel: {
|
|
60
|
+
POST: (request: Request, context: {
|
|
61
|
+
params: Promise<{
|
|
62
|
+
id: string;
|
|
63
|
+
}>;
|
|
64
|
+
}) => Promise<Response>;
|
|
65
|
+
};
|
|
66
|
+
/** GET /api/ucp/orders/[id] */
|
|
67
|
+
order: {
|
|
68
|
+
GET: (request: Request, context: {
|
|
69
|
+
params: Promise<{
|
|
70
|
+
id: string;
|
|
71
|
+
}>;
|
|
72
|
+
}) => Promise<Response>;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
export declare function createUcpRoutes(instance: AgenticCommerceInstance): UcpRouteHandlers;
|
|
76
|
+
//# sourceMappingURL=ucp-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ucp-routes.d.ts","sourceRoot":"","sources":["../../src/routes/ucp-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAYH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AAE3D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,2BAA2B;IAC3B,SAAS,EAAE;QACT,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;KAC7C,CAAA;IACD,sCAAsC;IACtC,gBAAgB,EAAE;QAChB,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;KAC9C,CAAA;IACD,+CAA+C;IAC/C,eAAe,EAAE;QACf,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAAE,MAAM,EAAE,OAAO,CAAC;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC1F,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAAE,MAAM,EAAE,OAAO,CAAC;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;KAC3F,CAAA;IACD,oDAAoD;IACpD,uBAAuB,EAAE;QACvB,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAAE,MAAM,EAAE,OAAO,CAAC;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;KAC5F,CAAA;IACD,kDAAkD;IAClD,qBAAqB,EAAE;QACrB,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAAE,MAAM,EAAE,OAAO,CAAC;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;KAC5F,CAAA;IACD,+BAA+B;IAC/B,KAAK,EAAE;QACL,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;YAAE,MAAM,EAAE,OAAO,CAAC;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;KAC3F,CAAA;CACF,CAAA;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,uBAAuB,GAAG,gBAAgB,CA6RnF"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UCP Route Handlers
|
|
3
|
+
*
|
|
4
|
+
* Creates Next.js App Router route handlers for all UCP endpoints.
|
|
5
|
+
* Based on UCP spec version 2026-04-08.
|
|
6
|
+
* https://ucp.dev/2026-04-08/specification/overview
|
|
7
|
+
*
|
|
8
|
+
* Endpoints:
|
|
9
|
+
* - GET /.well-known/ucp — Discovery profile
|
|
10
|
+
* - POST /api/ucp/checkout-sessions — Create checkout
|
|
11
|
+
* - GET /api/ucp/checkout-sessions/[id] — Get checkout
|
|
12
|
+
* - PUT /api/ucp/checkout-sessions/[id] — Update checkout
|
|
13
|
+
* - POST /api/ucp/checkout-sessions/[id]/complete — Complete checkout
|
|
14
|
+
* - POST /api/ucp/checkout-sessions/[id]/cancel — Cancel checkout
|
|
15
|
+
* - GET /api/ucp/orders/[id] — Get order
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ```ts
|
|
19
|
+
* // src/lib/agentic-commerce.ts
|
|
20
|
+
* export const agenticCommerce = createAgenticCommerce({ ... })
|
|
21
|
+
* export const ucpRoutes = createUcpRoutes(agenticCommerce)
|
|
22
|
+
*
|
|
23
|
+
* // src/app/.well-known/ucp/route.ts
|
|
24
|
+
* export { GET } from '@/lib/agentic-commerce'
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
import { formatUcpProfile, formatUcpCheckoutSession, formatUcpCompleteResponse, formatUcpOrder, formatUcpError, ucpToSaleorAddress, metadataToRecord, recordToMetadataInput, } from "@financedistrict/saleor-agentic-commerce-core";
|
|
28
|
+
export function createUcpRoutes(instance) {
|
|
29
|
+
const { saleorClient, paymentHandlers, formatterContext, config } = instance;
|
|
30
|
+
function ucpError(code, content, status) {
|
|
31
|
+
return Response.json(formatUcpError({ ucpVersion: config.ucpVersion, code, content }), { status });
|
|
32
|
+
}
|
|
33
|
+
function endpointBaseUrl(request) {
|
|
34
|
+
const url = new URL(request.url);
|
|
35
|
+
return `${url.origin}/api/ucp`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Shared helper: prepare payment handlers and store metadata on checkout.
|
|
39
|
+
* Returns the final checkout with updated metadata.
|
|
40
|
+
*/
|
|
41
|
+
async function preparePaymentAndRefetch(checkoutId, checkout, baseUrl) {
|
|
42
|
+
const totalAmount = Math.round(checkout.totalPrice.gross.amount * 100);
|
|
43
|
+
const metadata = metadataToRecord(checkout.privateMetadata);
|
|
44
|
+
const prepareResults = await paymentHandlers.prepareCheckoutPayment({
|
|
45
|
+
checkoutId,
|
|
46
|
+
total: totalAmount,
|
|
47
|
+
currencyCode: checkout.totalPrice.gross.currency,
|
|
48
|
+
checkoutBaseUrl: `${baseUrl}/checkout-sessions`,
|
|
49
|
+
storeName: config.storeName,
|
|
50
|
+
checkoutMetadata: metadata,
|
|
51
|
+
});
|
|
52
|
+
const metadataUpdates = recordToMetadataInput(prepareResults);
|
|
53
|
+
if (metadataUpdates.length > 0) {
|
|
54
|
+
await saleorClient.updatePrivateMetadata(checkoutId, metadataUpdates);
|
|
55
|
+
}
|
|
56
|
+
const updatedCheckout = await saleorClient.getCheckout(checkoutId);
|
|
57
|
+
return updatedCheckout.ok ? updatedCheckout.data : checkout;
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
// =====================================================
|
|
61
|
+
// Discovery — GET /.well-known/ucp
|
|
62
|
+
// =====================================================
|
|
63
|
+
discovery: {
|
|
64
|
+
async GET(request) {
|
|
65
|
+
const baseUrl = endpointBaseUrl(request);
|
|
66
|
+
const profile = await formatUcpProfile(formatterContext, baseUrl);
|
|
67
|
+
return Response.json(profile, {
|
|
68
|
+
headers: {
|
|
69
|
+
"Cache-Control": "public, max-age=300",
|
|
70
|
+
"Content-Type": "application/json",
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
// =====================================================
|
|
76
|
+
// Create Checkout Session — POST /api/ucp/checkout-sessions
|
|
77
|
+
// =====================================================
|
|
78
|
+
checkoutSessions: {
|
|
79
|
+
async POST(request) {
|
|
80
|
+
let body;
|
|
81
|
+
try {
|
|
82
|
+
body = await request.json();
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return ucpError("invalid_body", "Request body must be valid JSON", 400);
|
|
86
|
+
}
|
|
87
|
+
const lineItems = body.line_items;
|
|
88
|
+
if (!Array.isArray(lineItems) || lineItems.length === 0) {
|
|
89
|
+
return ucpError("missing_line_items", "line_items array is required", 400);
|
|
90
|
+
}
|
|
91
|
+
// Map UCP line items to Saleor checkout lines
|
|
92
|
+
const lines = lineItems.map((item) => ({
|
|
93
|
+
variantId: item.item?.id || item.id,
|
|
94
|
+
quantity: item.quantity || 1,
|
|
95
|
+
}));
|
|
96
|
+
// Extract buyer email
|
|
97
|
+
const email = body.buyer?.email;
|
|
98
|
+
// Extract fulfillment address from fulfillment.methods[0].destinations[0]
|
|
99
|
+
const fulfillmentDest = body.fulfillment?.methods?.[0]?.destinations?.[0];
|
|
100
|
+
const shippingAddress = fulfillmentDest
|
|
101
|
+
? ucpToSaleorAddress(fulfillmentDest)
|
|
102
|
+
: undefined;
|
|
103
|
+
// Create Saleor checkout
|
|
104
|
+
const checkoutResult = await saleorClient.createCheckout({
|
|
105
|
+
lines,
|
|
106
|
+
email,
|
|
107
|
+
shippingAddress,
|
|
108
|
+
});
|
|
109
|
+
if (!checkoutResult.ok) {
|
|
110
|
+
return ucpError("checkout_create_failed", checkoutResult.error, 422);
|
|
111
|
+
}
|
|
112
|
+
const baseUrl = endpointBaseUrl(request);
|
|
113
|
+
const finalCheckout = await preparePaymentAndRefetch(checkoutResult.data.id, checkoutResult.data, baseUrl);
|
|
114
|
+
const session = formatUcpCheckoutSession(formatterContext, finalCheckout);
|
|
115
|
+
return Response.json(session, { status: 201 });
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
// =====================================================
|
|
119
|
+
// Get/Update Checkout Session
|
|
120
|
+
// =====================================================
|
|
121
|
+
checkoutSession: {
|
|
122
|
+
async GET(request, context) {
|
|
123
|
+
const { id } = await context.params;
|
|
124
|
+
const result = await saleorClient.getCheckout(id);
|
|
125
|
+
if (!result.ok)
|
|
126
|
+
return ucpError("checkout_not_found", result.error, 404);
|
|
127
|
+
const session = formatUcpCheckoutSession(formatterContext, result.data);
|
|
128
|
+
return Response.json(session);
|
|
129
|
+
},
|
|
130
|
+
async PUT(request, context) {
|
|
131
|
+
const { id } = await context.params;
|
|
132
|
+
let body;
|
|
133
|
+
try {
|
|
134
|
+
body = await request.json();
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return ucpError("invalid_body", "Request body must be valid JSON", 400);
|
|
138
|
+
}
|
|
139
|
+
// Update buyer email
|
|
140
|
+
if (body.buyer?.email) {
|
|
141
|
+
const result = await saleorClient.updateCheckoutEmail(id, body.buyer.email);
|
|
142
|
+
if (!result.ok)
|
|
143
|
+
return ucpError("email_update_failed", result.error, 422);
|
|
144
|
+
}
|
|
145
|
+
// Update fulfillment: extract destination address and selected option
|
|
146
|
+
if (body.fulfillment?.methods) {
|
|
147
|
+
const method = body.fulfillment.methods[0];
|
|
148
|
+
if (method) {
|
|
149
|
+
// Update shipping address from destination
|
|
150
|
+
const dest = method.destinations?.[0];
|
|
151
|
+
if (dest) {
|
|
152
|
+
const addr = ucpToSaleorAddress(dest);
|
|
153
|
+
const result = await saleorClient.updateCheckoutShippingAddress(id, addr);
|
|
154
|
+
if (!result.ok)
|
|
155
|
+
return ucpError("shipping_address_update_failed", result.error, 422);
|
|
156
|
+
}
|
|
157
|
+
// Update delivery method from selected option
|
|
158
|
+
const selectedOptionId = method.groups?.[0]?.selected_option_id;
|
|
159
|
+
if (selectedOptionId) {
|
|
160
|
+
const result = await saleorClient.updateCheckoutDeliveryMethod(id, selectedOptionId);
|
|
161
|
+
if (!result.ok)
|
|
162
|
+
return ucpError("delivery_method_update_failed", result.error, 422);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Update line items if provided
|
|
167
|
+
if (body.line_items && Array.isArray(body.line_items)) {
|
|
168
|
+
const lines = body.line_items.map((item) => ({
|
|
169
|
+
variantId: item.item?.id || item.id,
|
|
170
|
+
quantity: item.quantity || 1,
|
|
171
|
+
}));
|
|
172
|
+
const result = await saleorClient.updateCheckoutLines(id, lines);
|
|
173
|
+
if (!result.ok)
|
|
174
|
+
return ucpError("items_update_failed", result.error, 422);
|
|
175
|
+
}
|
|
176
|
+
// Re-fetch and prepare payment
|
|
177
|
+
const checkoutResult = await saleorClient.getCheckout(id);
|
|
178
|
+
if (!checkoutResult.ok)
|
|
179
|
+
return ucpError("checkout_not_found", checkoutResult.error, 404);
|
|
180
|
+
const baseUrl = endpointBaseUrl(request);
|
|
181
|
+
const finalCheckout = await preparePaymentAndRefetch(id, checkoutResult.data, baseUrl);
|
|
182
|
+
const session = formatUcpCheckoutSession(formatterContext, finalCheckout);
|
|
183
|
+
return Response.json(session);
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
// =====================================================
|
|
187
|
+
// Complete Checkout Session
|
|
188
|
+
// =====================================================
|
|
189
|
+
checkoutSessionComplete: {
|
|
190
|
+
async POST(request, context) {
|
|
191
|
+
const { id } = await context.params;
|
|
192
|
+
let body;
|
|
193
|
+
try {
|
|
194
|
+
body = await request.json();
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return ucpError("invalid_body", "Request body must be valid JSON", 400);
|
|
198
|
+
}
|
|
199
|
+
// Extract payment instrument
|
|
200
|
+
const payment = body.payment;
|
|
201
|
+
if (!payment?.instruments || !Array.isArray(payment.instruments)) {
|
|
202
|
+
return ucpError("missing_payment", "payment.instruments array is required", 400);
|
|
203
|
+
}
|
|
204
|
+
const selectedInstrument = payment.instruments.find((i) => i.selected) || payment.instruments[0];
|
|
205
|
+
if (!selectedInstrument) {
|
|
206
|
+
return ucpError("no_instrument_selected", "At least one payment instrument must be provided", 400);
|
|
207
|
+
}
|
|
208
|
+
// Fetch checkout for metadata
|
|
209
|
+
const checkoutResult = await saleorClient.getCheckout(id);
|
|
210
|
+
if (!checkoutResult.ok)
|
|
211
|
+
return ucpError("checkout_not_found", checkoutResult.error, 404);
|
|
212
|
+
const checkout = checkoutResult.data;
|
|
213
|
+
const metadata = metadataToRecord(checkout.privateMetadata);
|
|
214
|
+
// Update billing address if provided on instrument
|
|
215
|
+
if (selectedInstrument.billing_address) {
|
|
216
|
+
const addr = ucpToSaleorAddress(selectedInstrument.billing_address);
|
|
217
|
+
await saleorClient.updateCheckoutBillingAddress(id, addr);
|
|
218
|
+
}
|
|
219
|
+
// Settle payment via the appropriate handler
|
|
220
|
+
const settleResult = await paymentHandlers.settlePayment({
|
|
221
|
+
checkoutId: id,
|
|
222
|
+
handlerId: selectedInstrument.handler_id,
|
|
223
|
+
credential: selectedInstrument.credential,
|
|
224
|
+
checkoutMetadata: metadata,
|
|
225
|
+
});
|
|
226
|
+
if (!settleResult.success) {
|
|
227
|
+
return ucpError("payment_failed", settleResult.error || "Payment settlement failed", 422);
|
|
228
|
+
}
|
|
229
|
+
// Complete checkout in Saleor
|
|
230
|
+
const orderResult = await saleorClient.completeCheckout(id);
|
|
231
|
+
if (!orderResult.ok)
|
|
232
|
+
return ucpError("checkout_complete_failed", orderResult.error, 422);
|
|
233
|
+
// Return checkout session with completed status and order confirmation
|
|
234
|
+
const orderConfirmation = {
|
|
235
|
+
id: orderResult.data.id,
|
|
236
|
+
label: orderResult.data.number ?? undefined,
|
|
237
|
+
permalink_url: `${config.storefrontUrl}/orders/${orderResult.data.id}`,
|
|
238
|
+
};
|
|
239
|
+
const response = formatUcpCompleteResponse(formatterContext, checkout, orderConfirmation);
|
|
240
|
+
return Response.json(response);
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
// =====================================================
|
|
244
|
+
// Cancel Checkout Session
|
|
245
|
+
// =====================================================
|
|
246
|
+
checkoutSessionCancel: {
|
|
247
|
+
async POST(_request, context) {
|
|
248
|
+
const { id } = await context.params;
|
|
249
|
+
// Verify checkout exists
|
|
250
|
+
const result = await saleorClient.getCheckout(id);
|
|
251
|
+
if (!result.ok)
|
|
252
|
+
return ucpError("checkout_not_found", result.error, 404);
|
|
253
|
+
// Mark as canceled via metadata
|
|
254
|
+
await saleorClient.updatePrivateMetadata(id, [
|
|
255
|
+
{ key: "ucp_canceled", value: "true" },
|
|
256
|
+
{ key: "ucp_canceled_at", value: new Date().toISOString() },
|
|
257
|
+
]);
|
|
258
|
+
// Return full checkout session with canceled status
|
|
259
|
+
const session = formatUcpCheckoutSession(formatterContext, result.data);
|
|
260
|
+
return Response.json({
|
|
261
|
+
...session,
|
|
262
|
+
status: "canceled",
|
|
263
|
+
});
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
// =====================================================
|
|
267
|
+
// Get Order
|
|
268
|
+
// =====================================================
|
|
269
|
+
order: {
|
|
270
|
+
async GET(request, context) {
|
|
271
|
+
const { id } = await context.params;
|
|
272
|
+
const result = await saleorClient.getOrder(id);
|
|
273
|
+
if (!result.ok)
|
|
274
|
+
return ucpError("order_not_found", result.error, 404);
|
|
275
|
+
const order = formatUcpOrder(formatterContext, result.data);
|
|
276
|
+
return Response.json(order);
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=ucp-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ucp-routes.js","sourceRoot":"","sources":["../../src/routes/ucp-routes.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@financedistrict/saleor-agentic-commerce-nextjs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Drop-in Next.js route handlers that expose your Saleor storefront to AI shopping agents via UCP and ACP protocols.",
|
|
5
|
+
"author": "Finance District <dev@fd.xyz>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./routes/*": {
|
|
16
|
+
"types": "./dist/routes/*.d.ts",
|
|
17
|
+
"default": "./dist/routes/*.js"
|
|
18
|
+
},
|
|
19
|
+
"./middleware/*": {
|
|
20
|
+
"types": "./dist/middleware/*.d.ts",
|
|
21
|
+
"default": "./dist/middleware/*.js"
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"package.json",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc",
|
|
33
|
+
"dev": "tsc --watch",
|
|
34
|
+
"clean": "rm -rf dist"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"saleor",
|
|
38
|
+
"saleor-sdk",
|
|
39
|
+
"saleor-app",
|
|
40
|
+
"nextjs",
|
|
41
|
+
"next-js",
|
|
42
|
+
"app-router",
|
|
43
|
+
"route-handler",
|
|
44
|
+
"agentic-commerce",
|
|
45
|
+
"ai-commerce",
|
|
46
|
+
"ai-agent",
|
|
47
|
+
"ai-shopping",
|
|
48
|
+
"ucp",
|
|
49
|
+
"acp",
|
|
50
|
+
"universal-commerce-protocol",
|
|
51
|
+
"agentic-commerce-protocol",
|
|
52
|
+
"headless-commerce",
|
|
53
|
+
"storefront",
|
|
54
|
+
"commerce-api",
|
|
55
|
+
"checkout",
|
|
56
|
+
"shopping-agent",
|
|
57
|
+
"autonomous-agent"
|
|
58
|
+
],
|
|
59
|
+
"repository": {
|
|
60
|
+
"type": "git",
|
|
61
|
+
"url": "https://github.com/financedistrict-platform/saleor-agentic-commerce.git",
|
|
62
|
+
"directory": "packages/nextjs"
|
|
63
|
+
},
|
|
64
|
+
"homepage": "https://github.com/financedistrict-platform/saleor-agentic-commerce#readme",
|
|
65
|
+
"bugs": {
|
|
66
|
+
"url": "https://github.com/financedistrict-platform/saleor-agentic-commerce/issues"
|
|
67
|
+
},
|
|
68
|
+
"dependencies": {
|
|
69
|
+
"@financedistrict/saleor-agentic-commerce-core": "workspace:*"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"typescript": "^5.3.0"
|
|
73
|
+
}
|
|
74
|
+
}
|