@ucptools/validator 1.0.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.
Files changed (121) hide show
  1. package/CLAUDE.md +109 -0
  2. package/CONTRIBUTING.md +113 -0
  3. package/LICENSE +21 -0
  4. package/README.md +203 -0
  5. package/api/analyze-feed.js +140 -0
  6. package/api/badge.js +185 -0
  7. package/api/benchmark.js +177 -0
  8. package/api/directory-stats.ts +29 -0
  9. package/api/directory.ts +73 -0
  10. package/api/generate-compliance.js +143 -0
  11. package/api/generate-schema.js +457 -0
  12. package/api/generate.js +132 -0
  13. package/api/security-scan.js +133 -0
  14. package/api/simulate.js +187 -0
  15. package/api/tsconfig.json +10 -0
  16. package/api/validate.js +1351 -0
  17. package/apify-actor/.actor/actor.json +68 -0
  18. package/apify-actor/.actor/input_schema.json +32 -0
  19. package/apify-actor/APIFY-STORE-LISTING.md +412 -0
  20. package/apify-actor/Dockerfile +8 -0
  21. package/apify-actor/README.md +166 -0
  22. package/apify-actor/main.ts +111 -0
  23. package/apify-actor/package.json +17 -0
  24. package/apify-actor/src/main.js +199 -0
  25. package/docs/BRAND-IDENTITY.md +238 -0
  26. package/docs/BRAND-STYLE-GUIDE.md +356 -0
  27. package/drizzle/0000_black_king_cobra.sql +39 -0
  28. package/drizzle/meta/0000_snapshot.json +309 -0
  29. package/drizzle/meta/_journal.json +13 -0
  30. package/drizzle.config.ts +10 -0
  31. package/examples/full-profile.json +70 -0
  32. package/examples/minimal-profile.json +23 -0
  33. package/package.json +69 -0
  34. package/public/.well-known/ucp +25 -0
  35. package/public/android-chrome-192x192.png +0 -0
  36. package/public/android-chrome-512x512.png +0 -0
  37. package/public/apple-touch-icon.png +0 -0
  38. package/public/brand.css +321 -0
  39. package/public/directory.html +701 -0
  40. package/public/favicon-16x16.png +0 -0
  41. package/public/favicon-32x32.png +0 -0
  42. package/public/favicon.ico +0 -0
  43. package/public/guides/bigcommerce.html +743 -0
  44. package/public/guides/fastucp.html +838 -0
  45. package/public/guides/magento.html +779 -0
  46. package/public/guides/shopify.html +726 -0
  47. package/public/guides/squarespace.html +749 -0
  48. package/public/guides/wix.html +747 -0
  49. package/public/guides/woocommerce.html +733 -0
  50. package/public/index.html +3835 -0
  51. package/public/learn.html +396 -0
  52. package/public/logo.jpeg +0 -0
  53. package/public/og-image-icon.png +0 -0
  54. package/public/og-image.png +0 -0
  55. package/public/robots.txt +6 -0
  56. package/public/site.webmanifest +31 -0
  57. package/public/sitemap.xml +69 -0
  58. package/public/social/linkedin-banner-1128x191.png +0 -0
  59. package/public/social/temp.PNG +0 -0
  60. package/public/social/x-header-1500x500.png +0 -0
  61. package/public/verify.html +410 -0
  62. package/scripts/generate-favicons.js +44 -0
  63. package/scripts/generate-ico.js +23 -0
  64. package/scripts/generate-og-image.js +45 -0
  65. package/scripts/reset-db.ts +77 -0
  66. package/scripts/seed-db.ts +71 -0
  67. package/scripts/setup-benchmark-db.js +70 -0
  68. package/src/api/server.ts +266 -0
  69. package/src/cli/index.ts +302 -0
  70. package/src/compliance/compliance-generator.ts +452 -0
  71. package/src/compliance/index.ts +28 -0
  72. package/src/compliance/templates.ts +338 -0
  73. package/src/compliance/types.ts +170 -0
  74. package/src/db/index.ts +28 -0
  75. package/src/db/schema.ts +84 -0
  76. package/src/feed-analyzer/feed-analyzer.ts +726 -0
  77. package/src/feed-analyzer/index.ts +34 -0
  78. package/src/feed-analyzer/types.ts +354 -0
  79. package/src/generator/index.ts +7 -0
  80. package/src/generator/key-generator.ts +124 -0
  81. package/src/generator/profile-builder.ts +402 -0
  82. package/src/hosting/artifacts-generator.ts +679 -0
  83. package/src/hosting/index.ts +6 -0
  84. package/src/index.ts +105 -0
  85. package/src/security/index.ts +15 -0
  86. package/src/security/security-scanner.ts +604 -0
  87. package/src/security/types.ts +55 -0
  88. package/src/services/directory.ts +434 -0
  89. package/src/simulator/agent-simulator.ts +941 -0
  90. package/src/simulator/index.ts +7 -0
  91. package/src/simulator/types.ts +170 -0
  92. package/src/types/generator.ts +140 -0
  93. package/src/types/index.ts +7 -0
  94. package/src/types/ucp-profile.ts +140 -0
  95. package/src/types/validation.ts +89 -0
  96. package/src/validator/index.ts +194 -0
  97. package/src/validator/network-validator.ts +417 -0
  98. package/src/validator/rules-validator.ts +297 -0
  99. package/src/validator/sdk-validator.ts +330 -0
  100. package/src/validator/structural-validator.ts +476 -0
  101. package/tests/fixtures/non-compliant-profile.json +25 -0
  102. package/tests/fixtures/official-sample-profile.json +75 -0
  103. package/tests/integration/benchmark.test.ts +207 -0
  104. package/tests/integration/database.test.ts +163 -0
  105. package/tests/integration/directory-api.test.ts +268 -0
  106. package/tests/integration/simulate-api.test.ts +230 -0
  107. package/tests/integration/validate-api.test.ts +269 -0
  108. package/tests/setup.ts +15 -0
  109. package/tests/unit/agent-simulator.test.ts +575 -0
  110. package/tests/unit/compliance-generator.test.ts +374 -0
  111. package/tests/unit/directory-service.test.ts +272 -0
  112. package/tests/unit/feed-analyzer.test.ts +517 -0
  113. package/tests/unit/lint-suggestions.test.ts +423 -0
  114. package/tests/unit/official-samples.test.ts +211 -0
  115. package/tests/unit/pdf-report.test.ts +390 -0
  116. package/tests/unit/sdk-validator.test.ts +531 -0
  117. package/tests/unit/security-scanner.test.ts +410 -0
  118. package/tests/unit/validation.test.ts +390 -0
  119. package/tsconfig.json +20 -0
  120. package/vercel.json +34 -0
  121. package/vitest.config.ts +22 -0
package/CLAUDE.md ADDED
@@ -0,0 +1,109 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ UCP Profile Manager is a toolkit for validating and generating UCP (Universal Commerce Protocol) Business Profiles - an open standard enabling AI agents to discover, browse, and complete purchases on UCP-enabled merchants. The project includes a core library, REST API, CLI tools, web UI, and Apify actor integration.
8
+
9
+ **Live deployment:** https://ucptools.dev
10
+
11
+ ## Commands
12
+
13
+ ```bash
14
+ # Development
15
+ npm run dev # Watch mode Express server (tsx watch src/api/server.ts)
16
+ npm run build # TypeScript compilation
17
+ npm start # Production server (node dist/api/server.js)
18
+
19
+ # Testing
20
+ npm test # Vitest tests (30s timeout, v8 coverage)
21
+
22
+ # Linting
23
+ npm run lint # ESLint on src/**/*.ts
24
+
25
+ # CLI tools
26
+ npm run validate # Run validator CLI (tsx src/cli/index.ts)
27
+ npm run generate # Run generator CLI (tsx src/cli/generate.ts)
28
+
29
+ # Database (Drizzle + PostgreSQL)
30
+ npm run db:generate # Generate Drizzle schema
31
+ npm run db:migrate # Apply migrations
32
+ npm run db:push # Push schema to DB
33
+ npm run db:studio # Open Drizzle Studio
34
+ ```
35
+
36
+ ## Architecture
37
+
38
+ ### Core Library (`/src/`)
39
+
40
+ **Validator (`/src/validator/`)** - Four validation levels:
41
+ - `structural-validator.ts` - JSON structure, required fields, version format (YYYY-MM-DD)
42
+ - `rules-validator.ts` - UCP compliance (namespace/origin binding, extension chains, HTTPS endpoints, signing keys)
43
+ - `network-validator.ts` - Remote schema fetching/verification, self-describing schema validation
44
+ - `sdk-validator.ts` - Integration with @ucp-js/sdk for official UCP compliance
45
+ - `index.ts` - Orchestrator exposing `validateProfile()`, `validateRemote()`, `validateQuick()`, `validateJsonString()`
46
+
47
+ **Generator (`/src/generator/`)** - Profile generation:
48
+ - `profile-builder.ts` - `buildProfile()` for full profiles, `generateMinimalProfile()` for checkout-only
49
+ - `key-generator.ts` - Ed25519/ES256 signing key generation (`generateSigningKeyPair()`)
50
+
51
+ **Simulator (`/src/simulator/`)** - AI agent interaction simulation:
52
+ - `agent-simulator.ts` - Tests real-world functionality: discovery flow, capability inspection, checkout simulation
53
+ - Not just spec compliance - simulates actual agent workflows
54
+
55
+ **Hosting (`/src/hosting/`)** - Platform-specific deployment configs:
56
+ - `artifacts-generator.ts` - Generates installation artifacts for Nginx, Apache, Vercel, Netlify, Cloudflare Workers, S3+CloudFront
57
+
58
+ ### API & Deployment
59
+
60
+ **Express API (`/src/api/server.ts`)** - REST endpoints:
61
+ - `POST /v1/profiles/validate`, `/validate-quick`, `/validate-remote`, `/validate-json`
62
+ - `POST /v1/profiles/generate`, `/generate-minimal`
63
+ - `POST /v1/hosting/artifacts`
64
+
65
+ **Vercel Serverless (`/api/`)** - Edge functions for ucptools.dev
66
+
67
+ **Database (`/src/db/`)** - Drizzle ORM with PostgreSQL (Neon):
68
+ - Schema: merchants (directory), benchmarkStats, benchmarkSummary
69
+ - Service: `/src/services/directory.ts` - merchant CRUD, filtering, stats
70
+
71
+ ### Types (`/src/types/`)
72
+ - `ucp-profile.ts` - UCP specification types
73
+ - `validation.ts` - ValidationReport, ValidationIssue interfaces
74
+ - `generator.ts` - Generator input/output types
75
+
76
+ ## Key Patterns
77
+
78
+ **Validation Issue Structure:**
79
+ ```typescript
80
+ {
81
+ severity: 'error' | 'warn' | 'info',
82
+ code: string, // e.g., 'UCP_NS_ORIGIN_MISMATCH'
83
+ path: string, // JSON path, e.g., '$.ucp.capabilities[0]'
84
+ message: string,
85
+ hint?: string // Fix suggestion
86
+ }
87
+ ```
88
+
89
+ **Error Codes:** `UCP_MISSING_ROOT`, `UCP_MISSING_VERSION`, `UCP_INVALID_VERSION_FORMAT`, `UCP_NS_ORIGIN_MISMATCH`, `UCP_ORPHANED_EXTENSION`, `UCP_ENDPOINT_NOT_HTTPS`, `UCP_ENDPOINT_TRAILING_SLASH`, `UCP_MISSING_SIGNING_KEYS`, `UCP_SCHEMA_FETCH_FAILED`
90
+
91
+ ## Environment Variables
92
+
93
+ ```
94
+ DATABASE_URL # PostgreSQL connection string (Neon)
95
+ NODE_ENV # development | production
96
+ PORT # API port (default: 3000)
97
+ LOG_LEVEL # Pino log level (default: info)
98
+ ```
99
+
100
+ ## Tech Stack
101
+
102
+ - **Runtime:** Node.js 20+, TypeScript 5.6, ES2022 target
103
+ - **API:** Express 4.21
104
+ - **Database:** PostgreSQL via @neondatabase/serverless, Drizzle ORM
105
+ - **Validation:** AJV 8.17 (JSON Schema), Zod 3.23, @ucp-js/sdk 0.1
106
+ - **Crypto:** jose (JWT/JWK), Ed25519 signing
107
+ - **CLI:** Commander 12, Chalk 5
108
+ - **Testing:** Vitest
109
+ - **Deployment:** Vercel
@@ -0,0 +1,113 @@
1
+ # Contributing to @ucptools/validator
2
+
3
+ Thank you for your interest in contributing to the UCP Validator! This document provides guidelines and instructions for contributing.
4
+
5
+ ## Code of Conduct
6
+
7
+ By participating in this project, you agree to maintain a respectful and inclusive environment for everyone.
8
+
9
+ ## How to Contribute
10
+
11
+ ### Reporting Bugs
12
+
13
+ 1. Check if the bug has already been reported in [Issues](https://github.com/Nolpak14/ucp-tools/issues)
14
+ 2. If not, create a new issue with:
15
+ - A clear, descriptive title
16
+ - Steps to reproduce the issue
17
+ - Expected vs actual behavior
18
+ - Your environment (Node.js version, OS)
19
+ - Sample UCP profile if applicable
20
+
21
+ ### Suggesting Features
22
+
23
+ 1. Check existing issues for similar suggestions
24
+ 2. Create a new issue with the `enhancement` label
25
+ 3. Describe the feature and its use case
26
+ 4. Explain how it benefits UCP profile validation/generation
27
+
28
+ ### Pull Requests
29
+
30
+ 1. Fork the repository
31
+ 2. Create a feature branch: `git checkout -b feature/your-feature-name`
32
+ 3. Make your changes
33
+ 4. Run tests: `npm test`
34
+ 5. Run linting: `npm run lint`
35
+ 6. Commit with a clear message describing your changes
36
+ 7. Push to your fork and submit a pull request
37
+
38
+ ## Development Setup
39
+
40
+ ```bash
41
+ # Clone your fork
42
+ git clone https://github.com/YOUR_USERNAME/ucp-tools.git
43
+ cd ucp-tools
44
+
45
+ # Install dependencies
46
+ npm install
47
+
48
+ # Run tests
49
+ npm test
50
+
51
+ # Run in development mode
52
+ npm run dev
53
+ ```
54
+
55
+ ## Project Structure
56
+
57
+ ```
58
+ src/
59
+ types/ # TypeScript type definitions
60
+ validator/ # Validation logic (structural, rules, network, SDK)
61
+ generator/ # Profile and key generation
62
+ simulator/ # AI agent simulation
63
+ hosting/ # Deployment artifact generation
64
+ api/ # Express REST API
65
+ cli/ # Command-line tools
66
+ db/ # Database schema and services
67
+ examples/ # Sample UCP profiles
68
+ ```
69
+
70
+ ## Coding Standards
71
+
72
+ - Use TypeScript for all new code
73
+ - Follow existing code style (enforced by ESLint)
74
+ - Add JSDoc comments for public APIs
75
+ - Write tests for new functionality
76
+ - Keep functions focused and single-purpose
77
+
78
+ ## Testing
79
+
80
+ ```bash
81
+ # Run all tests
82
+ npm test
83
+
84
+ # Run tests in watch mode
85
+ npm test -- --watch
86
+
87
+ # Run specific test file
88
+ npm test -- src/validator/structural-validator.test.ts
89
+ ```
90
+
91
+ ## Validation Error Codes
92
+
93
+ When adding new validation rules, follow the existing pattern:
94
+
95
+ ```typescript
96
+ {
97
+ severity: 'error' | 'warn' | 'info',
98
+ code: 'UCP_YOUR_ERROR_CODE', // Prefix with UCP_
99
+ path: '$.ucp.path.to.issue', // JSON path format
100
+ message: 'Clear description of the issue',
101
+ hint: 'Suggestion to fix the issue' // Optional
102
+ }
103
+ ```
104
+
105
+ ## Questions?
106
+
107
+ - Open an issue for general questions
108
+ - Check [ucptools.dev](https://ucptools.dev) for documentation
109
+ - Review the [UCP Specification](https://ucp.dev/specification/overview/)
110
+
111
+ ## License
112
+
113
+ By contributing, you agree that your contributions will be licensed under the MIT License.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 UCP.tools
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,203 @@
1
+ # @ucptools/validator
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@ucptools/validator)](https://www.npmjs.com/package/@ucptools/validator)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ **Validate and generate UCP (Universal Commerce Protocol) Business Profiles** for AI-powered shopping agents like ChatGPT, Google AI Mode, and Copilot checkout.
7
+
8
+ > **Try it online:** [ucptools.dev](https://ucptools.dev) - Free AI Commerce Readiness Checker
9
+
10
+ ---
11
+
12
+ ## What is UCP?
13
+
14
+ The [Universal Commerce Protocol](https://ucp.dev) is an open standard enabling AI agents to discover, browse, and complete purchases on any UCP-enabled merchant. Google announced UCP on January 11, 2026, with support from Shopify, Target, Walmart, and 20+ ecosystem partners.
15
+
16
+ This library helps you:
17
+ - **Validate** your UCP profile for compliance
18
+ - **Generate** properly formatted UCP profiles
19
+ - **Verify** schemas and capability declarations
20
+
21
+ ---
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install @ucptools/validator
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Quick Start
32
+
33
+ ### Validate a Profile
34
+
35
+ ```typescript
36
+ import { validateProfile, validateQuick, validateRemote } from '@ucptools/validator';
37
+
38
+ // Validate a local profile object
39
+ const report = await validateProfile(myProfile);
40
+ console.log(report.ok ? 'Valid!' : 'Issues found:', report.issues);
41
+
42
+ // Quick validation (no network calls)
43
+ const quickReport = validateQuick(myProfile);
44
+
45
+ // Validate a remote profile by domain
46
+ const remoteReport = await validateRemote('example.com');
47
+ ```
48
+
49
+ ### Generate a Profile
50
+
51
+ ```typescript
52
+ import { buildProfile, generateMinimalProfile } from '@ucptools/validator';
53
+
54
+ // Generate a minimal profile (checkout only)
55
+ const minimal = generateMinimalProfile({
56
+ endpoint: 'https://api.yourstore.com/ucp/v1',
57
+ });
58
+
59
+ // Generate a full profile
60
+ const result = await buildProfile({
61
+ merchant: {
62
+ merchantId: 'store-123',
63
+ primaryDomain: 'yourstore.com',
64
+ },
65
+ transport: {
66
+ rest: { endpoint: 'https://api.yourstore.com/ucp/v1' },
67
+ },
68
+ capabilities: {
69
+ checkout: true,
70
+ order: true,
71
+ fulfillment: false,
72
+ discount: false,
73
+ product: false,
74
+ inventory: false,
75
+ },
76
+ });
77
+
78
+ console.log(result.profileJson);
79
+ ```
80
+
81
+ ### Generate Signing Keys
82
+
83
+ ```typescript
84
+ import { generateSigningKeyPair } from '@ucptools/validator';
85
+
86
+ // Generate Ed25519 key pair for Order capability
87
+ const { publicKey, privateKey, kid } = await generateSigningKeyPair('Ed25519');
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Validation Levels
93
+
94
+ ### 1. Structural Validation (Fast, Offline)
95
+ - JSON structure verification
96
+ - Required fields check
97
+ - Version format validation (YYYY-MM-DD)
98
+
99
+ ### 2. UCP Rules Validation (Offline)
100
+ - Namespace/origin binding (`dev.ucp.*` must use `ucp.dev` URLs)
101
+ - Extension chain validation (no orphaned `extends`)
102
+ - Endpoint rules (HTTPS, no trailing slash)
103
+ - Signing keys requirement for Order capability
104
+
105
+ ### 3. Network Validation (Online)
106
+ - Fetch and verify remote schemas
107
+ - Self-describing schema validation
108
+ - Schema/capability version matching
109
+
110
+ ---
111
+
112
+ ## Validation Report
113
+
114
+ ```typescript
115
+ interface ValidationReport {
116
+ ok: boolean; // true if no errors
117
+ profile_url?: string; // URL of validated profile
118
+ ucp_version?: string; // UCP version from profile
119
+ issues: ValidationIssue[]; // Array of issues found
120
+ validated_at: string; // ISO timestamp
121
+ validation_mode: ValidationMode;
122
+ }
123
+
124
+ interface ValidationIssue {
125
+ severity: 'error' | 'warn' | 'info';
126
+ code: string; // e.g., 'UCP_NS_ORIGIN_MISMATCH'
127
+ path: string; // JSON path, e.g., '$.ucp.capabilities[0]'
128
+ message: string;
129
+ hint?: string; // Suggestion to fix
130
+ }
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Error Codes
136
+
137
+ | Code | Severity | Description |
138
+ |------|----------|-------------|
139
+ | `UCP_MISSING_ROOT` | error | Missing `ucp` object at root |
140
+ | `UCP_MISSING_VERSION` | error | Missing version field |
141
+ | `UCP_INVALID_VERSION_FORMAT` | error | Version not in YYYY-MM-DD format |
142
+ | `UCP_NS_ORIGIN_MISMATCH` | error | Schema URL doesn't match namespace origin |
143
+ | `UCP_ORPHANED_EXTENSION` | error | Extends references non-existent capability |
144
+ | `UCP_ENDPOINT_NOT_HTTPS` | error | Endpoint must use HTTPS |
145
+ | `UCP_ENDPOINT_TRAILING_SLASH` | warn | Remove trailing slash from endpoint |
146
+ | `UCP_MISSING_SIGNING_KEYS` | error | Order capability requires signing_keys |
147
+ | `UCP_SCHEMA_FETCH_FAILED` | warn | Could not fetch remote schema |
148
+
149
+ ---
150
+
151
+ ## CLI Usage
152
+
153
+ ```bash
154
+ # Validate a local file
155
+ npx @ucptools/validator validate -f ucp.json
156
+
157
+ # Validate a remote profile
158
+ npx @ucptools/validator validate -r yourstore.com
159
+
160
+ # Generate a minimal profile
161
+ npx @ucptools/validator generate-minimal -e https://api.example.com/ucp/v1 -o ucp.json
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Online Tool
167
+
168
+ Don't want to install anything? Use our free online tool:
169
+
170
+ **[ucptools.dev](https://ucptools.dev)** - AI Commerce Readiness Checker
171
+
172
+ - Validates UCP profiles + Schema.org requirements
173
+ - Generates UCP profiles with a simple form
174
+ - Creates Schema.org snippets (MerchantReturnPolicy, shippingDetails)
175
+ - Provides A-F grading and actionable recommendations
176
+
177
+ ---
178
+
179
+ ## Resources
180
+
181
+ - [UCP Specification](https://ucp.dev/specification/overview/)
182
+ - [UCP GitHub Repository](https://github.com/Universal-Commerce-Protocol/ucp)
183
+ - [Google UCP Business Profile Guide](https://developers.google.com/merchant/ucp/guides/business-profile)
184
+ - [UCP JavaScript SDK](https://github.com/Universal-Commerce-Protocol/js-sdk)
185
+
186
+ ---
187
+
188
+ ## Contributing
189
+
190
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details.
191
+
192
+ ---
193
+
194
+ ## License
195
+
196
+ MIT - See [LICENSE](LICENSE) for details.
197
+
198
+ ---
199
+
200
+ <p align="center">
201
+ Built with love for the AI Commerce ecosystem<br>
202
+ <a href="https://ucptools.dev">ucptools.dev</a>
203
+ </p>
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Vercel Serverless Function: Product Feed Quality Analyzer
3
+ * POST /api/analyze-feed
4
+ *
5
+ * Analyzes product feed quality for AI agent visibility.
6
+ *
7
+ * Request body:
8
+ * {
9
+ * "url": "https://example.com/products",
10
+ * "maxProducts": 50,
11
+ * "includeProductDetails": true
12
+ * }
13
+ *
14
+ * GET /api/analyze-feed?url=https://example.com/products
15
+ * Quick analysis with default options.
16
+ */
17
+
18
+ export default async function handler(req, res) {
19
+ // Handle CORS
20
+ res.setHeader('Access-Control-Allow-Origin', '*');
21
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
22
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
23
+
24
+ if (req.method === 'OPTIONS') {
25
+ return res.status(200).end();
26
+ }
27
+
28
+ // Extract URL from query (GET) or body (POST)
29
+ let url;
30
+ let maxProducts = 50;
31
+ let includeProductDetails = true;
32
+
33
+ if (req.method === 'GET') {
34
+ url = req.query.url;
35
+ if (req.query.maxProducts) {
36
+ maxProducts = parseInt(req.query.maxProducts, 10);
37
+ }
38
+ if (req.query.includeProductDetails === 'false') {
39
+ includeProductDetails = false;
40
+ }
41
+ } else if (req.method === 'POST') {
42
+ const body = req.body || {};
43
+ url = body.url;
44
+ maxProducts = body.maxProducts || 50;
45
+ includeProductDetails = body.includeProductDetails !== false;
46
+ } else {
47
+ return res.status(405).json({
48
+ error: 'Method not allowed',
49
+ message: 'Use GET or POST to analyze a product feed',
50
+ });
51
+ }
52
+
53
+ // Validate URL
54
+ if (!url) {
55
+ return res.status(400).json({
56
+ error: 'Missing URL',
57
+ message: 'Please provide a URL to analyze',
58
+ });
59
+ }
60
+
61
+ try {
62
+ new URL(url);
63
+ } catch {
64
+ return res.status(400).json({
65
+ error: 'Invalid URL',
66
+ message: 'Please provide a valid URL',
67
+ });
68
+ }
69
+
70
+ // Validate maxProducts
71
+ if (maxProducts < 1 || maxProducts > 100) {
72
+ return res.status(400).json({
73
+ error: 'Invalid maxProducts',
74
+ message: 'maxProducts must be between 1 and 100',
75
+ });
76
+ }
77
+
78
+ try {
79
+ // Fetch the page content
80
+ const controller = new AbortController();
81
+ const timeoutId = setTimeout(() => controller.abort(), 30000);
82
+
83
+ const response = await fetch(url, {
84
+ headers: {
85
+ 'User-Agent': 'UCP-Tools Feed Analyzer/1.0 (https://ucp.day)',
86
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
87
+ },
88
+ signal: controller.signal,
89
+ });
90
+
91
+ clearTimeout(timeoutId);
92
+
93
+ if (!response.ok) {
94
+ return res.status(400).json({
95
+ error: 'Failed to fetch URL',
96
+ message: `Server returned ${response.status}: ${response.statusText}`,
97
+ });
98
+ }
99
+
100
+ const html = await response.text();
101
+
102
+ // Import and run the analyzer
103
+ const { analyzeProductFeedFromHtml } = await import('../src/feed-analyzer/index.js');
104
+
105
+ const result = analyzeProductFeedFromHtml(html, url, {
106
+ maxProducts,
107
+ includeProductDetails,
108
+ });
109
+
110
+ // Check if any products were found
111
+ if (result.productsFound === 0) {
112
+ return res.status(200).json({
113
+ success: true,
114
+ warning: 'No products found',
115
+ message: 'No Schema.org Product markup was found on this page. Make sure your page includes JSON-LD structured data with @type: "Product".',
116
+ ...result,
117
+ });
118
+ }
119
+
120
+ return res.status(200).json({
121
+ success: true,
122
+ ...result,
123
+ });
124
+
125
+ } catch (error) {
126
+ console.error('Feed analysis error:', error);
127
+
128
+ if (error.name === 'AbortError') {
129
+ return res.status(408).json({
130
+ error: 'Request timeout',
131
+ message: 'The request took too long. The target server may be slow or unresponsive.',
132
+ });
133
+ }
134
+
135
+ return res.status(500).json({
136
+ error: 'Analysis failed',
137
+ message: error.message || 'An unexpected error occurred',
138
+ });
139
+ }
140
+ }