x402check 0.1.1 → 0.3.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/index.cjs CHANGED
@@ -28,6 +28,12 @@ const ErrorCode = {
28
28
  NO_EVM_CHECKSUM: "NO_EVM_CHECKSUM",
29
29
  INVALID_SOLANA_ADDRESS: "INVALID_SOLANA_ADDRESS",
30
30
  ADDRESS_NETWORK_MISMATCH: "ADDRESS_NETWORK_MISMATCH",
31
+ INVALID_BAZAAR_INFO: "INVALID_BAZAAR_INFO",
32
+ INVALID_BAZAAR_SCHEMA: "INVALID_BAZAAR_SCHEMA",
33
+ INVALID_BAZAAR_INFO_INPUT: "INVALID_BAZAAR_INFO_INPUT",
34
+ INVALID_OUTPUT_SCHEMA: "INVALID_OUTPUT_SCHEMA",
35
+ INVALID_OUTPUT_SCHEMA_INPUT: "INVALID_OUTPUT_SCHEMA_INPUT",
36
+ MISSING_INPUT_SCHEMA: "MISSING_INPUT_SCHEMA",
31
37
  UNKNOWN_NETWORK: "UNKNOWN_NETWORK",
32
38
  UNKNOWN_ASSET: "UNKNOWN_ASSET",
33
39
  LEGACY_FORMAT: "LEGACY_FORMAT",
@@ -61,6 +67,12 @@ const ErrorMessages = {
61
67
  NO_EVM_CHECKSUM: "EVM address is all-lowercase with no checksum protection",
62
68
  INVALID_SOLANA_ADDRESS: "Invalid Solana address format",
63
69
  ADDRESS_NETWORK_MISMATCH: "Address format does not match network type",
70
+ INVALID_BAZAAR_INFO: "extensions.bazaar.info must be an object with input and output",
71
+ INVALID_BAZAAR_SCHEMA: "extensions.bazaar.schema must be a valid JSON Schema object",
72
+ INVALID_BAZAAR_INFO_INPUT: "extensions.bazaar.info.input must include type and method",
73
+ INVALID_OUTPUT_SCHEMA: "accepts[i].outputSchema must be an object with input and output",
74
+ INVALID_OUTPUT_SCHEMA_INPUT: "accepts[i].outputSchema.input must include type and method",
75
+ MISSING_INPUT_SCHEMA: "No input schema found (no bazaar extension or outputSchema) -- consider adding one so agents know how to call your API",
64
76
  UNKNOWN_NETWORK: "Network is not in the known registry -- config may still work but cannot be fully validated",
65
77
  UNKNOWN_ASSET: "Asset is not in the known registry -- config may still work but cannot be fully validated",
66
78
  LEGACY_FORMAT: "Config uses legacy flat format -- consider upgrading to x402 v2",
@@ -1724,6 +1736,146 @@ function validateLegacy(_config, detectedFormat, _originalInput) {
1724
1736
  return issues;
1725
1737
  }
1726
1738
 
1739
+ //#endregion
1740
+ //#region src/validation/rules/extensions.ts
1741
+ /**
1742
+ * Check whether a value is a non-null plain object (not an array).
1743
+ */
1744
+ function isObject(v) {
1745
+ return v !== null && typeof v === "object" && !Array.isArray(v);
1746
+ }
1747
+ /**
1748
+ * Validate `extensions.bazaar` when present.
1749
+ *
1750
+ * Checks:
1751
+ * - bazaar is an object
1752
+ * - bazaar.info exists and is an object with input (type + method) and output
1753
+ * - bazaar.schema exists and looks like a JSON Schema object
1754
+ *
1755
+ * @returns Array of warning issues (empty when bazaar is absent or valid)
1756
+ */
1757
+ function validateBazaar(config) {
1758
+ const issues = [];
1759
+ if (!config.extensions) return issues;
1760
+ const bazaar = config.extensions["bazaar"];
1761
+ if (bazaar === void 0) return issues;
1762
+ if (!isObject(bazaar)) {
1763
+ issues.push({
1764
+ code: ErrorCode.INVALID_BAZAAR_INFO,
1765
+ field: "extensions.bazaar",
1766
+ message: "extensions.bazaar must be an object",
1767
+ severity: "warning",
1768
+ fix: "Set extensions.bazaar to an object with info and schema properties"
1769
+ });
1770
+ return issues;
1771
+ }
1772
+ const info = bazaar["info"];
1773
+ if (!isObject(info)) issues.push({
1774
+ code: ErrorCode.INVALID_BAZAAR_INFO,
1775
+ field: "extensions.bazaar.info",
1776
+ message: ErrorMessages.INVALID_BAZAAR_INFO,
1777
+ severity: "warning",
1778
+ fix: "Add an info object with input and output properties describing your API"
1779
+ });
1780
+ else {
1781
+ const input = info["input"];
1782
+ if (!isObject(input) || !input["type"] || !input["method"]) issues.push({
1783
+ code: ErrorCode.INVALID_BAZAAR_INFO_INPUT,
1784
+ field: "extensions.bazaar.info.input",
1785
+ message: ErrorMessages.INVALID_BAZAAR_INFO_INPUT,
1786
+ severity: "warning",
1787
+ fix: "Add input.type (e.g. \"application/json\") and input.method (e.g. \"POST\")"
1788
+ });
1789
+ const output = info["output"];
1790
+ if (!isObject(output)) issues.push({
1791
+ code: ErrorCode.INVALID_BAZAAR_INFO,
1792
+ field: "extensions.bazaar.info.output",
1793
+ message: "extensions.bazaar.info.output must be an object",
1794
+ severity: "warning",
1795
+ fix: "Add an output object describing the API response format"
1796
+ });
1797
+ }
1798
+ const schema = bazaar["schema"];
1799
+ if (!isObject(schema) || !schema["type"] && !schema["$schema"] && !schema["properties"]) issues.push({
1800
+ code: ErrorCode.INVALID_BAZAAR_SCHEMA,
1801
+ field: "extensions.bazaar.schema",
1802
+ message: ErrorMessages.INVALID_BAZAAR_SCHEMA,
1803
+ severity: "warning",
1804
+ fix: "Add a JSON Schema object with type, $schema, or properties"
1805
+ });
1806
+ return issues;
1807
+ }
1808
+ /**
1809
+ * Validate `accepts[].outputSchema` on the raw parsed input.
1810
+ *
1811
+ * Uses the raw parsed object because AcceptsEntry strips outputSchema during normalization.
1812
+ *
1813
+ * Checks per entry with outputSchema:
1814
+ * - outputSchema is an object
1815
+ * - outputSchema.input exists with type and method
1816
+ * - outputSchema.output exists and is an object
1817
+ *
1818
+ * @returns Array of warning issues
1819
+ */
1820
+ function validateOutputSchema(parsed) {
1821
+ const issues = [];
1822
+ const accepts = parsed["accepts"];
1823
+ if (!Array.isArray(accepts)) return issues;
1824
+ for (let i = 0; i < accepts.length; i++) {
1825
+ const entry = accepts[i];
1826
+ if (!isObject(entry)) continue;
1827
+ const outputSchema = entry["outputSchema"];
1828
+ if (outputSchema === void 0) continue;
1829
+ const fieldPath = `accepts[${i}].outputSchema`;
1830
+ if (!isObject(outputSchema)) {
1831
+ issues.push({
1832
+ code: ErrorCode.INVALID_OUTPUT_SCHEMA,
1833
+ field: fieldPath,
1834
+ message: ErrorMessages.INVALID_OUTPUT_SCHEMA,
1835
+ severity: "warning",
1836
+ fix: "Set outputSchema to an object with input and output properties"
1837
+ });
1838
+ continue;
1839
+ }
1840
+ const input = outputSchema["input"];
1841
+ if (!isObject(input) || !input["type"] || !input["method"]) issues.push({
1842
+ code: ErrorCode.INVALID_OUTPUT_SCHEMA_INPUT,
1843
+ field: `${fieldPath}.input`,
1844
+ message: ErrorMessages.INVALID_OUTPUT_SCHEMA_INPUT,
1845
+ severity: "warning",
1846
+ fix: "Add input.type (e.g. \"application/json\") and input.method (e.g. \"POST\")"
1847
+ });
1848
+ const output = outputSchema["output"];
1849
+ if (!isObject(output)) issues.push({
1850
+ code: ErrorCode.INVALID_OUTPUT_SCHEMA,
1851
+ field: `${fieldPath}.output`,
1852
+ message: "accepts[i].outputSchema.output must be an object",
1853
+ severity: "warning",
1854
+ fix: "Add an output object describing the API response format"
1855
+ });
1856
+ }
1857
+ return issues;
1858
+ }
1859
+ /**
1860
+ * Emit a warning when neither `extensions.bazaar` nor any `accepts[].outputSchema` is present.
1861
+ *
1862
+ * @returns Single-element array with MISSING_INPUT_SCHEMA warning, or empty array
1863
+ */
1864
+ function validateMissingSchema(config, parsed) {
1865
+ if (config.extensions && config.extensions["bazaar"] !== void 0) return [];
1866
+ const accepts = parsed["accepts"];
1867
+ if (Array.isArray(accepts)) {
1868
+ for (const entry of accepts) if (isObject(entry) && entry["outputSchema"] !== void 0) return [];
1869
+ }
1870
+ return [{
1871
+ code: ErrorCode.MISSING_INPUT_SCHEMA,
1872
+ field: "extensions",
1873
+ message: ErrorMessages.MISSING_INPUT_SCHEMA,
1874
+ severity: "warning",
1875
+ fix: "Add extensions.bazaar with info and schema to help agents discover your API -- see https://bazaar.x402.org"
1876
+ }];
1877
+ }
1878
+
1727
1879
  //#endregion
1728
1880
  //#region src/validation/orchestrator.ts
1729
1881
  /**
@@ -1808,6 +1960,9 @@ function runPipeline(input, options) {
1808
1960
  else warnings.push(issue);
1809
1961
  }
1810
1962
  warnings.push(...validateLegacy(normalized, format, parsed));
1963
+ warnings.push(...validateBazaar(normalized));
1964
+ warnings.push(...validateOutputSchema(parsed));
1965
+ warnings.push(...validateMissingSchema(normalized, parsed));
1811
1966
  if (options?.strict === true) {
1812
1967
  for (const warning of warnings) errors.push({
1813
1968
  ...warning,
@@ -1916,9 +2071,68 @@ function extractConfig(response) {
1916
2071
  };
1917
2072
  }
1918
2073
 
2074
+ //#endregion
2075
+ //#region src/check.ts
2076
+ /**
2077
+ * Check an HTTP 402 response: extract config, validate, and enrich with registry data.
2078
+ *
2079
+ * Never throws. All failures are represented in the returned CheckResult.
2080
+ *
2081
+ * @param response - Response-like object with body and/or headers
2082
+ * @param options - Validation options (e.g. strict mode)
2083
+ * @returns Unified check result
2084
+ */
2085
+ function check(response, options) {
2086
+ const extraction = extractConfig(response);
2087
+ if (!extraction.config) return {
2088
+ extracted: false,
2089
+ source: null,
2090
+ extractionError: extraction.error,
2091
+ valid: false,
2092
+ version: "unknown",
2093
+ errors: [],
2094
+ warnings: [],
2095
+ normalized: null,
2096
+ summary: [],
2097
+ raw: null
2098
+ };
2099
+ const validation = validate(extraction.config, options);
2100
+ const summary = [];
2101
+ const accepts = validation.normalized?.accepts ?? [];
2102
+ for (let i = 0; i < accepts.length; i++) {
2103
+ const entry = accepts[i];
2104
+ const networkInfo = getNetworkInfo(entry.network);
2105
+ const assetInfo = getAssetInfo(entry.network, entry.asset);
2106
+ summary.push({
2107
+ index: i,
2108
+ network: entry.network,
2109
+ networkName: networkInfo?.name ?? entry.network,
2110
+ networkType: networkInfo?.type ?? null,
2111
+ payTo: entry.payTo,
2112
+ amount: entry.amount,
2113
+ asset: entry.asset,
2114
+ assetSymbol: assetInfo?.symbol ?? null,
2115
+ assetDecimals: assetInfo?.decimals ?? null,
2116
+ scheme: entry.scheme
2117
+ });
2118
+ }
2119
+ return {
2120
+ extracted: true,
2121
+ source: extraction.source,
2122
+ extractionError: null,
2123
+ valid: validation.valid,
2124
+ version: validation.version,
2125
+ errors: validation.errors,
2126
+ warnings: validation.warnings,
2127
+ normalized: validation.normalized,
2128
+ summary,
2129
+ raw: extraction.config
2130
+ };
2131
+ }
2132
+
1919
2133
  //#endregion
1920
2134
  //#region src/index.ts
1921
- const VERSION = "0.1.0";
2135
+ const VERSION = "0.3.0";
1922
2136
 
1923
2137
  //#endregion
1924
2138
  exports.CAIP2_REGEX = CAIP2_REGEX;
@@ -1928,6 +2142,7 @@ exports.KNOWN_ASSETS = KNOWN_ASSETS;
1928
2142
  exports.KNOWN_NETWORKS = KNOWN_NETWORKS;
1929
2143
  exports.SIMPLE_NAME_TO_CAIP2 = SIMPLE_NAME_TO_CAIP2;
1930
2144
  exports.VERSION = VERSION;
2145
+ exports.check = check;
1931
2146
  exports.decodeBase58 = decodeBase58;
1932
2147
  exports.detect = detect;
1933
2148
  exports.extractConfig = extractConfig;