@godaddy/gd-commerce-server 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +28 -4
- package/package.json +9 -10
package/README.md
CHANGED
|
@@ -57,3 +57,24 @@ Configure `checkoutReturnUrls` on the router using trusted deployment settings.
|
|
|
57
57
|
Without this policy, HTTP checkout returns 503 before creating a session. Invalid request destinations return 400. This applies to both router presets that expose checkout. Trusted in-process callers of `createCheckoutSession()` own their return URLs and must construct or validate them server-side.
|
|
58
58
|
|
|
59
59
|
A return from hosted checkout is not proof of payment. The order-status route uses the authorized Orders REST API, which supports completed orders, and returns its payment status (for example `PAID` or `PENDING`; `unknown` if absent). The server OAuth client must be granted `commerce.order:read`. The helper verifies the returned order ID, store, and channel and returns a limited summary without customer contact data. Hosts must authenticate callers and authorize access to each requested order before exposing this route.
|
|
60
|
+
|
|
61
|
+
### Connection state
|
|
62
|
+
|
|
63
|
+
Hosts can implement the optional synchronous `CommerceConfiguration.readConnectionState()`
|
|
64
|
+
method. Its return type is exported as `CommerceConnectionState` (`unbound | connecting | ready`).
|
|
65
|
+
Returning `undefined` keeps the existing behavior. Throw when the state is unknown or cannot be
|
|
66
|
+
read. The default environment configuration does not implement this method, so missing
|
|
67
|
+
credentials never count as `unbound`.
|
|
68
|
+
|
|
69
|
+
`GET /config` returns `{ state: 'unbound' }` or `{ state: 'connecting' }` without reading store
|
|
70
|
+
credentials. `ready` includes the usual opaque `cartScope` and `currencyCode` after `read()`
|
|
71
|
+
succeeds. Without this method, the successful response shape is unchanged. All responses are
|
|
72
|
+
uncached; a malformed state or unavailable configuration returns 503. Data and checkout routes,
|
|
73
|
+
and the in-process checkout and order helpers, reject any state other than `ready` before
|
|
74
|
+
upstream calls.
|
|
75
|
+
|
|
76
|
+
The host owns the connection lifecycle. Report `ready` only after the store connection is
|
|
77
|
+
complete. Lost configuration is an error, never evidence of `unbound`. After a store connects,
|
|
78
|
+
report `unbound` again only after it is deliberately disconnected. The storefront package owns
|
|
79
|
+
the generic sample products and local sample cart; this server never creates sample Commerce
|
|
80
|
+
records or simulates checkout.
|
package/dist/index.d.ts
CHANGED
|
@@ -39,7 +39,10 @@ interface CommerceConfig {
|
|
|
39
39
|
/** Optional host-owned attribution shared by draft orders and checkout. */
|
|
40
40
|
owner?: string;
|
|
41
41
|
}
|
|
42
|
+
type CommerceConnectionState = 'unbound' | 'connecting' | 'ready';
|
|
42
43
|
interface CommerceConfiguration {
|
|
44
|
+
/** Authoritative host state. Missing support preserves legacy live/error behavior. */
|
|
45
|
+
readConnectionState?(): CommerceConnectionState | undefined;
|
|
43
46
|
read(): CommerceConfig;
|
|
44
47
|
readCheckout(): CommerceCheckoutConfiguration;
|
|
45
48
|
}
|
|
@@ -143,4 +146,4 @@ declare function createCommerceRouter(options?: CreateCommerceRouterOptions): Ro
|
|
|
143
146
|
declare function createCommerceCatalogRouter(configuration?: CommerceConfiguration): Router;
|
|
144
147
|
declare function createGoDaddyPaymentsRouter(configuration?: CommerceConfiguration, checkoutReturnUrls?: CheckoutReturnUrls): Router;
|
|
145
148
|
//#endregion
|
|
146
|
-
export { type CheckoutReturnUrls, type CheckoutSession, type CommerceCheckoutConfiguration, type CommerceCheckoutShippingConfiguration, type CommerceConfig, type CommerceConfiguration, type CommerceOrderStatus, type CommerceRouterFeatures, type CreateCheckoutSessionParams, type CreateCommerceRouterOptions, type RuntimeCommerceConfigurationOptions, createCheckoutSession, createCommerceCatalogRouter, createCommerceRouter, createGoDaddyPaymentsRouter, createRuntimeCommerceConfiguration, getOrderStatus, parseCommerceCheckoutConfiguration, readCommerceConfig };
|
|
149
|
+
export { type CheckoutReturnUrls, type CheckoutSession, type CommerceCheckoutConfiguration, type CommerceCheckoutShippingConfiguration, type CommerceConfig, type CommerceConfiguration, type CommerceConnectionState, type CommerceOrderStatus, type CommerceRouterFeatures, type CreateCheckoutSessionParams, type CreateCommerceRouterOptions, type RuntimeCommerceConfigurationOptions, createCheckoutSession, createCommerceCatalogRouter, createCommerceRouter, createGoDaddyPaymentsRouter, createRuntimeCommerceConfiguration, getOrderStatus, parseCommerceCheckoutConfiguration, readCommerceConfig };
|
package/dist/index.js
CHANGED
|
@@ -79,7 +79,14 @@ function commerceConfigurationForResponse(res) {
|
|
|
79
79
|
return createRuntimeCommerceConfiguration();
|
|
80
80
|
}
|
|
81
81
|
function readCommerceConfigForResponse(res) {
|
|
82
|
-
|
|
82
|
+
const configuration = commerceConfigurationForResponse(res);
|
|
83
|
+
assertCommerceConnectionReady(configuration);
|
|
84
|
+
return configuration.read();
|
|
85
|
+
}
|
|
86
|
+
/** Nonready and invalid connection states must never use leftover credentials. */
|
|
87
|
+
function assertCommerceConnectionReady(configuration) {
|
|
88
|
+
const state = configuration.readConnectionState?.();
|
|
89
|
+
if (state !== void 0 && state !== "ready") throw new Error("Commerce store connection is not ready. Complete the store connection before continuing.");
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
//#endregion
|
|
@@ -330,6 +337,7 @@ async function createCheckoutSession(params, configuration = createRuntimeCommer
|
|
|
330
337
|
skuId,
|
|
331
338
|
lineItemData
|
|
332
339
|
].filter(Boolean).length !== 1) throw new Error("createCheckoutSession: exactly one of draftOrderId, skuId, or lineItemData is required");
|
|
340
|
+
assertCommerceConnectionReady(configuration);
|
|
333
341
|
const { storeId, channelId, clientId, clientSecret, apiBaseUrl, sourceApp, owner, currencyCode: configCurrencyCode } = configuration.read();
|
|
334
342
|
const checkoutConfiguration = configuration.readCheckout();
|
|
335
343
|
const enablePromotionCodes = promotionCodesEnabled(checkoutConfiguration);
|
|
@@ -420,6 +428,7 @@ async function createCheckoutSession(params, configuration = createRuntimeCommer
|
|
|
420
428
|
//#region src/lib/commerce/get-order-status.ts
|
|
421
429
|
async function getOrderStatus(orderId, configuration = createRuntimeCommerceConfiguration()) {
|
|
422
430
|
if (typeof orderId !== "string" || !orderId.trim() || orderId === "." || orderId === "..") throw new Error("getOrderStatus: a valid orderId is required");
|
|
431
|
+
assertCommerceConnectionReady(configuration);
|
|
423
432
|
const { storeId, channelId, clientId, clientSecret, apiBaseUrl, currencyCode } = configuration.read();
|
|
424
433
|
const token = await getOAuthAccessToken({
|
|
425
434
|
clientId,
|
|
@@ -1065,6 +1074,7 @@ async function handler$6(req, res) {
|
|
|
1065
1074
|
return;
|
|
1066
1075
|
}
|
|
1067
1076
|
if (req.headers?.["x-commerce-scope"] !== void 0) {
|
|
1077
|
+
assertCommerceConnectionReady(configuration);
|
|
1068
1078
|
if (!validateCommerceCartScope(req, res, configuration.read())) return;
|
|
1069
1079
|
}
|
|
1070
1080
|
const validateReturnUrls = res.locals.commerceCheckoutReturnUrlValidator;
|
|
@@ -1097,8 +1107,16 @@ async function handler$6(req, res) {
|
|
|
1097
1107
|
async function handler$7(_req, res) {
|
|
1098
1108
|
res.setHeader("Cache-Control", "no-store");
|
|
1099
1109
|
try {
|
|
1100
|
-
const
|
|
1110
|
+
const configuration = commerceConfigurationForResponse(res);
|
|
1111
|
+
const state = configuration.readConnectionState?.();
|
|
1112
|
+
if (state === "unbound" || state === "connecting") {
|
|
1113
|
+
res.json({ state });
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
if (state !== void 0 && state !== "ready") throw new Error("Invalid Commerce connection state.");
|
|
1117
|
+
const config = configuration.read();
|
|
1101
1118
|
res.json({
|
|
1119
|
+
...state === "ready" ? { state } : {},
|
|
1102
1120
|
cartScope: getCommerceCartScope(config),
|
|
1103
1121
|
currencyCode: config.currencyCode
|
|
1104
1122
|
});
|
|
@@ -1166,9 +1184,11 @@ function buildSkuGroupVariables({ productId, selectedAttributeValues, skuGroupFi
|
|
|
1166
1184
|
//#region src/server/api/commerce/products/[id]/GET.ts
|
|
1167
1185
|
const skuGroupQuery = `
|
|
1168
1186
|
query SkuGroup($id: String!, $first: Int, $attributeValues: [String!] = []) {
|
|
1187
|
+
activeSkuGroups: skuGroups(id: { in: [$id] }, status: { eq: "ACTIVE" }, first: 1) {
|
|
1188
|
+
edges { node { id } }
|
|
1189
|
+
}
|
|
1169
1190
|
skuGroup(id: $id) {
|
|
1170
1191
|
id
|
|
1171
|
-
status
|
|
1172
1192
|
name
|
|
1173
1193
|
label
|
|
1174
1194
|
description
|
|
@@ -1282,7 +1302,11 @@ async function handler$9(req, res) {
|
|
|
1282
1302
|
clientId
|
|
1283
1303
|
})
|
|
1284
1304
|
});
|
|
1285
|
-
|
|
1305
|
+
if (!data.skuGroup || !data.activeSkuGroups?.edges?.some((edge) => edge?.node?.id === productId)) {
|
|
1306
|
+
res.status(404).json({ error: "Product not found" });
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
res.json({ skuGroup: data.skuGroup });
|
|
1286
1310
|
} catch (error) {
|
|
1287
1311
|
res.status(500).json({
|
|
1288
1312
|
error: "Failed to load product",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godaddy/gd-commerce-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Opinionated Express server integration for GoDaddy Commerce",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,14 +19,6 @@
|
|
|
19
19
|
},
|
|
20
20
|
"./package.json": "./package.json"
|
|
21
21
|
},
|
|
22
|
-
"scripts": {
|
|
23
|
-
"build": "tsdown",
|
|
24
|
-
"typecheck": "tsc --noEmit",
|
|
25
|
-
"test": "vitest run",
|
|
26
|
-
"lint": "biome check src",
|
|
27
|
-
"lint:fix": "biome check --write src",
|
|
28
|
-
"prepublishOnly": "pnpm build"
|
|
29
|
-
},
|
|
30
22
|
"peerDependencies": {
|
|
31
23
|
"express": "^5.0.0"
|
|
32
24
|
},
|
|
@@ -47,5 +39,12 @@
|
|
|
47
39
|
"type": "git",
|
|
48
40
|
"url": "git+https://github.com/godaddy/javascript.git",
|
|
49
41
|
"directory": "packages/commerce-server"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsdown",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"lint": "biome check src",
|
|
48
|
+
"lint:fix": "biome check --write src"
|
|
50
49
|
}
|
|
51
|
-
}
|
|
50
|
+
}
|