@artos-commerce/ucp-cli 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/README.md +177 -0
- package/dist/agent.d.ts +35 -0
- package/dist/agent.js +46 -0
- package/dist/agent.js.map +1 -0
- package/dist/args.d.ts +20 -0
- package/dist/args.js +58 -0
- package/dist/args.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.js +250 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/account.d.ts +19 -0
- package/dist/commands/account.js +31 -0
- package/dist/commands/account.js.map +1 -0
- package/dist/commands/cart.d.ts +17 -0
- package/dist/commands/cart.js +51 -0
- package/dist/commands/cart.js.map +1 -0
- package/dist/commands/catalog-search.d.ts +22 -0
- package/dist/commands/catalog-search.js +27 -0
- package/dist/commands/catalog-search.js.map +1 -0
- package/dist/commands/checkout.d.ts +20 -0
- package/dist/commands/checkout.js +52 -0
- package/dist/commands/checkout.js.map +1 -0
- package/dist/commands/discover.d.ts +13 -0
- package/dist/commands/discover.js +27 -0
- package/dist/commands/discover.js.map +1 -0
- package/dist/commands/init.d.ts +16 -0
- package/dist/commands/init.js +222 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/profile-init.d.ts +22 -0
- package/dist/commands/profile-init.js +34 -0
- package/dist/commands/profile-init.js.map +1 -0
- package/dist/commands/purchase.d.ts +22 -0
- package/dist/commands/purchase.js +29 -0
- package/dist/commands/purchase.js.map +1 -0
- package/dist/config.d.ts +28 -0
- package/dist/config.js +22 -0
- package/dist/config.js.map +1 -0
- package/dist/conformance.d.ts +35 -0
- package/dist/conformance.js +240 -0
- package/dist/conformance.js.map +1 -0
- package/dist/doctor.d.ts +23 -0
- package/dist/doctor.js +123 -0
- package/dist/doctor.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +24 -0
- package/dist/io.js +2 -0
- package/dist/io.js.map +1 -0
- package/dist/output.d.ts +38 -0
- package/dist/output.js +131 -0
- package/dist/output.js.map +1 -0
- package/dist/profile.d.ts +38 -0
- package/dist/profile.js +43 -0
- package/dist/profile.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { formatAccountTools } from '../output.js';
|
|
2
|
+
/** Lists or calls buyer-account tools (require ARTOS_BUYER_BEARER). */
|
|
3
|
+
export async function account(deps, args) {
|
|
4
|
+
if (!deps.hasBuyer) {
|
|
5
|
+
deps.io.error('account: set ARTOS_BUYER_BEARER to a buyer OAuth bearer (account tools are buyer-bound).');
|
|
6
|
+
return 1;
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
if (args.action === 'list') {
|
|
10
|
+
const tools = await deps.account.listAccountTools();
|
|
11
|
+
deps.io.write(formatAccountTools(tools, { json: args.json }));
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
if (args.action === 'call') {
|
|
15
|
+
if (!args.tool) {
|
|
16
|
+
deps.io.error('account call: a tool name is required.');
|
|
17
|
+
return 1;
|
|
18
|
+
}
|
|
19
|
+
const res = await deps.account.callAccountTool(args.tool, args.toolArgs ?? {});
|
|
20
|
+
deps.io.write(JSON.stringify(res, null, 2));
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
deps.io.error(`Unknown account subcommand: ${args.action}`);
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
deps.io.error(`account: ${err.message}`);
|
|
28
|
+
return 1;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.js","sourceRoot":"","sources":["../../src/commands/account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAsBlD,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,IAAiB,EACjB,IAAiB;IAEjB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnB,IAAI,CAAC,EAAE,CAAC,KAAK,CACX,0FAA0F,CAC3F,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;YACpD,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC9D,OAAO,CAAC,CAAC;QACX,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACf,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;gBACxD,OAAO,CAAC,CAAC;YACX,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,eAAe,CAC5C,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,QAAQ,IAAI,EAAE,CACpB,CAAC;YACF,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC5C,OAAO,CAAC,CAAC;QACX,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,+BAA+B,IAAI,CAAC,MAAgB,EAAE,CAAC,CAAC;QACtE,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,YAAa,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CheckoutLineItem } from '@artos-commerce/ucp-client/checkout';
|
|
2
|
+
import type { StoreCaller } from '../agent.js';
|
|
3
|
+
import type { Io } from '../io.js';
|
|
4
|
+
export type CartAction = 'create' | 'view' | 'update';
|
|
5
|
+
export interface CartArgs {
|
|
6
|
+
action: CartAction;
|
|
7
|
+
store: string;
|
|
8
|
+
id?: string;
|
|
9
|
+
items?: CheckoutLineItem[];
|
|
10
|
+
json?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface CartDeps {
|
|
13
|
+
store: StoreCaller;
|
|
14
|
+
io: Pick<Io, 'write' | 'error'>;
|
|
15
|
+
}
|
|
16
|
+
/** Creates, views, or updates a store cart. */
|
|
17
|
+
export declare function cart(deps: CartDeps, args: CartArgs): Promise<number>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { isUcpError, messageOf } from '@artos-commerce/ucp-client/ucp';
|
|
2
|
+
import { lineItems } from '../args.js';
|
|
3
|
+
import { formatEntity } from '../output.js';
|
|
4
|
+
/** Creates, views, or updates a store cart. */
|
|
5
|
+
export async function cart(deps, args) {
|
|
6
|
+
if (!args.store.trim()) {
|
|
7
|
+
deps.io.error('cart: --store <slug> is required.');
|
|
8
|
+
return 1;
|
|
9
|
+
}
|
|
10
|
+
let res;
|
|
11
|
+
switch (args.action) {
|
|
12
|
+
case 'create': {
|
|
13
|
+
if (!args.items?.length) {
|
|
14
|
+
deps.io.error('cart create: at least one --item is required.');
|
|
15
|
+
return 1;
|
|
16
|
+
}
|
|
17
|
+
res = await deps.store.call(args.store, 'create_cart', { cart: { line_items: lineItems(args.items) } }, { idempotent: true });
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
case 'view': {
|
|
21
|
+
if (!args.id) {
|
|
22
|
+
deps.io.error('cart view: --id is required.');
|
|
23
|
+
return 1;
|
|
24
|
+
}
|
|
25
|
+
res = await deps.store.call(args.store, 'get_cart', { id: args.id });
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case 'update': {
|
|
29
|
+
if (!args.id) {
|
|
30
|
+
deps.io.error('cart update: --id is required.');
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
if (!args.items?.length) {
|
|
34
|
+
deps.io.error('cart update: at least one --item is required.');
|
|
35
|
+
return 1;
|
|
36
|
+
}
|
|
37
|
+
res = await deps.store.call(args.store, 'update_cart', { id: args.id, cart: { line_items: lineItems(args.items) } }, { idempotent: true });
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
default:
|
|
41
|
+
deps.io.error(`Unknown cart subcommand: ${args.action}`);
|
|
42
|
+
return 1;
|
|
43
|
+
}
|
|
44
|
+
if (isUcpError(res)) {
|
|
45
|
+
deps.io.error(messageOf(res) ?? 'The store returned an error.');
|
|
46
|
+
return 1;
|
|
47
|
+
}
|
|
48
|
+
deps.io.write(formatEntity('Cart', res, { json: args.json }));
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=cart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cart.js","sourceRoot":"","sources":["../../src/commands/cart.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { UcpResponse } from '@artos-commerce/ucp-client/ucp';
|
|
2
|
+
import type { Io } from '../io.js';
|
|
3
|
+
/** The transport surface this command needs (a subset of `UcpClient`). */
|
|
4
|
+
export interface CatalogSearcher {
|
|
5
|
+
globalSearch(catalog: {
|
|
6
|
+
query?: string;
|
|
7
|
+
filters?: Record<string, unknown>;
|
|
8
|
+
}): Promise<UcpResponse>;
|
|
9
|
+
}
|
|
10
|
+
export interface CatalogSearchArgs {
|
|
11
|
+
query: string;
|
|
12
|
+
/** Max price in MAJOR units (dollars); converted to minor units on the wire. */
|
|
13
|
+
max?: number;
|
|
14
|
+
currency?: string;
|
|
15
|
+
json?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface CatalogSearchDeps {
|
|
18
|
+
client: CatalogSearcher;
|
|
19
|
+
io: Pick<Io, 'write' | 'error'>;
|
|
20
|
+
}
|
|
21
|
+
/** Runs a cross-store catalog search and prints the results. */
|
|
22
|
+
export declare function catalogSearch(deps: CatalogSearchDeps, args: CatalogSearchArgs): Promise<number>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { normalizeSearchFilters } from '@artos-commerce/ucp-client/checkout';
|
|
2
|
+
import { formatSearchResults } from '../output.js';
|
|
3
|
+
/** Runs a cross-store catalog search and prints the results. */
|
|
4
|
+
export async function catalogSearch(deps, args) {
|
|
5
|
+
if (!args.query.trim()) {
|
|
6
|
+
deps.io.error('catalog search: a query is required.');
|
|
7
|
+
return 1;
|
|
8
|
+
}
|
|
9
|
+
const filters = args.max != null
|
|
10
|
+
? normalizeSearchFilters({
|
|
11
|
+
price: { max: args.max, currency: args.currency },
|
|
12
|
+
})
|
|
13
|
+
: undefined;
|
|
14
|
+
try {
|
|
15
|
+
const res = await deps.client.globalSearch({
|
|
16
|
+
query: args.query,
|
|
17
|
+
...(filters ? { filters } : {}),
|
|
18
|
+
});
|
|
19
|
+
deps.io.write(formatSearchResults(res, { json: args.json }));
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
deps.io.error(`Search failed: ${err.message}`);
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=catalog-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-search.js","sourceRoot":"","sources":["../../src/commands/catalog-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAE7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAwBnD,gEAAgE;AAChE,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAuB,EACvB,IAAuB;IAEvB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QACvB,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACtD,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,OAAO,GACX,IAAI,CAAC,GAAG,IAAI,IAAI;QACd,CAAC,CAAC,sBAAsB,CAAC;YACrB,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;SAClD,CAAC;QACJ,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;YACzC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChC,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7D,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,kBAAmB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CheckoutLineItem } from '@artos-commerce/ucp-client/checkout';
|
|
2
|
+
import type { StoreCaller } from '../agent.js';
|
|
3
|
+
import type { Io } from '../io.js';
|
|
4
|
+
export type CheckoutAction = 'create' | 'view' | 'update';
|
|
5
|
+
export interface CheckoutArgs {
|
|
6
|
+
action: CheckoutAction;
|
|
7
|
+
store: string;
|
|
8
|
+
id?: string;
|
|
9
|
+
cartId?: string;
|
|
10
|
+
items?: CheckoutLineItem[];
|
|
11
|
+
/** Nested patch from `--set` (e.g. `{ shipping_address: { country: 'US' } }`). */
|
|
12
|
+
set?: Record<string, unknown>;
|
|
13
|
+
json?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface CheckoutDeps {
|
|
16
|
+
store: StoreCaller;
|
|
17
|
+
io: Pick<Io, 'write' | 'error'>;
|
|
18
|
+
}
|
|
19
|
+
/** Creates, views, or updates a store checkout. */
|
|
20
|
+
export declare function checkout(deps: CheckoutDeps, args: CheckoutArgs): Promise<number>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { isUcpError, messageOf } from '@artos-commerce/ucp-client/ucp';
|
|
2
|
+
import { lineItems } from '../args.js';
|
|
3
|
+
import { formatEntity } from '../output.js';
|
|
4
|
+
/** Creates, views, or updates a store checkout. */
|
|
5
|
+
export async function checkout(deps, args) {
|
|
6
|
+
if (!args.store.trim()) {
|
|
7
|
+
deps.io.error('checkout: --store <slug> is required.');
|
|
8
|
+
return 1;
|
|
9
|
+
}
|
|
10
|
+
let res;
|
|
11
|
+
switch (args.action) {
|
|
12
|
+
case 'create': {
|
|
13
|
+
const body = { ...(args.set ?? {}) };
|
|
14
|
+
if (args.cartId)
|
|
15
|
+
body.cart_id = args.cartId;
|
|
16
|
+
if (args.items?.length)
|
|
17
|
+
body.line_items = lineItems(args.items);
|
|
18
|
+
res = await deps.store.call(args.store, 'create_checkout', { checkout: body }, { idempotent: true });
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
case 'view': {
|
|
22
|
+
if (!args.id) {
|
|
23
|
+
deps.io.error('checkout view: --id is required.');
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
res = await deps.store.call(args.store, 'get_checkout', { id: args.id });
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
case 'update': {
|
|
30
|
+
if (!args.id) {
|
|
31
|
+
deps.io.error('checkout update: --id is required.');
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
if (!args.set || Object.keys(args.set).length === 0) {
|
|
35
|
+
deps.io.error('checkout update: at least one --set key=value is required.');
|
|
36
|
+
return 1;
|
|
37
|
+
}
|
|
38
|
+
res = await deps.store.call(args.store, 'update_checkout', { id: args.id, checkout: args.set }, { idempotent: true });
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
default:
|
|
42
|
+
deps.io.error(`Unknown checkout subcommand: ${args.action}`);
|
|
43
|
+
return 1;
|
|
44
|
+
}
|
|
45
|
+
if (isUcpError(res)) {
|
|
46
|
+
deps.io.error(messageOf(res) ?? 'The store returned an error.');
|
|
47
|
+
return 1;
|
|
48
|
+
}
|
|
49
|
+
deps.io.write(formatEntity('Checkout', res, { json: args.json }));
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=checkout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkout.js","sourceRoot":"","sources":["../../src/commands/checkout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Io } from '../io.js';
|
|
2
|
+
export interface DiscoverArgs {
|
|
3
|
+
store: string;
|
|
4
|
+
json?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface DiscoverDeps {
|
|
7
|
+
/** Fetches and parses a JSON document, throwing on a non-2xx response. */
|
|
8
|
+
fetchJson: (url: string) => Promise<Record<string, unknown>>;
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
io: Pick<Io, 'write' | 'error'>;
|
|
11
|
+
}
|
|
12
|
+
/** Fetches a store's UCP profile and prints its keys, handlers, and capabilities. */
|
|
13
|
+
export declare function discover(deps: DiscoverDeps, args: DiscoverArgs): Promise<number>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { formatStoreProfile } from '../output.js';
|
|
2
|
+
/** Fetches a store's UCP profile and prints its keys, handlers, and capabilities. */
|
|
3
|
+
export async function discover(deps, args) {
|
|
4
|
+
if (!args.store.trim()) {
|
|
5
|
+
deps.io.error('discover: --store <slug> is required.');
|
|
6
|
+
return 1;
|
|
7
|
+
}
|
|
8
|
+
const url = `${deps.baseUrl}/s/${args.store}/.well-known/ucp`;
|
|
9
|
+
try {
|
|
10
|
+
const raw = await deps.fetchJson(url);
|
|
11
|
+
// The endpoint returns HTTP 200 with a UCP error envelope for an unknown
|
|
12
|
+
// store, so surface that as a failure instead of printing an empty profile.
|
|
13
|
+
const ucp = raw.ucp;
|
|
14
|
+
if (ucp?.status === 'error') {
|
|
15
|
+
const messages = raw.messages;
|
|
16
|
+
deps.io.error(`discover: ${messages?.[0]?.content ?? `store "${args.store}" not found`}`);
|
|
17
|
+
return 1;
|
|
18
|
+
}
|
|
19
|
+
deps.io.write(formatStoreProfile(args.store, raw, { json: args.json }));
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
deps.io.error(`Failed to fetch ${url}: ${err.message}`);
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=discover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/commands/discover.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAelD,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,IAAkB,EAClB,IAAkB;IAElB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QACvB,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACvD,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,MAAM,IAAI,CAAC,KAAK,kBAAkB,CAAC;IAC9D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACtC,yEAAyE;QACzE,4EAA4E;QAC5E,MAAM,GAAG,GAAG,GAAG,CAAC,GAAsC,CAAC;QACvD,IAAI,GAAG,EAAE,MAAM,KAAK,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAmD,CAAC;YACzE,IAAI,CAAC,EAAE,CAAC,KAAK,CACX,aAAa,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,UAAU,IAAI,CAAC,KAAK,aAAa,EAAE,CAC3E,CAAC;YACF,OAAO,CAAC,CAAC;QACX,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACxE,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,GAAG,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACnE,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Io } from '../io.js';
|
|
2
|
+
/** The starter project's files, keyed by path relative to the target directory. */
|
|
3
|
+
export declare function starterFiles(opts: {
|
|
4
|
+
name: string;
|
|
5
|
+
}): Record<string, string>;
|
|
6
|
+
export interface InitDeps {
|
|
7
|
+
io: Pick<Io, 'write' | 'error' | 'mkdir' | 'writeFile' | 'exists'>;
|
|
8
|
+
}
|
|
9
|
+
export interface InitArgs {
|
|
10
|
+
/** Project name (used in package.json + README). */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Absolute target directory to scaffold into. */
|
|
13
|
+
outDir: string;
|
|
14
|
+
}
|
|
15
|
+
/** Scaffolds a Build-track agent starter project into `outDir`. */
|
|
16
|
+
export declare function initProject(deps: InitDeps, args: InitArgs): number;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
/** Pinned dependency versions for the generated starter. */
|
|
3
|
+
const UCP_CLIENT_VERSION = '^0.2.0';
|
|
4
|
+
const STARTER_INDEX = `import 'dotenv/config';
|
|
5
|
+
import {
|
|
6
|
+
UcpClient,
|
|
7
|
+
Ap2Signer,
|
|
8
|
+
createCheckoutHandlers,
|
|
9
|
+
createAccountHandlers,
|
|
10
|
+
OAuthClient,
|
|
11
|
+
createPkce,
|
|
12
|
+
isUcpError,
|
|
13
|
+
} from '@artos-commerce/ucp-client';
|
|
14
|
+
|
|
15
|
+
function required(name: string): string {
|
|
16
|
+
const value = process.env[name];
|
|
17
|
+
if (!value) throw new Error('Missing required env var: ' + name);
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const config = {
|
|
22
|
+
artosBaseUrl: process.env.ARTOS_BASE_URL ?? 'https://api.artos.sh',
|
|
23
|
+
platformApiKey: required('UCP_PLATFORM_API_KEY'),
|
|
24
|
+
platformProfileUrl: required('PLATFORM_PROFILE_URL'),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// The buyer bearer is optional; account tools + the crypto rail need it.
|
|
28
|
+
const buyerToken = process.env.ARTOS_BUYER_BEARER || undefined;
|
|
29
|
+
const client = new UcpClient(config, { buyerToken });
|
|
30
|
+
|
|
31
|
+
// AP2 signer (needed to PLACE orders). Generate a key with:
|
|
32
|
+
// npx @artos-commerce/ucp-cli profile init
|
|
33
|
+
const signer = process.env.AGENT_PRIVATE_JWK
|
|
34
|
+
? new Ap2Signer(
|
|
35
|
+
JSON.parse(process.env.AGENT_PRIVATE_JWK),
|
|
36
|
+
process.env.AGENT_KID ?? '',
|
|
37
|
+
)
|
|
38
|
+
: undefined;
|
|
39
|
+
|
|
40
|
+
async function main() {
|
|
41
|
+
// 1) Search the cross-store catalog (works anonymously).
|
|
42
|
+
const results = await client.globalSearch({
|
|
43
|
+
query: 'shoes',
|
|
44
|
+
filters: { price: { max: 150, currency: 'USD' } },
|
|
45
|
+
});
|
|
46
|
+
const products =
|
|
47
|
+
(results.products as Array<{ title?: string }> | undefined) ?? [];
|
|
48
|
+
console.log('Found ' + products.length + ' product(s):');
|
|
49
|
+
for (const p of products.slice(0, 5)) {
|
|
50
|
+
console.log(' • ' + (p.title ?? '(untitled)'));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 2) Build + confirm a checkout (needs a real platform key + the agent signer).
|
|
54
|
+
if (signer) {
|
|
55
|
+
const shop = createCheckoutHandlers({ client, signer });
|
|
56
|
+
// const checkout = await shop.createCheckout({ storeSlug, items: [{ id, quantity: 1 }] });
|
|
57
|
+
// const outcome = await shop.confirmPurchase({
|
|
58
|
+
// storeSlug,
|
|
59
|
+
// checkoutId: checkout.id,
|
|
60
|
+
// paymentMethod: 'sh.artos.card',
|
|
61
|
+
// });
|
|
62
|
+
void shop;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 3) Buyer-account tools (needs ARTOS_BUYER_BEARER — see signIn() below).
|
|
66
|
+
if (buyerToken) {
|
|
67
|
+
const account = createAccountHandlers({ client });
|
|
68
|
+
const me = await account.getBuyerContext();
|
|
69
|
+
console.log('Buyer context: ' + (isUcpError(me) ? 'error' : 'ok'));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 4) Buyer sign-in (PKCE). Run this once to obtain a buyer bearer, then set it as
|
|
74
|
+
// ARTOS_BUYER_BEARER for the account + crypto steps above.
|
|
75
|
+
export async function signIn() {
|
|
76
|
+
const oauth = new OAuthClient({ artosBaseUrl: config.artosBaseUrl });
|
|
77
|
+
const pkce = createPkce();
|
|
78
|
+
const { url, state } = await oauth.authorizeUrl({
|
|
79
|
+
clientId:
|
|
80
|
+
process.env.OAUTH_CLIENT_ID ??
|
|
81
|
+
'https://your-app.example/well-known/oauth-client.json',
|
|
82
|
+
redirectUri:
|
|
83
|
+
process.env.OAUTH_REDIRECT_URI ?? 'http://localhost:8898/callback',
|
|
84
|
+
codeChallenge: pkce.challenge,
|
|
85
|
+
});
|
|
86
|
+
console.log('Open this URL to sign in (state=' + state + '):');
|
|
87
|
+
console.log(url);
|
|
88
|
+
// On the redirect (verify state!), exchange the code:
|
|
89
|
+
// const tokens = await oauth.exchangeCode({
|
|
90
|
+
// code, codeVerifier: pkce.verifier, clientId, redirectUri,
|
|
91
|
+
// });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
main().catch((err) => {
|
|
95
|
+
console.error(err);
|
|
96
|
+
process.exitCode = 1;
|
|
97
|
+
});
|
|
98
|
+
`;
|
|
99
|
+
const STARTER_ENV = `# Artos API base URL
|
|
100
|
+
ARTOS_BASE_URL=https://api.artos.sh
|
|
101
|
+
|
|
102
|
+
# Platform (cross-store) UCP API key: "<clientId>.<secret>"
|
|
103
|
+
UCP_PLATFORM_API_KEY=
|
|
104
|
+
|
|
105
|
+
# HTTPS URL of your published agent UCP profile (signing_keys + capabilities)
|
|
106
|
+
PLATFORM_PROFILE_URL=https://your-app.example/.well-known/ucp
|
|
107
|
+
|
|
108
|
+
# Agent AP2 signing key (generate with: npx @artos-commerce/ucp-cli profile init)
|
|
109
|
+
AGENT_PRIVATE_JWK=
|
|
110
|
+
AGENT_KID=
|
|
111
|
+
|
|
112
|
+
# Optional: a buyer OAuth bearer (account tools + crypto rail). Obtain via signIn().
|
|
113
|
+
ARTOS_BUYER_BEARER=
|
|
114
|
+
|
|
115
|
+
# Optional: OAuth client for buyer sign-in (PKCE)
|
|
116
|
+
OAUTH_CLIENT_ID=
|
|
117
|
+
OAUTH_REDIRECT_URI=http://localhost:8898/callback
|
|
118
|
+
`;
|
|
119
|
+
const STARTER_TSCONFIG = `{
|
|
120
|
+
"compilerOptions": {
|
|
121
|
+
"target": "ES2022",
|
|
122
|
+
"module": "NodeNext",
|
|
123
|
+
"moduleResolution": "NodeNext",
|
|
124
|
+
"strict": true,
|
|
125
|
+
"esModuleInterop": true,
|
|
126
|
+
"skipLibCheck": true,
|
|
127
|
+
"types": ["node"],
|
|
128
|
+
"noEmit": true
|
|
129
|
+
},
|
|
130
|
+
"include": ["src"]
|
|
131
|
+
}
|
|
132
|
+
`;
|
|
133
|
+
const STARTER_GITIGNORE = `node_modules
|
|
134
|
+
.env
|
|
135
|
+
dist
|
|
136
|
+
*.log
|
|
137
|
+
`;
|
|
138
|
+
function starterPackageJson(name) {
|
|
139
|
+
return (JSON.stringify({
|
|
140
|
+
name,
|
|
141
|
+
version: '0.1.0',
|
|
142
|
+
private: true,
|
|
143
|
+
type: 'module',
|
|
144
|
+
scripts: { start: 'tsx src/index.ts' },
|
|
145
|
+
dependencies: {
|
|
146
|
+
'@artos-commerce/ucp-client': UCP_CLIENT_VERSION,
|
|
147
|
+
dotenv: '^16.4.5',
|
|
148
|
+
},
|
|
149
|
+
devDependencies: {
|
|
150
|
+
'@types/node': '^20.19.42',
|
|
151
|
+
tsx: '^4.19.2',
|
|
152
|
+
typescript: '^5.6.0',
|
|
153
|
+
},
|
|
154
|
+
engines: { node: '>=20' },
|
|
155
|
+
}, null, 2) + '\n');
|
|
156
|
+
}
|
|
157
|
+
function starterReadme(name) {
|
|
158
|
+
return `# ${name}
|
|
159
|
+
|
|
160
|
+
A Build-track Artos agent starter, wired with
|
|
161
|
+
[\`@artos-commerce/ucp-client\`](https://www.npmjs.com/package/@artos-commerce/ucp-client):
|
|
162
|
+
cross-store catalog search, checkout + \`confirmPurchase\`, buyer-account tools,
|
|
163
|
+
and buyer OAuth (PKCE).
|
|
164
|
+
|
|
165
|
+
## Setup
|
|
166
|
+
|
|
167
|
+
\`\`\`bash
|
|
168
|
+
npm install
|
|
169
|
+
cp .env.example .env # then fill it in
|
|
170
|
+
npm start
|
|
171
|
+
\`\`\`
|
|
172
|
+
|
|
173
|
+
Generate an agent signing key + profile with:
|
|
174
|
+
|
|
175
|
+
\`\`\`bash
|
|
176
|
+
npx @artos-commerce/ucp-cli profile init
|
|
177
|
+
\`\`\`
|
|
178
|
+
|
|
179
|
+
Publish the printed \`ucp.json\` at your \`PLATFORM_PROFILE_URL\`, and load the
|
|
180
|
+
private key as \`AGENT_PRIVATE_JWK\` (never commit it).
|
|
181
|
+
|
|
182
|
+
## What's inside
|
|
183
|
+
|
|
184
|
+
- \`src/index.ts\` — searches the catalog, then shows how to checkout, call
|
|
185
|
+
account tools, and sign a buyer in (PKCE). Edit it for your use case.
|
|
186
|
+
`;
|
|
187
|
+
}
|
|
188
|
+
/** The starter project's files, keyed by path relative to the target directory. */
|
|
189
|
+
export function starterFiles(opts) {
|
|
190
|
+
return {
|
|
191
|
+
'package.json': starterPackageJson(opts.name),
|
|
192
|
+
'tsconfig.json': STARTER_TSCONFIG,
|
|
193
|
+
'.env.example': STARTER_ENV,
|
|
194
|
+
'.gitignore': STARTER_GITIGNORE,
|
|
195
|
+
'README.md': starterReadme(opts.name),
|
|
196
|
+
'src/index.ts': STARTER_INDEX,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/** Scaffolds a Build-track agent starter project into `outDir`. */
|
|
200
|
+
export function initProject(deps, args) {
|
|
201
|
+
if (deps.io.exists(join(args.outDir, 'package.json'))) {
|
|
202
|
+
deps.io.error(`init: ${args.outDir} already contains a package.json — choose an empty directory (--out <dir>).`);
|
|
203
|
+
return 1;
|
|
204
|
+
}
|
|
205
|
+
const files = starterFiles({ name: args.name });
|
|
206
|
+
deps.io.mkdir(args.outDir);
|
|
207
|
+
deps.io.mkdir(join(args.outDir, 'src'));
|
|
208
|
+
for (const [rel, contents] of Object.entries(files)) {
|
|
209
|
+
deps.io.writeFile(join(args.outDir, rel), contents);
|
|
210
|
+
}
|
|
211
|
+
deps.io.write([
|
|
212
|
+
`Scaffolded ${args.name} into ${args.outDir}`,
|
|
213
|
+
'',
|
|
214
|
+
'Next steps:',
|
|
215
|
+
` cd ${args.outDir}`,
|
|
216
|
+
' npm install',
|
|
217
|
+
' cp .env.example .env # then fill it in',
|
|
218
|
+
' npm start',
|
|
219
|
+
].join('\n'));
|
|
220
|
+
return 0;
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,4DAA4D;AAC5D,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AAEpC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8FrB,CAAC;AAEF,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;CAmBnB,CAAC;AAEF,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;CAaxB,CAAC;AAEF,MAAM,iBAAiB,GAAG;;;;CAIzB,CAAC;AAEF,SAAS,kBAAkB,CAAC,IAAY;IACtC,OAAO,CACL,IAAI,CAAC,SAAS,CACZ;QACE,IAAI;QACJ,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE;QACtC,YAAY,EAAE;YACZ,4BAA4B,EAAE,kBAAkB;YAChD,MAAM,EAAE,SAAS;SAClB;QACD,eAAe,EAAE;YACf,aAAa,EAAE,WAAW;YAC1B,GAAG,EAAE,SAAS;YACd,UAAU,EAAE,QAAQ;SACrB;QACD,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;KAC1B,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CACT,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BjB,CAAC;AACF,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAAC,IAAsB;IACjD,OAAO;QACL,cAAc,EAAE,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;QAC7C,eAAe,EAAE,gBAAgB;QACjC,cAAc,EAAE,WAAW;QAC3B,YAAY,EAAE,iBAAiB;QAC/B,WAAW,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;QACrC,cAAc,EAAE,aAAa;KAC9B,CAAC;AACJ,CAAC;AAaD,mEAAmE;AACnE,MAAM,UAAU,WAAW,CAAC,IAAc,EAAE,IAAc;IACxD,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;QACtD,IAAI,CAAC,EAAE,CAAC,KAAK,CACX,SAAS,IAAI,CAAC,MAAM,6EAA6E,CAClG,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAChD,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3B,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,CAAC,EAAE,CAAC,KAAK,CACX;QACE,cAAc,IAAI,CAAC,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE;QAC7C,EAAE;QACF,aAAa;QACb,QAAQ,IAAI,CAAC,MAAM,EAAE;QACrB,eAAe;QACf,4CAA4C;QAC5C,aAAa;KACd,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GeneratedProfile } from '../profile.js';
|
|
2
|
+
import type { Io } from '../io.js';
|
|
3
|
+
export interface ProfileInitArgs {
|
|
4
|
+
outDir: string;
|
|
5
|
+
/** The public URL the profile will be hosted at. */
|
|
6
|
+
url: string;
|
|
7
|
+
kid?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ProfileInitDeps {
|
|
10
|
+
generate: (opts: {
|
|
11
|
+
url: string;
|
|
12
|
+
kid?: string;
|
|
13
|
+
}) => Promise<GeneratedProfile>;
|
|
14
|
+
mkdir: (path: string) => void;
|
|
15
|
+
writeFile: (path: string, contents: string) => void;
|
|
16
|
+
io: Pick<Io, 'write' | 'error'>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generates an agent UCP profile + keypair and writes the public profile and the
|
|
20
|
+
* private signing key to `outDir`. Prints the env vars needed to use them.
|
|
21
|
+
*/
|
|
22
|
+
export declare function profileInit(deps: ProfileInitDeps, args: ProfileInitArgs): Promise<number>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
/**
|
|
3
|
+
* Generates an agent UCP profile + keypair and writes the public profile and the
|
|
4
|
+
* private signing key to `outDir`. Prints the env vars needed to use them.
|
|
5
|
+
*/
|
|
6
|
+
export async function profileInit(deps, args) {
|
|
7
|
+
try {
|
|
8
|
+
const generated = await deps.generate({ url: args.url, kid: args.kid });
|
|
9
|
+
deps.mkdir(args.outDir);
|
|
10
|
+
const profilePath = join(args.outDir, 'ucp.json');
|
|
11
|
+
const keyPath = join(args.outDir, 'private-jwk.json');
|
|
12
|
+
deps.writeFile(profilePath, `${JSON.stringify(generated.profile, null, 2)}\n`);
|
|
13
|
+
deps.writeFile(keyPath, `${JSON.stringify(generated.privateJwk, null, 2)}\n`);
|
|
14
|
+
deps.io.write([
|
|
15
|
+
`Generated agent profile (kid ${generated.kid}).`,
|
|
16
|
+
'',
|
|
17
|
+
` ${profilePath}`,
|
|
18
|
+
` → host this publicly at ${args.url}`,
|
|
19
|
+
` ${keyPath}`,
|
|
20
|
+
' → SECRET: load as AGENT_PRIVATE_JWK; never commit it',
|
|
21
|
+
'',
|
|
22
|
+
'Next:',
|
|
23
|
+
` export PLATFORM_PROFILE_URL=${args.url}`,
|
|
24
|
+
` export AGENT_KID=${generated.kid}`,
|
|
25
|
+
` export AGENT_PRIVATE_JWK="$(cat ${keyPath})"`,
|
|
26
|
+
].join('\n'));
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
deps.io.error(`profile init failed: ${err.message}`);
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=profile-init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-init.js","sourceRoot":"","sources":["../../src/commands/profile-init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAkBjC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAqB,EACrB,IAAqB;IAErB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAExB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;QACtD,IAAI,CAAC,SAAS,CACZ,WAAW,EACX,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAClD,CAAC;QACF,IAAI,CAAC,SAAS,CACZ,OAAO,EACP,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CACrD,CAAC;QAEF,IAAI,CAAC,EAAE,CAAC,KAAK,CACX;YACE,gCAAgC,SAAS,CAAC,GAAG,IAAI;YACjD,EAAE;YACF,KAAK,WAAW,EAAE;YAClB,+BAA+B,IAAI,CAAC,GAAG,EAAE;YACzC,KAAK,OAAO,EAAE;YACd,0DAA0D;YAC1D,EAAE;YACF,OAAO;YACP,iCAAiC,IAAI,CAAC,GAAG,EAAE;YAC3C,sBAAsB,SAAS,CAAC,GAAG,EAAE;YACrC,qCAAqC,OAAO,IAAI;SACjD,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,wBAAyB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAChE,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ConfirmFn } from '../agent.js';
|
|
2
|
+
import type { Io } from '../io.js';
|
|
3
|
+
export interface PurchaseArgs {
|
|
4
|
+
store: string;
|
|
5
|
+
id: string;
|
|
6
|
+
/** Chosen rail handler id (e.g. `sh.artos.card`). Omit to be asked. */
|
|
7
|
+
pay?: string;
|
|
8
|
+
/** Server-side allowance (PaymentMandate) UUID. */
|
|
9
|
+
mandate?: string;
|
|
10
|
+
/** `true` apply best coupon, `false` strip it, `undefined` leave untouched. */
|
|
11
|
+
applyCoupon?: boolean;
|
|
12
|
+
json?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface PurchaseDeps {
|
|
15
|
+
confirm: ConfirmFn;
|
|
16
|
+
io: Pick<Io, 'write' | 'error'>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Exit codes: 0 = order placed; 2 = action required (escalation / pick a rail);
|
|
20
|
+
* 1 = error.
|
|
21
|
+
*/
|
|
22
|
+
export declare function purchaseConfirm(deps: PurchaseDeps, args: PurchaseArgs): Promise<number>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { formatOutcome } from '../output.js';
|
|
2
|
+
/**
|
|
3
|
+
* Exit codes: 0 = order placed; 2 = action required (escalation / pick a rail);
|
|
4
|
+
* 1 = error.
|
|
5
|
+
*/
|
|
6
|
+
export async function purchaseConfirm(deps, args) {
|
|
7
|
+
if (!args.store.trim() || !args.id.trim()) {
|
|
8
|
+
deps.io.error('purchase confirm: --store <slug> and --id <checkoutId> are required.');
|
|
9
|
+
return 1;
|
|
10
|
+
}
|
|
11
|
+
const outcome = await deps.confirm({
|
|
12
|
+
storeSlug: args.store,
|
|
13
|
+
checkoutId: args.id,
|
|
14
|
+
paymentMethod: args.pay,
|
|
15
|
+
paymentMandateId: args.mandate,
|
|
16
|
+
applyCoupon: args.applyCoupon,
|
|
17
|
+
});
|
|
18
|
+
deps.io.write(formatOutcome(outcome, { json: args.json }));
|
|
19
|
+
switch (outcome.status) {
|
|
20
|
+
case 'completed':
|
|
21
|
+
return 0;
|
|
22
|
+
case 'escalation_required':
|
|
23
|
+
case 'payment_selection_required':
|
|
24
|
+
return 2;
|
|
25
|
+
case 'error':
|
|
26
|
+
return 1;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=purchase.js.map
|