@01.software/cli 0.10.1 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  // src/handler.ts
2
2
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3
3
 
4
- // ../../packages/auth-contracts/dist/index.js
4
+ // ../../packages/auth-contracts/src/index.ts
5
5
  var MCP_RESOURCE_AUDIENCE = "https://mcp.01.software/mcp";
6
6
  var MCP_OAUTH_ISSUER = "https://01.software";
7
7
  var MCP_PROTECTED_RESOURCE_METADATA_PATH = "/.well-known/oauth-protected-resource/mcp";
@@ -295,7 +295,8 @@ var restockActionSchema = z2.enum(["return_to_stock", "discard"]);
295
295
  var returnWithRefundItemSchema = z2.object({
296
296
  orderItem: z2.union([z2.string(), z2.number()]).transform(String),
297
297
  quantity: z2.number().int().positive("quantity must be a positive integer"),
298
- restockAction: restockActionSchema.default("return_to_stock")
298
+ restockAction: restockActionSchema.default("return_to_stock"),
299
+ restockingFee: z2.number().min(0, "restockingFee must be non-negative").optional().describe("Restocking fee charged for this line (ADR 0005 \xA7Gap 1)")
299
300
  }).strict();
300
301
  var returnWithRefundSchema = z2.object({
301
302
  orderNumber: z2.string().min(1, "orderNumber is required").describe("Order number (required)"),
@@ -303,6 +304,7 @@ var returnWithRefundSchema = z2.object({
303
304
  reasonDetail: z2.string().optional().describe("Detailed reason text (optional)"),
304
305
  returnItems: z2.array(returnWithRefundItemSchema).min(1, "At least one return item is required").max(100, "Too many return items").describe("Array of products to return (required)"),
305
306
  refundAmount: z2.number().min(0, "refundAmount must be non-negative").describe("Refund amount (required, min 0)"),
307
+ returnShippingFee: z2.number().min(0, "returnShippingFee must be non-negative").optional().describe("Return shipping fee charged to the customer (ADR 0005 \xA7Gap 1)"),
306
308
  pgPaymentId: z2.string().min(1, "pgPaymentId is required").describe("PG payment ID for refund (required)"),
307
309
  paymentKey: z2.string().min(1).optional().describe("Provider payment key for verified refund"),
308
310
  refundReceiptUrl: z2.string().optional().describe("Refund receipt URL (optional)")
@@ -331,6 +333,16 @@ var MCP_TOOL_CONTRACT = {
331
333
  oauthScope: "mcp:read",
332
334
  readOnly: true
333
335
  },
336
+ "product-detail": {
337
+ consoleRole: "tenant-viewer",
338
+ oauthScope: "mcp:read",
339
+ readOnly: true
340
+ },
341
+ "product-upsert": {
342
+ consoleRole: "tenant-admin",
343
+ oauthScope: "mcp:write",
344
+ readOnly: false
345
+ },
334
346
  "validate-discount": {
335
347
  consoleRole: "tenant-viewer",
336
348
  oauthScope: "mcp:read",
@@ -530,6 +542,21 @@ var TOOL_POLICY_MANIFEST = {
530
542
  consoleSurface: "GET /api/products/{id}/stock",
531
543
  annotationPolicy: READ_ONLY_ANNOTATION
532
544
  },
545
+ "product-detail": {
546
+ category: "read-only-collection",
547
+ oauthScope: MCP_SCOPES.read,
548
+ consoleRole: "tenant-viewer",
549
+ consoleSurface: "GET /api/products/detail",
550
+ annotationPolicy: READ_ONLY_ANNOTATION
551
+ },
552
+ "product-upsert": {
553
+ category: "mutation-product",
554
+ oauthScope: MCP_SCOPES.write,
555
+ consoleRole: "tenant-admin",
556
+ consoleSurface: "POST /api/products/upsert",
557
+ annotationPolicy: DESTRUCTIVE_IDEMPOTENT_MUTATION_ANNOTATION,
558
+ exemptionReason: REASON_IDEMPOTENT_DESTRUCTIVE_UPDATE
559
+ },
533
560
  "validate-discount": {
534
561
  category: "read-only-collection",
535
562
  oauthScope: MCP_SCOPES.read,
@@ -883,9 +910,12 @@ function signMcpServiceToken(context) {
883
910
  }
884
911
 
885
912
  // src/lib/console-api.ts
886
- var BASE_URL = process.env.SOFTWARE_API_URL || "http://localhost:3000";
913
+ var DEFAULT_API_URL = "https://api.01.software";
887
914
  var TIMEOUT_MS = 5e3;
888
915
  var MISSING_HTTP_AUTH_CONTEXT_ERROR = "MCP HTTP requests require a validated OAuth tenant context before tool execution.";
916
+ function resolveConsoleApiUrl() {
917
+ return (process.env.SOFTWARE_API_URL || process.env.NEXT_PUBLIC_SOFTWARE_API_URL || DEFAULT_API_URL).replace(/\/$/, "");
918
+ }
889
919
  function resolveAuthHeaderContext() {
890
920
  const oauthContext = tenantAuthContext();
891
921
  if (oauthContext) {
@@ -935,7 +965,7 @@ async function consoleGet(path, apiKey) {
935
965
  const controller = new AbortController();
936
966
  const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
937
967
  try {
938
- const res = await fetch(`${BASE_URL}${path}`, {
968
+ const res = await fetch(`${resolveConsoleApiUrl()}${path}`, {
939
969
  headers: authHeaders,
940
970
  signal: controller.signal
941
971
  });
@@ -954,7 +984,7 @@ async function consolePost(path, body, apiKey) {
954
984
  const controller = new AbortController();
955
985
  const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
956
986
  try {
957
- const res = await fetch(`${BASE_URL}${path}`, {
987
+ const res = await fetch(`${resolveConsoleApiUrl()}${path}`, {
958
988
  method: "POST",
959
989
  headers: { ...authHeaders, "Content-Type": "application/json" },
960
990
  body: JSON.stringify(body),
@@ -975,7 +1005,7 @@ async function consolePostTelemetry(path, body, apiKey) {
975
1005
  const controller = new AbortController();
976
1006
  const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
977
1007
  try {
978
- const res = await fetch(`${BASE_URL}${path}`, {
1008
+ const res = await fetch(`${resolveConsoleApiUrl()}${path}`, {
979
1009
  method: "POST",
980
1010
  headers: { ...authHeaders, "Content-Type": "application/json" },
981
1011
  body: JSON.stringify(body),
@@ -1873,6 +1903,118 @@ async function stockCheck({
1873
1903
  }
1874
1904
  }
1875
1905
 
1906
+ // src/tools/product-detail.ts
1907
+ import { z as z22 } from "zod";
1908
+ var schema22 = {
1909
+ slug: z22.string().optional().describe("Product slug (one of slug or id required)"),
1910
+ id: z22.string().optional().describe("Product id (one of slug or id required)")
1911
+ };
1912
+ var metadata22 = {
1913
+ name: "product-detail",
1914
+ description: "Fetch full product detail by slug or id. Returns one resolver-ready product with variants, option slugs, option value slugs/media, brand, categories, tags, images, videos, and listing rollup, or null if missing/unpublished/wrong tenant/feature disabled.",
1915
+ annotations: {
1916
+ title: "Get product detail",
1917
+ readOnlyHint: true,
1918
+ destructiveHint: false,
1919
+ idempotentHint: true
1920
+ }
1921
+ };
1922
+ async function productDetail({
1923
+ slug,
1924
+ id
1925
+ }) {
1926
+ try {
1927
+ if (Boolean(slug) === Boolean(id)) {
1928
+ return toolError(new Error("Provide exactly one of slug or id"));
1929
+ }
1930
+ const client = getClient();
1931
+ const params = slug ? { slug } : { id };
1932
+ const result = await client.commerce.product.detail(params);
1933
+ return toolSuccess({ data: result });
1934
+ } catch (error) {
1935
+ return toolError(error);
1936
+ }
1937
+ }
1938
+
1939
+ // src/tools/product-upsert.ts
1940
+ import { z as z23 } from "zod";
1941
+ var optionValueSchema = z23.object({
1942
+ id: z23.string().optional().describe("Existing option-value ID for updates"),
1943
+ value: z23.string().describe("Display label (e.g. Black, S)"),
1944
+ slug: z23.string().optional().describe("Canonical value token used in variant maps and URLs"),
1945
+ swatchColor: z23.string().nullable().optional(),
1946
+ thumbnail: z23.string().nullable().optional(),
1947
+ images: z23.array(z23.string()).optional(),
1948
+ metadata: z23.unknown().optional()
1949
+ });
1950
+ var optionSchema = z23.object({
1951
+ id: z23.string().optional().describe("Existing option ID for updates"),
1952
+ title: z23.string().describe("Option name (e.g. Color, Size)"),
1953
+ slug: z23.string().optional().describe("Canonical option token used in variant maps and URLs"),
1954
+ values: z23.array(optionValueSchema).describe("Allowed option values")
1955
+ });
1956
+ var variantOptionValueSchema = z23.object({
1957
+ valueSlug: z23.string().optional(),
1958
+ valueId: z23.string().optional(),
1959
+ value: z23.string().optional()
1960
+ });
1961
+ var variantSchema = z23.object({
1962
+ id: z23.string().optional().describe("Existing variant ID for updates"),
1963
+ optionValues: z23.union([
1964
+ z23.record(z23.string(), z23.union([z23.string(), variantOptionValueSchema])),
1965
+ z23.array(z23.string())
1966
+ ]).optional().describe(
1967
+ "Option-value selection. Prefer canonical { optionSlug: valueSlug } maps. Object values may use { valueSlug, valueId, value }. Exact { OptionTitle: ValueLabel } maps remain compatibility-only and fail when labels are ambiguous. Arrays of option-value IDs are also accepted."
1968
+ ),
1969
+ sku: z23.string().nullable().optional(),
1970
+ title: z23.string().nullable().optional(),
1971
+ price: z23.number().nonnegative().describe("Selling price (KRW, min 0)"),
1972
+ compareAtPrice: z23.number().nonnegative().nullable().optional(),
1973
+ stock: z23.number().int().nonnegative().optional(),
1974
+ isUnlimited: z23.boolean().optional(),
1975
+ weight: z23.number().nonnegative().nullable().optional(),
1976
+ requiresShipping: z23.boolean().optional(),
1977
+ barcode: z23.string().nullable().optional(),
1978
+ externalId: z23.string().nullable().optional(),
1979
+ isActive: z23.boolean().optional(),
1980
+ thumbnail: z23.string().nullable().optional(),
1981
+ images: z23.array(z23.string()).optional(),
1982
+ metadata: z23.unknown().optional()
1983
+ });
1984
+ var schema23 = {
1985
+ product: z23.record(z23.string(), z23.unknown()).describe(
1986
+ "Product fields. Include `id` to update an existing product; omit for create (then `title` is required)."
1987
+ ),
1988
+ options: z23.array(optionSchema).optional().describe(
1989
+ "Option definitions. Prefer explicit option slug and value slugs. Omitted options on an existing product are deleted (with their values)."
1990
+ ),
1991
+ variants: z23.array(variantSchema).optional().describe(
1992
+ "Variant rows. Prefer canonical { optionSlug: valueSlug } optionValues maps. Omitted variants on an existing product are deleted, unless referenced by an active cart or non-terminal order \u2014 those are soft-deactivated (isActive: false)."
1993
+ )
1994
+ };
1995
+ var metadata23 = {
1996
+ name: "product-upsert",
1997
+ description: "Atomically create or update a product together with its options, option-values, and variants in a single transaction. Mirrors Shopify productSet semantics. Any failure rolls back the entire write.",
1998
+ annotations: {
1999
+ title: "Upsert product (atomic)",
2000
+ readOnlyHint: false,
2001
+ destructiveHint: true,
2002
+ idempotentHint: true,
2003
+ openWorldHint: false
2004
+ }
2005
+ };
2006
+ async function productUpsert(params) {
2007
+ try {
2008
+ const client = getClient();
2009
+ const result = await client.commerce.product.upsert(
2010
+ params
2011
+ );
2012
+ return toolSuccess({ data: result });
2013
+ } catch (error) {
2014
+ return toolError(error);
2015
+ }
2016
+ }
2017
+
1876
2018
  // src/tools/get-collection-schema.ts
1877
2019
  import { SERVER_COLLECTIONS as SERVER_COLLECTIONS3 } from "@01.software/sdk";
1878
2020
 
@@ -1887,8 +2029,8 @@ async function getCollectionSchema(collection) {
1887
2029
  }
1888
2030
 
1889
2031
  // src/tools/get-collection-schema.ts
1890
- var schema22 = createCollectionSchemaToolInputSchema(SERVER_COLLECTIONS3).shape;
1891
- var metadata22 = {
2032
+ var schema24 = createCollectionSchemaToolInputSchema(SERVER_COLLECTIONS3).shape;
2033
+ var metadata24 = {
1892
2034
  name: "get-collection-schema",
1893
2035
  description: "Get the authoritative tenant-aware collection schema from console. Use this before create/update to understand writable fields, hidden fields, required metadata, and collection-level visibility.",
1894
2036
  annotations: {
@@ -1939,8 +2081,8 @@ async function getTenantFeatureProgress(feature, includeEvidence = false) {
1939
2081
  }
1940
2082
 
1941
2083
  // src/tools/get-tenant-context.ts
1942
- var schema23 = tenantContextToolInputSchema.shape;
1943
- var metadata23 = {
2084
+ var schema25 = tenantContextToolInputSchema.shape;
2085
+ var metadata25 = {
1944
2086
  name: "get-tenant-context",
1945
2087
  description: "Get current tenant features, active collections, and field visibility. Call this at the start of every session. Use includeCounts=true to also get per-collection document counts for setup diagnostics.",
1946
2088
  annotations: {
@@ -2017,8 +2159,8 @@ async function handler({
2017
2159
  }
2018
2160
 
2019
2161
  // src/tools/check-feature-progress.ts
2020
- var schema24 = tenantFeatureProgressInputSchema.shape;
2021
- var metadata24 = {
2162
+ var schema26 = tenantFeatureProgressInputSchema.shape;
2163
+ var metadata26 = {
2022
2164
  name: "check-feature-progress",
2023
2165
  description: "Check tenant implementation progress for a supported feature. Start with feature=ecommerce to inspect catalog, cart, checkout, payment result, webhook, and operations readiness without mutating tenant data.",
2024
2166
  annotations: {
@@ -2041,7 +2183,7 @@ async function handler2({
2041
2183
  }
2042
2184
 
2043
2185
  // src/tools/list-configurable-fields.ts
2044
- import { z as z22 } from "zod";
2186
+ import { z as z24 } from "zod";
2045
2187
 
2046
2188
  // src/lib/field-config.ts
2047
2189
  async function fetchFieldConfigs() {
@@ -2064,12 +2206,12 @@ function invalidateFieldConfigCache() {
2064
2206
  }
2065
2207
 
2066
2208
  // src/tools/list-configurable-fields.ts
2067
- var schema25 = {
2068
- collection: z22.string().optional().describe(
2209
+ var schema27 = {
2210
+ collection: z24.string().optional().describe(
2069
2211
  "Filter by collection slug (optional \u2014 returns all if omitted). Use this filter to reduce response size when you know which collection to check."
2070
2212
  )
2071
2213
  };
2072
- var metadata25 = {
2214
+ var metadata27 = {
2073
2215
  name: "list-configurable-fields",
2074
2216
  description: "List all configurable fields for tenant collections with current visibility state. Shows which fields can be shown/hidden and their current status. Returns all collections including inactive features \u2014 cross-reference with get-tenant-context for active features. Response includes ~300 fields across 47 collections \u2014 use collection filter when possible.",
2075
2217
  annotations: {
@@ -2100,17 +2242,17 @@ async function listConfigurableFields(params) {
2100
2242
  }
2101
2243
 
2102
2244
  // src/tools/update-field-config.ts
2103
- import { z as z23 } from "zod";
2104
- var schema26 = {
2105
- collection: z23.string().min(1).describe("Collection slug (required)"),
2106
- hiddenFields: z23.array(z23.string().min(1).max(200)).max(300).describe(
2245
+ import { z as z25 } from "zod";
2246
+ var schema28 = {
2247
+ collection: z25.string().min(1).describe("Collection slug (required)"),
2248
+ hiddenFields: z25.array(z25.string().min(1).max(200)).max(300).describe(
2107
2249
  "Fields to hide (required). This is a FULL REPLACE \u2014 fields NOT in this list will be shown. Pass [] to show all fields. Use list-configurable-fields first to see available field paths."
2108
2250
  ),
2109
- isHidden: z23.boolean().optional().describe(
2251
+ isHidden: z25.boolean().optional().describe(
2110
2252
  "Hide the entire collection from Admin Panel (optional). When true, individual hiddenFields are irrelevant."
2111
2253
  )
2112
2254
  };
2113
- var metadata26 = {
2255
+ var metadata28 = {
2114
2256
  name: "update-field-config",
2115
2257
  description: "Update field visibility configuration for a tenant collection. Hidden fields are removed from the Admin Panel UI. IMPORTANT: hiddenFields is a full replace, not a merge. Always call list-configurable-fields first to see current state.",
2116
2258
  annotations: {
@@ -2138,7 +2280,7 @@ async function updateFieldConfig(params) {
2138
2280
  }
2139
2281
 
2140
2282
  // src/tools/sdk-get-recipe.ts
2141
- import { z as z24 } from "zod";
2283
+ import { z as z26 } from "zod";
2142
2284
 
2143
2285
  // src/lib/sdk-recipes.ts
2144
2286
  var recipes = {
@@ -2570,8 +2712,8 @@ function getRecipe(goal, runtime = "both") {
2570
2712
  }
2571
2713
 
2572
2714
  // src/tools/sdk-get-recipe.ts
2573
- var schema27 = {
2574
- goal: z24.enum([
2715
+ var schema29 = {
2716
+ goal: z26.enum([
2575
2717
  "fetch-list",
2576
2718
  "fetch-by-id",
2577
2719
  "create-item",
@@ -2583,11 +2725,11 @@ var schema27 = {
2583
2725
  "file-upload",
2584
2726
  "bulk-operations"
2585
2727
  ]).describe("What the user wants to accomplish"),
2586
- runtime: z24.enum(["browser", "server", "both"]).default("both").describe("Target runtime environment"),
2587
- collection: z24.string().optional().describe("Specific collection name if applicable"),
2588
- includeExample: z24.boolean().default(true).describe("Whether to include a full code example")
2728
+ runtime: z26.enum(["browser", "server", "both"]).default("both").describe("Target runtime environment"),
2729
+ collection: z26.string().optional().describe("Specific collection name if applicable"),
2730
+ includeExample: z26.boolean().default(true).describe("Whether to include a full code example")
2589
2731
  };
2590
- var metadata27 = {
2732
+ var metadata29 = {
2591
2733
  name: "sdk-get-recipe",
2592
2734
  description: "Get a complete SDK code recipe for a specific task. Returns recommended approach, code example, and related documentation links. Use this FIRST when the user asks how to do something with the SDK.",
2593
2735
  annotations: {
@@ -2630,7 +2772,7 @@ function handler3({
2630
2772
  }
2631
2773
 
2632
2774
  // src/tools/sdk-search-docs.ts
2633
- import { z as z25 } from "zod";
2775
+ import { z as z27 } from "zod";
2634
2776
 
2635
2777
  // src/lib/sdk-doc-index.ts
2636
2778
  var docIndex = [
@@ -2805,11 +2947,11 @@ function searchDocs(query, limit = 5) {
2805
2947
  }
2806
2948
 
2807
2949
  // src/tools/sdk-search-docs.ts
2808
- var schema28 = {
2809
- query: z25.string().min(2).describe('Search keyword or phrase (e.g. "infinite scroll", "webhook", "customer login")'),
2810
- limit: z25.number().min(1).max(10).default(5).describe("Maximum results to return (1-10, default: 5)")
2950
+ var schema30 = {
2951
+ query: z27.string().min(2).describe('Search keyword or phrase (e.g. "infinite scroll", "webhook", "customer login")'),
2952
+ limit: z27.number().min(1).max(10).default(5).describe("Maximum results to return (1-10, default: 5)")
2811
2953
  };
2812
- var metadata28 = {
2954
+ var metadata30 = {
2813
2955
  name: "sdk-search-docs",
2814
2956
  description: "Search SDK documentation by keyword. Returns matching topics with summaries and resource links. Use when looking for specific SDK features or patterns.",
2815
2957
  annotations: {
@@ -2844,9 +2986,9 @@ function handler4({
2844
2986
  }
2845
2987
 
2846
2988
  // src/tools/sdk-get-auth-setup.ts
2847
- import { z as z26 } from "zod";
2848
- var schema29 = {
2849
- scenario: z26.enum([
2989
+ import { z as z28 } from "zod";
2990
+ var schema31 = {
2991
+ scenario: z28.enum([
2850
2992
  "browser-client",
2851
2993
  "server-client",
2852
2994
  "customer-auth",
@@ -2855,7 +2997,7 @@ var schema29 = {
2855
2997
  "webhook-verification"
2856
2998
  ]).describe("Authentication scenario")
2857
2999
  };
2858
- var metadata29 = {
3000
+ var metadata31 = {
2859
3001
  name: "sdk-get-auth-setup",
2860
3002
  description: "Get the current authentication setup for a specific scenario. Returns env var names, code snippets, and security notes.",
2861
3003
  annotations: {
@@ -3009,14 +3151,14 @@ function handler5({
3009
3151
  }
3010
3152
 
3011
3153
  // src/tools/sdk-get-collection-pattern.ts
3012
- import { z as z27 } from "zod";
3154
+ import { z as z29 } from "zod";
3013
3155
  import { COLLECTIONS, SERVER_COLLECTIONS as SERVER_COLLECTIONS4 } from "@01.software/sdk";
3014
- var schema30 = {
3015
- collection: z27.enum(SERVER_COLLECTIONS4).describe("Collection name"),
3016
- operation: z27.enum(["read", "write", "full-crud"]).default("read").describe("What operations are needed"),
3017
- surface: z27.enum(["query-builder", "react-query", "server-api"]).default("query-builder").describe("Preferred API surface")
3156
+ var schema32 = {
3157
+ collection: z29.enum(SERVER_COLLECTIONS4).describe("Collection name"),
3158
+ operation: z29.enum(["read", "write", "full-crud"]).default("read").describe("What operations are needed"),
3159
+ surface: z29.enum(["query-builder", "react-query", "server-api"]).default("query-builder").describe("Preferred API surface")
3018
3160
  };
3019
- var metadata30 = {
3161
+ var metadata32 = {
3020
3162
  name: "sdk-get-collection-pattern",
3021
3163
  description: "Get the recommended CRUD pattern for a specific collection. Returns code examples for the chosen API surface and operation type.",
3022
3164
  annotations: {
@@ -3217,14 +3359,14 @@ function handler6({
3217
3359
  }
3218
3360
 
3219
3361
  // src/prompts/sdk-usage-guide.ts
3220
- import { z as z28 } from "zod";
3221
- var schema31 = {
3222
- goal: z28.string().describe('What the user wants to accomplish (e.g., "query product list", "create order")'),
3223
- runtime: z28.enum(["browser", "server"]).optional().describe("Target runtime: browser (React/Next.js client) or server (Node.js)"),
3224
- surface: z28.enum(["query-builder", "react-query", "customer-api", "server-api"]).optional().describe("Preferred API surface"),
3225
- collection: z28.string().optional().describe("Specific collection if relevant")
3362
+ import { z as z30 } from "zod";
3363
+ var schema33 = {
3364
+ goal: z30.string().describe('What the user wants to accomplish (e.g., "query product list", "create order")'),
3365
+ runtime: z30.enum(["browser", "server"]).optional().describe("Target runtime: browser (React/Next.js client) or server (Node.js)"),
3366
+ surface: z30.enum(["query-builder", "react-query", "customer-api", "server-api"]).optional().describe("Preferred API surface"),
3367
+ collection: z30.string().optional().describe("Specific collection if relevant")
3226
3368
  };
3227
- var metadata31 = {
3369
+ var metadata33 = {
3228
3370
  name: "sdk-usage-guide",
3229
3371
  title: "SDK Usage Guide",
3230
3372
  description: "Provides guidance on how to perform a specific task using the 01.software SDK",
@@ -3357,18 +3499,44 @@ const client = createServerClient({
3357
3499
  })
3358
3500
  \`\`\`
3359
3501
 
3360
- You can perform the "${goal}" task by following the patterns above.`;
3502
+ You can perform the "${goal}" task by following the patterns above.
3503
+
3504
+ ## Common recipes
3505
+
3506
+ ### Product detail page (slug-based)
3507
+
3508
+ \`\`\`typescript
3509
+ const product = await client.commerce.product.detail({ slug })
3510
+ if (!product) return notFound()
3511
+ // product: { product, variants, options, brand, categories, tags, images, videos, listing }
3512
+ \`\`\`
3513
+
3514
+ For React: \`const { data } = client.query.useProductDetailBySlug(slug)\`.
3515
+
3516
+ ### Product listing (grouped)
3517
+
3518
+ \`\`\`typescript
3519
+ const { docs } = await client.commerce.product.listingGroups({ productIds })
3520
+ \`\`\`
3521
+
3522
+ ### Stock check before adding to cart
3523
+
3524
+ \`\`\`typescript
3525
+ const { allAvailable } = await client.commerce.product.stockCheck({
3526
+ items: [{ variantId, quantity }],
3527
+ })
3528
+ \`\`\``;
3361
3529
  }
3362
3530
 
3363
3531
  // src/prompts/collection-query-help.ts
3364
- import { z as z29 } from "zod";
3532
+ import { z as z31 } from "zod";
3365
3533
  import { COLLECTIONS as COLLECTIONS2, SERVER_COLLECTIONS as SERVER_COLLECTIONS5 } from "@01.software/sdk";
3366
- var schema32 = {
3367
- collection: z29.enum(SERVER_COLLECTIONS5).describe("Collection name"),
3368
- operation: z29.enum(["find", "create", "update", "delete"]).describe("Operation to perform (find, create, update, delete)"),
3369
- filters: z29.string().optional().describe("Filter conditions (JSON string, optional)")
3534
+ var schema34 = {
3535
+ collection: z31.enum(SERVER_COLLECTIONS5).describe("Collection name"),
3536
+ operation: z31.enum(["find", "create", "update", "delete"]).describe("Operation to perform (find, create, update, delete)"),
3537
+ filters: z31.string().optional().describe("Filter conditions (JSON string, optional)")
3370
3538
  };
3371
- var metadata32 = {
3539
+ var metadata34 = {
3372
3540
  name: "collection-query-help",
3373
3541
  title: "Collection Query Help",
3374
3542
  description: "Provides guidance on how to write queries for a specific collection",
@@ -3460,16 +3628,16 @@ ${operation === "find" ? `- Use \`where\` option for filtering (Payload query sy
3460
3628
  }
3461
3629
 
3462
3630
  // src/prompts/order-flow-guide.ts
3463
- import { z as z30 } from "zod";
3464
- var schema33 = {
3465
- scenario: z30.enum([
3631
+ import { z as z32 } from "zod";
3632
+ var schema35 = {
3633
+ scenario: z32.enum([
3466
3634
  "simple-order",
3467
3635
  "cart-checkout",
3468
3636
  "return-refund",
3469
3637
  "fulfillment-tracking"
3470
3638
  ]).describe("Order flow scenario")
3471
3639
  };
3472
- var metadata33 = {
3640
+ var metadata35 = {
3473
3641
  name: "order-flow-guide",
3474
3642
  title: "Order Flow Guide",
3475
3643
  description: "Provides step-by-step guidance for ecommerce order flows including creation, checkout, returns, and fulfillment.",
@@ -3654,9 +3822,9 @@ ${SCENARIOS[scenario] || "Unknown scenario."}
3654
3822
  }
3655
3823
 
3656
3824
  // src/prompts/feature-setup-guide.ts
3657
- import { z as z31 } from "zod";
3658
- var schema34 = {
3659
- feature: z31.enum([
3825
+ import { z as z33 } from "zod";
3826
+ var schema36 = {
3827
+ feature: z33.enum([
3660
3828
  "ecommerce",
3661
3829
  "customers",
3662
3830
  "articles",
@@ -3671,7 +3839,7 @@ var schema34 = {
3671
3839
  "community"
3672
3840
  ]).describe("Feature to get setup guide for")
3673
3841
  };
3674
- var metadata34 = {
3842
+ var metadata36 = {
3675
3843
  name: "feature-setup-guide",
3676
3844
  title: "Feature Setup Guide",
3677
3845
  description: "Setup checklist and remediation guide for a tenant feature. Load with check-feature-progress and get-tenant-context to diagnose setup gaps.",
@@ -3878,7 +4046,7 @@ ${FEATURES[feature] || "Unknown feature."}
3878
4046
  }
3879
4047
 
3880
4048
  // src/resources/(config)/app.ts
3881
- var metadata35 = {
4049
+ var metadata37 = {
3882
4050
  name: "app-config",
3883
4051
  title: "Application Config",
3884
4052
  description: "01.software SDK and MCP server configuration information"
@@ -3944,7 +4112,7 @@ Rate limits depend on your tenant plan:
3944
4112
 
3945
4113
  // src/resources/(collections)/schema.ts
3946
4114
  import { COLLECTIONS as COLLECTIONS3 } from "@01.software/sdk";
3947
- var metadata36 = {
4115
+ var metadata38 = {
3948
4116
  name: "collections-schema",
3949
4117
  title: "Collection Schema Info",
3950
4118
  description: "Available collections and their schema information"
@@ -3968,7 +4136,12 @@ var COLLECTIONS_BY_CATEGORY = {
3968
4136
  "fulfillments",
3969
4137
  "fulfillment-items"
3970
4138
  ],
3971
- "Shipping & Returns": ["returns", "return-items", "shipping-policies"],
4139
+ "Shipping & Returns": [
4140
+ "returns",
4141
+ "return-items",
4142
+ "shipping-policies",
4143
+ "shipping-zones"
4144
+ ],
3972
4145
  Customers: [
3973
4146
  "customers",
3974
4147
  "customer-profiles",
@@ -3976,7 +4149,7 @@ var COLLECTIONS_BY_CATEGORY = {
3976
4149
  "customer-addresses"
3977
4150
  ],
3978
4151
  Carts: ["carts", "cart-items"],
3979
- "Discounts & Promotions": ["discounts", "promotions"],
4152
+ Discounts: ["discounts"],
3980
4153
  Documents: ["documents", "document-categories", "document-types"],
3981
4154
  Articles: [
3982
4155
  "articles",
@@ -3990,9 +4163,7 @@ var COLLECTIONS_BY_CATEGORY = {
3990
4163
  "reactions",
3991
4164
  "reaction-types",
3992
4165
  "bookmarks",
3993
- "post-categories",
3994
- "reports",
3995
- "community-bans"
4166
+ "post-categories"
3996
4167
  ],
3997
4168
  Playlists: [
3998
4169
  "playlists",
@@ -4082,7 +4253,7 @@ Total available collections: ${COLLECTIONS3.length}`;
4082
4253
  }
4083
4254
 
4084
4255
  // src/resources/(docs)/getting-started.ts
4085
- var metadata37 = {
4256
+ var metadata39 = {
4086
4257
  name: "docs-getting-started",
4087
4258
  title: "Getting Started",
4088
4259
  description: "01.software SDK getting started guide"
@@ -4127,7 +4298,7 @@ const result = await client.collections.from('products').find({
4127
4298
  }
4128
4299
 
4129
4300
  // src/resources/(docs)/guides.ts
4130
- var metadata38 = {
4301
+ var metadata40 = {
4131
4302
  name: "docs-guides",
4132
4303
  title: "Guides",
4133
4304
  description: "01.software SDK usage guides"
@@ -4338,7 +4509,7 @@ For more implementation guidance, see the [SDK Guide](/developers/sdk).`;
4338
4509
  }
4339
4510
 
4340
4511
  // src/resources/(docs)/api.ts
4341
- var metadata39 = {
4512
+ var metadata41 = {
4342
4513
  name: "docs-api",
4343
4514
  title: "API Reference",
4344
4515
  description: "01.software SDK API reference documentation"
@@ -4624,7 +4795,7 @@ For more details, see the [API documentation](/developers/api).`;
4624
4795
  }
4625
4796
 
4626
4797
  // src/resources/(docs)/query-builder.ts
4627
- var metadata40 = {
4798
+ var metadata42 = {
4628
4799
  name: "docs-query-builder",
4629
4800
  title: "Query Builder",
4630
4801
  description: "01.software SDK Query Builder API reference (client.collections.from)"
@@ -4818,7 +4989,7 @@ console.log(result.hasNextPage) // true
4818
4989
  }
4819
4990
 
4820
4991
  // src/resources/(docs)/react-query.ts
4821
- var metadata41 = {
4992
+ var metadata43 = {
4822
4993
  name: "docs-react-query",
4823
4994
  title: "React Query Hooks",
4824
4995
  description: "01.software SDK React Query hooks reference (client.query)"
@@ -5066,7 +5237,7 @@ export function ProductList() {
5066
5237
  }
5067
5238
 
5068
5239
  // src/resources/(docs)/server-api.ts
5069
- var metadata42 = {
5240
+ var metadata44 = {
5070
5241
  name: "docs-server-api",
5071
5242
  title: "Server-side API",
5072
5243
  description: "01.software SDK server-side API reference (client.commerce) for orders, fulfillments, returns, carts, and validation"
@@ -5328,7 +5499,7 @@ const result = await client.commerce.shipping.calculate({
5328
5499
  }
5329
5500
 
5330
5501
  // src/resources/(docs)/customer-auth.ts
5331
- var metadata43 = {
5502
+ var metadata45 = {
5332
5503
  name: "docs-customer-auth",
5333
5504
  title: "Customer Auth API",
5334
5505
  description: "01.software SDK Customer Auth API reference (client.customer)"
@@ -5506,7 +5677,7 @@ async function loadProfile() {
5506
5677
  }
5507
5678
 
5508
5679
  // src/resources/(docs)/browser-vs-server.ts
5509
- var metadata44 = {
5680
+ var metadata46 = {
5510
5681
  name: "docs-browser-vs-server",
5511
5682
  title: "Client vs ServerClient",
5512
5683
  description: "When to use Client (createClient) vs ServerClient (createServerClient) in the 01.software SDK"
@@ -5665,7 +5836,7 @@ export function ProductList() {
5665
5836
  }
5666
5837
 
5667
5838
  // src/resources/(docs)/file-upload.ts
5668
- var metadata45 = {
5839
+ var metadata47 = {
5669
5840
  name: "docs-file-upload",
5670
5841
  title: "File Upload",
5671
5842
  description: "01.software SDK file upload patterns using the images collection"
@@ -5816,7 +5987,7 @@ The platform stores files in Cloudflare R2 and serves via CDN (\`cdn.01.software
5816
5987
  }
5817
5988
 
5818
5989
  // src/resources/(docs)/webhook.ts
5819
- var metadata46 = {
5990
+ var metadata48 = {
5820
5991
  name: "docs-webhook",
5821
5992
  title: "Webhooks",
5822
5993
  description: "01.software SDK webhook verification and event handling"
@@ -5929,9 +6100,91 @@ Failed webhook deliveries are queued with automatic retries. Ensure your handler
5929
6100
  Configure webhook URLs in the 01.software console under Tenant Settings > Webhooks. Multiple URLs can be registered; all receive every event.`;
5930
6101
  }
5931
6102
 
6103
+ // src/resources/(docs)/product-detail.ts
6104
+ var metadata49 = {
6105
+ name: "docs-product-detail",
6106
+ title: "Product Detail Helper",
6107
+ description: "01.software SDK commerce.product.detail helper guide"
6108
+ };
6109
+ function handler19() {
6110
+ return `# Product Detail Helper
6111
+
6112
+ ## When to use the helper vs the raw query builder
6113
+
6114
+ Use \`client.commerce.product.detail({ slug | id })\` when you need a full product detail page payload in one call. The helper folds the Payload query, access policy, and response shaping (variants, options, option value slugs/media, brand, categories, tags, images, videos, listing rollup) into a single call.
6115
+
6116
+ Use \`client.collections.from('products').find(...)\` (escape hatch) when you need bulk reads, custom filter combinations, or fields outside the helper response shape.
6117
+
6118
+ ## Single-call example
6119
+
6120
+ \`\`\`typescript
6121
+ import { createClient, resolveProductSelection } from '@01.software/sdk'
6122
+
6123
+ const client = createClient({
6124
+ publishableKey: process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY!,
6125
+ })
6126
+
6127
+ const detail = await client.commerce.product.detail({ slug: 'my-product' })
6128
+ if (!detail) return notFound()
6129
+ const selection = resolveProductSelection(detail, {
6130
+ search: '?opt.color=black&opt.size=large',
6131
+ })
6132
+ // selection.selectedVariant, selection.price, selection.stock, selection.media
6133
+ \`\`\`
6134
+
6135
+ ## URL round-trip
6136
+
6137
+ Use the SDK codec for one canonical selection URL format: \`opt.<optionSlug>=<valueSlug>\`. Option and value slugs are the stable public tokens exposed by product detail.
6138
+
6139
+ \`\`\`typescript
6140
+ import { createProductSelectionCodec } from '@01.software/sdk'
6141
+
6142
+ const codec = createProductSelectionCodec(detail)
6143
+ const selection = codec.parse('?opt.color=black')
6144
+ const href = codec.stringify(selection)
6145
+ \`\`\`
6146
+
6147
+ Value-slug-only URLs such as \`?black\` or \`?color=black\` are rejected because option titles are not stable identifiers.
6148
+
6149
+ ## React Query hook variant
6150
+
6151
+ \`\`\`typescript
6152
+ const { data: detail, isLoading } = client.query.useProductDetailBySlug(slug)
6153
+ \`\`\`
6154
+
6155
+ Cache invalidates automatically when any of 10 detail-relevant collections is mutated through SDK mutation hooks.
6156
+
6157
+ ## SSG / Server Component snippet
6158
+
6159
+ \`\`\`tsx
6160
+ // app/products/[slug]/page.tsx
6161
+ import { createClient } from '@01.software/sdk'
6162
+ import { notFound } from 'next/navigation'
6163
+
6164
+ export const revalidate = 60
6165
+
6166
+ export default async function ProductPage({ params }: { params: { slug: string } }) {
6167
+ const client = createClient({
6168
+ publishableKey: process.env.NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY!,
6169
+ })
6170
+ const detail = await client.commerce.product.detail({ slug: params.slug })
6171
+ if (!detail) return notFound()
6172
+ return <ProductView detail={detail} />
6173
+ }
6174
+ \`\`\`
6175
+
6176
+ ## The \`null\` return contract
6177
+
6178
+ The endpoint returns 404 for \`not_found\`, \`not_published\`, \`tenant_mismatch\`, or \`feature_disabled\`. The SDK collapses all 404s to \`null\` so consumer UIs render one "not available" path.
6179
+
6180
+ ## Backend correlation
6181
+
6182
+ Log \`client.lastRequestId\` against backend logs \u2014 the endpoint records the exact 404 code alongside the request ID.`;
6183
+ }
6184
+
5932
6185
  // src/server.ts
5933
6186
  var REGISTERED_TOOLS_BY_SERVER = /* @__PURE__ */ new WeakMap();
5934
- function registerTool(server, schema35, meta, handler20) {
6187
+ function registerTool(server, schema37, meta, handler21) {
5935
6188
  let registered = REGISTERED_TOOLS_BY_SERVER.get(server);
5936
6189
  if (!registered) {
5937
6190
  registered = /* @__PURE__ */ new Set();
@@ -5942,7 +6195,7 @@ function registerTool(server, schema35, meta, handler20) {
5942
6195
  meta.name,
5943
6196
  {
5944
6197
  description: meta.description,
5945
- inputSchema: schema35,
6198
+ inputSchema: schema37,
5946
6199
  annotations: meta.annotations
5947
6200
  },
5948
6201
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -5971,7 +6224,7 @@ function registerTool(server, schema35, meta, handler20) {
5971
6224
  const summary = activeSummary ?? ownSummary;
5972
6225
  let result = null;
5973
6226
  try {
5974
- result = await handler20(params);
6227
+ result = await handler21(params);
5975
6228
  return { content: [{ type: "text", text: result }] };
5976
6229
  } finally {
5977
6230
  if (summary) {
@@ -5988,26 +6241,26 @@ function registerTool(server, schema35, meta, handler20) {
5988
6241
  }
5989
6242
  );
5990
6243
  }
5991
- function registerPrompt(server, schema35, meta, handler20) {
6244
+ function registerPrompt(server, schema37, meta, handler21) {
5992
6245
  server.registerPrompt(
5993
6246
  meta.name,
5994
6247
  {
5995
6248
  title: meta.title,
5996
6249
  description: meta.description,
5997
- argsSchema: schema35
6250
+ argsSchema: schema37
5998
6251
  },
5999
6252
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6000
6253
  (params) => ({
6001
6254
  messages: [
6002
6255
  {
6003
6256
  role: meta.role ?? "assistant",
6004
- content: { type: "text", text: handler20(params) }
6257
+ content: { type: "text", text: handler21(params) }
6005
6258
  }
6006
6259
  ]
6007
6260
  })
6008
6261
  );
6009
6262
  }
6010
- function registerStaticResource(server, uri, meta, handler20) {
6263
+ function registerStaticResource(server, uri, meta, handler21) {
6011
6264
  server.registerResource(
6012
6265
  meta.name,
6013
6266
  uri,
@@ -6017,7 +6270,7 @@ function registerStaticResource(server, uri, meta, handler20) {
6017
6270
  mimeType: meta.mimeType ?? "text/plain"
6018
6271
  },
6019
6272
  async (url) => ({
6020
- contents: [{ uri: url.href, text: handler20() }]
6273
+ contents: [{ uri: url.href, text: handler21() }]
6021
6274
  })
6022
6275
  );
6023
6276
  }
@@ -6119,147 +6372,160 @@ function createServer(options = {}) {
6119
6372
  calculateShipping
6120
6373
  );
6121
6374
  registerTool(server, schema21, metadata21, stockCheck);
6375
+ registerTool(server, schema22, metadata22, productDetail);
6376
+ registerTool(
6377
+ server,
6378
+ schema23,
6379
+ metadata23,
6380
+ productUpsert
6381
+ );
6122
6382
  }
6123
- registerTool(
6124
- server,
6125
- schema22,
6126
- metadata22,
6127
- getCollectionSchemaTool
6128
- );
6129
- registerTool(
6130
- server,
6131
- schema23,
6132
- metadata23,
6133
- handler
6134
- );
6135
6383
  registerTool(
6136
6384
  server,
6137
6385
  schema24,
6138
6386
  metadata24,
6139
- handler2
6387
+ getCollectionSchemaTool
6140
6388
  );
6141
6389
  registerTool(
6142
6390
  server,
6143
6391
  schema25,
6144
6392
  metadata25,
6145
- listConfigurableFields
6393
+ handler
6146
6394
  );
6147
6395
  registerTool(
6148
6396
  server,
6149
6397
  schema26,
6150
6398
  metadata26,
6151
- updateFieldConfig
6399
+ handler2
6152
6400
  );
6153
6401
  registerTool(
6154
6402
  server,
6155
6403
  schema27,
6156
6404
  metadata27,
6157
- handler3
6405
+ listConfigurableFields
6158
6406
  );
6159
6407
  registerTool(
6160
6408
  server,
6161
6409
  schema28,
6162
6410
  metadata28,
6163
- handler4
6411
+ updateFieldConfig
6164
6412
  );
6165
6413
  registerTool(
6166
6414
  server,
6167
6415
  schema29,
6168
6416
  metadata29,
6169
- handler5
6417
+ handler3
6170
6418
  );
6171
6419
  registerTool(
6172
6420
  server,
6173
6421
  schema30,
6174
6422
  metadata30,
6175
- handler6
6423
+ handler4
6176
6424
  );
6177
- registerPrompt(
6425
+ registerTool(
6178
6426
  server,
6179
6427
  schema31,
6180
6428
  metadata31,
6181
- sdkUsageGuide
6429
+ handler5
6182
6430
  );
6183
- registerPrompt(
6431
+ registerTool(
6184
6432
  server,
6185
6433
  schema32,
6186
6434
  metadata32,
6187
- collectionQueryHelp
6435
+ handler6
6188
6436
  );
6189
6437
  registerPrompt(
6190
6438
  server,
6191
6439
  schema33,
6192
6440
  metadata33,
6193
- orderFlowGuide
6441
+ sdkUsageGuide
6194
6442
  );
6195
6443
  registerPrompt(
6196
6444
  server,
6197
6445
  schema34,
6198
6446
  metadata34,
6447
+ collectionQueryHelp
6448
+ );
6449
+ registerPrompt(
6450
+ server,
6451
+ schema35,
6452
+ metadata35,
6453
+ orderFlowGuide
6454
+ );
6455
+ registerPrompt(
6456
+ server,
6457
+ schema36,
6458
+ metadata36,
6199
6459
  featureSetupGuide
6200
6460
  );
6201
6461
  registerStaticResource(
6202
6462
  server,
6203
6463
  "config://app",
6204
- metadata35,
6464
+ metadata37,
6205
6465
  handler7
6206
6466
  );
6207
6467
  registerStaticResource(
6208
6468
  server,
6209
6469
  "collections://schema",
6210
- metadata36,
6470
+ metadata38,
6211
6471
  handler8
6212
6472
  );
6213
6473
  registerStaticResource(
6214
6474
  server,
6215
6475
  "docs://sdk/getting-started",
6216
- metadata37,
6476
+ metadata39,
6217
6477
  handler9
6218
6478
  );
6219
- registerStaticResource(server, "docs://sdk/guides", metadata38, handler10);
6220
- registerStaticResource(server, "docs://sdk/api", metadata39, handler11);
6479
+ registerStaticResource(server, "docs://sdk/guides", metadata40, handler10);
6480
+ registerStaticResource(server, "docs://sdk/api", metadata41, handler11);
6221
6481
  registerStaticResource(
6222
6482
  server,
6223
6483
  "docs://sdk/query-builder",
6224
- metadata40,
6484
+ metadata42,
6225
6485
  handler12
6226
6486
  );
6227
6487
  registerStaticResource(
6228
6488
  server,
6229
6489
  "docs://sdk/react-query",
6230
- metadata41,
6490
+ metadata43,
6231
6491
  handler13
6232
6492
  );
6233
6493
  registerStaticResource(
6234
6494
  server,
6235
6495
  "docs://sdk/server-api",
6236
- metadata42,
6496
+ metadata44,
6237
6497
  handler14
6238
6498
  );
6239
6499
  registerStaticResource(
6240
6500
  server,
6241
6501
  "docs://sdk/customer-auth",
6242
- metadata43,
6502
+ metadata45,
6243
6503
  handler15
6244
6504
  );
6245
6505
  registerStaticResource(
6246
6506
  server,
6247
6507
  "docs://sdk/browser-vs-server",
6248
- metadata44,
6508
+ metadata46,
6249
6509
  handler16
6250
6510
  );
6251
6511
  registerStaticResource(
6252
6512
  server,
6253
6513
  "docs://sdk/file-upload",
6254
- metadata45,
6514
+ metadata47,
6255
6515
  handler17
6256
6516
  );
6257
6517
  registerStaticResource(
6258
6518
  server,
6259
6519
  "docs://sdk/webhook",
6260
- metadata46,
6520
+ metadata48,
6261
6521
  handler18
6262
6522
  );
6523
+ registerStaticResource(
6524
+ server,
6525
+ "docs://sdk/product-detail",
6526
+ metadata49,
6527
+ handler19
6528
+ );
6263
6529
  return server;
6264
6530
  }
6265
6531
 
@@ -6595,7 +6861,7 @@ function acceptsEventStream(req) {
6595
6861
  (entry) => entry.trim().split(";")[0]?.toLowerCase() === "text/event-stream"
6596
6862
  );
6597
6863
  }
6598
- async function handler19(req, res) {
6864
+ async function handler20(req, res) {
6599
6865
  setCors(res);
6600
6866
  if (req.method === "OPTIONS") {
6601
6867
  res.writeHead(204);
@@ -6705,5 +6971,5 @@ function writeRequestError(res, err) {
6705
6971
  res.end(JSON.stringify({ error: "Internal server error" }));
6706
6972
  }
6707
6973
  export {
6708
- handler19 as default
6974
+ handler20 as default
6709
6975
  };