@ucptools/validator 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/config.d.ts +20 -0
- package/dist/auth/config.d.ts.map +1 -0
- package/dist/auth/config.js +114 -0
- package/dist/auth/config.js.map +1 -0
- package/dist/auth/index.d.ts +5 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +17 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/middleware.d.ts +45 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +170 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/service.d.ts +80 -0
- package/dist/auth/service.d.ts.map +1 -0
- package/dist/auth/service.js +298 -0
- package/dist/auth/service.js.map +1 -0
- package/dist/cli/index.d.ts +6 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +375 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/mock-server.d.ts +20 -0
- package/dist/cli/mock-server.d.ts.map +1 -0
- package/dist/cli/mock-server.js +261 -0
- package/dist/cli/mock-server.js.map +1 -0
- package/dist/compliance/compliance-generator.d.ts +34 -0
- package/dist/compliance/compliance-generator.d.ts.map +1 -0
- package/dist/compliance/compliance-generator.js +320 -0
- package/dist/compliance/compliance-generator.js.map +1 -0
- package/dist/compliance/index.d.ts +8 -0
- package/dist/compliance/index.d.ts.map +1 -0
- package/dist/compliance/index.js +17 -0
- package/dist/compliance/index.js.map +1 -0
- package/dist/compliance/templates.d.ts +34 -0
- package/dist/compliance/templates.d.ts.map +1 -0
- package/{src/compliance/templates.ts → dist/compliance/templates.js} +117 -155
- package/dist/compliance/templates.js.map +1 -0
- package/dist/compliance/types.d.ts +64 -0
- package/dist/compliance/types.d.ts.map +1 -0
- package/dist/compliance/types.js +64 -0
- package/dist/compliance/types.js.map +1 -0
- package/dist/db/index.d.ts +17 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +80 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +3886 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +425 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/utils.d.ts +252 -0
- package/dist/db/utils.d.ts.map +1 -0
- package/dist/db/utils.js +295 -0
- package/dist/db/utils.js.map +1 -0
- package/dist/feed-analyzer/feed-analyzer.d.ts +26 -0
- package/dist/feed-analyzer/feed-analyzer.d.ts.map +1 -0
- package/{src/feed-analyzer/feed-analyzer.ts → dist/feed-analyzer/feed-analyzer.js} +856 -726
- package/dist/feed-analyzer/feed-analyzer.js.map +1 -0
- package/dist/feed-analyzer/index.d.ts +8 -0
- package/dist/feed-analyzer/index.d.ts.map +1 -0
- package/dist/feed-analyzer/index.js +19 -0
- package/dist/feed-analyzer/index.js.map +1 -0
- package/dist/feed-analyzer/types.d.ts +285 -0
- package/dist/feed-analyzer/types.d.ts.map +1 -0
- package/dist/feed-analyzer/types.js +175 -0
- package/dist/feed-analyzer/types.js.map +1 -0
- package/{src/generator/index.ts → dist/generator/index.d.ts} +1 -1
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +13 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/key-generator.d.ts +24 -0
- package/dist/generator/key-generator.d.ts.map +1 -0
- package/dist/generator/key-generator.js +144 -0
- package/dist/generator/key-generator.js.map +1 -0
- package/dist/generator/profile-builder.d.ts +15 -0
- package/dist/generator/profile-builder.d.ts.map +1 -0
- package/dist/generator/profile-builder.js +338 -0
- package/dist/generator/profile-builder.js.map +1 -0
- package/dist/hosting/artifacts-generator.d.ts +10 -0
- package/dist/hosting/artifacts-generator.d.ts.map +1 -0
- package/{src/hosting/artifacts-generator.ts → dist/hosting/artifacts-generator.js} +191 -241
- package/dist/hosting/artifacts-generator.js.map +1 -0
- package/{src/hosting/index.ts → dist/hosting/index.d.ts} +1 -1
- package/dist/hosting/index.d.ts.map +1 -0
- package/dist/hosting/index.js +10 -0
- package/dist/hosting/index.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/analytics.d.ts +337 -0
- package/dist/lib/analytics.d.ts.map +1 -0
- package/dist/lib/analytics.js +188 -0
- package/dist/lib/analytics.js.map +1 -0
- package/{src/security/index.ts → dist/security/index.d.ts} +8 -15
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +12 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/security-scanner.d.ts +10 -0
- package/dist/security/security-scanner.d.ts.map +1 -0
- package/dist/security/security-scanner.js +669 -0
- package/dist/security/security-scanner.js.map +1 -0
- package/dist/security/types.d.ts +80 -0
- package/dist/security/types.d.ts.map +1 -0
- package/dist/security/types.js +21 -0
- package/dist/security/types.js.map +1 -0
- package/dist/services/analytics.d.ts +114 -0
- package/dist/services/analytics.d.ts.map +1 -0
- package/dist/services/analytics.js +862 -0
- package/dist/services/analytics.js.map +1 -0
- package/dist/services/badge.d.ts +31 -0
- package/dist/services/badge.d.ts.map +1 -0
- package/dist/services/badge.js +152 -0
- package/dist/services/badge.js.map +1 -0
- package/dist/services/cron.d.ts +125 -0
- package/dist/services/cron.d.ts.map +1 -0
- package/dist/services/cron.js +613 -0
- package/dist/services/cron.js.map +1 -0
- package/dist/services/directory.d.ts +106 -0
- package/dist/services/directory.d.ts.map +1 -0
- package/dist/services/directory.js +351 -0
- package/dist/services/directory.js.map +1 -0
- package/dist/services/email.d.ts +112 -0
- package/dist/services/email.d.ts.map +1 -0
- package/dist/services/email.js +772 -0
- package/dist/services/email.js.map +1 -0
- package/dist/services/hosted-profiles.d.ts +77 -0
- package/dist/services/hosted-profiles.d.ts.map +1 -0
- package/dist/services/hosted-profiles.js +433 -0
- package/dist/services/hosted-profiles.js.map +1 -0
- package/dist/services/latency.d.ts +67 -0
- package/dist/services/latency.d.ts.map +1 -0
- package/dist/services/latency.js +274 -0
- package/dist/services/latency.js.map +1 -0
- package/dist/services/manifest-compliance.d.ts +64 -0
- package/dist/services/manifest-compliance.d.ts.map +1 -0
- package/dist/services/manifest-compliance.js +271 -0
- package/dist/services/manifest-compliance.js.map +1 -0
- package/dist/services/monitoring-diff.d.ts +31 -0
- package/dist/services/monitoring-diff.d.ts.map +1 -0
- package/dist/services/monitoring-diff.js +189 -0
- package/dist/services/monitoring-diff.js.map +1 -0
- package/dist/services/notifications.d.ts +46 -0
- package/dist/services/notifications.d.ts.map +1 -0
- package/dist/services/notifications.js +88 -0
- package/dist/services/notifications.js.map +1 -0
- package/dist/services/stripe.d.ts +93 -0
- package/dist/services/stripe.d.ts.map +1 -0
- package/dist/services/stripe.js +490 -0
- package/dist/services/stripe.js.map +1 -0
- package/dist/services/validation-history.d.ts +99 -0
- package/dist/services/validation-history.d.ts.map +1 -0
- package/dist/services/validation-history.js +344 -0
- package/dist/services/validation-history.js.map +1 -0
- package/dist/services/validation-logging.d.ts +103 -0
- package/dist/services/validation-logging.d.ts.map +1 -0
- package/dist/services/validation-logging.js +210 -0
- package/dist/services/validation-logging.js.map +1 -0
- package/dist/services/validation.d.ts +119 -0
- package/dist/services/validation.d.ts.map +1 -0
- package/dist/services/validation.js +1185 -0
- package/dist/services/validation.js.map +1 -0
- package/dist/simulator/agent-simulator.d.ts +69 -0
- package/dist/simulator/agent-simulator.d.ts.map +1 -0
- package/dist/simulator/agent-simulator.js +870 -0
- package/dist/simulator/agent-simulator.js.map +1 -0
- package/{src/simulator/index.ts → dist/simulator/index.d.ts} +7 -7
- package/dist/simulator/index.d.ts.map +1 -0
- package/dist/simulator/index.js +23 -0
- package/dist/simulator/index.js.map +1 -0
- package/{src/simulator/types.ts → dist/simulator/types.d.ts} +171 -170
- package/dist/simulator/types.d.ts.map +1 -0
- package/dist/simulator/types.js +18 -0
- package/dist/simulator/types.js.map +1 -0
- package/dist/types/acp-validation.d.ts +87 -0
- package/dist/types/acp-validation.d.ts.map +1 -0
- package/dist/types/acp-validation.js +40 -0
- package/dist/types/acp-validation.js.map +1 -0
- package/dist/types/analytics.d.ts +182 -0
- package/dist/types/analytics.d.ts.map +1 -0
- package/dist/types/analytics.js +7 -0
- package/dist/types/analytics.js.map +1 -0
- package/dist/types/generator.d.ts +106 -0
- package/dist/types/generator.d.ts.map +1 -0
- package/dist/types/generator.js +6 -0
- package/dist/types/generator.js.map +1 -0
- package/{src/types/index.ts → dist/types/index.d.ts} +1 -1
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +23 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/ucp-profile.d.ts +111 -0
- package/dist/types/ucp-profile.d.ts.map +1 -0
- package/dist/types/ucp-profile.js +45 -0
- package/dist/types/ucp-profile.js.map +1 -0
- package/dist/types/validation.d.ts +76 -0
- package/dist/types/validation.d.ts.map +1 -0
- package/dist/types/validation.js +42 -0
- package/dist/types/validation.js.map +1 -0
- package/dist/validator/acp/index.d.ts +31 -0
- package/dist/validator/acp/index.d.ts.map +1 -0
- package/dist/validator/acp/index.js +574 -0
- package/dist/validator/acp/index.js.map +1 -0
- package/dist/validator/index.d.ts +26 -0
- package/dist/validator/index.d.ts.map +1 -0
- package/dist/validator/index.js +161 -0
- package/dist/validator/index.js.map +1 -0
- package/dist/validator/network-validator.d.ts +28 -0
- package/dist/validator/network-validator.d.ts.map +1 -0
- package/dist/validator/network-validator.js +319 -0
- package/dist/validator/network-validator.js.map +1 -0
- package/dist/validator/rules-validator.d.ts +19 -0
- package/dist/validator/rules-validator.d.ts.map +1 -0
- package/dist/validator/rules-validator.js +306 -0
- package/dist/validator/rules-validator.js.map +1 -0
- package/dist/validator/sdk-validator.d.ts +58 -0
- package/dist/validator/sdk-validator.d.ts.map +1 -0
- package/{src/validator/sdk-validator.ts → dist/validator/sdk-validator.js} +273 -330
- package/dist/validator/sdk-validator.js.map +1 -0
- package/dist/validator/structural-validator.d.ts +11 -0
- package/dist/validator/structural-validator.d.ts.map +1 -0
- package/dist/validator/structural-validator.js +549 -0
- package/dist/validator/structural-validator.js.map +1 -0
- package/dist/validator/utils.d.ts +51 -0
- package/dist/validator/utils.d.ts.map +1 -0
- package/dist/validator/utils.js +132 -0
- package/dist/validator/utils.js.map +1 -0
- package/package.json +44 -12
- package/CLAUDE.md +0 -109
- package/api/analyze-feed.js +0 -140
- package/api/badge.js +0 -185
- package/api/benchmark.js +0 -177
- package/api/directory-stats.ts +0 -29
- package/api/directory.ts +0 -73
- package/api/generate-compliance.js +0 -143
- package/api/generate-schema.js +0 -457
- package/api/generate.js +0 -132
- package/api/security-scan.js +0 -133
- package/api/simulate.js +0 -187
- package/api/tsconfig.json +0 -10
- package/api/validate.js +0 -1351
- package/apify-actor/.actor/actor.json +0 -68
- package/apify-actor/.actor/input_schema.json +0 -32
- package/apify-actor/APIFY-STORE-LISTING.md +0 -412
- package/apify-actor/Dockerfile +0 -8
- package/apify-actor/README.md +0 -166
- package/apify-actor/main.ts +0 -111
- package/apify-actor/package.json +0 -17
- package/apify-actor/src/main.js +0 -199
- package/docs/BRAND-IDENTITY.md +0 -238
- package/docs/BRAND-STYLE-GUIDE.md +0 -356
- package/drizzle/0000_black_king_cobra.sql +0 -39
- package/drizzle/meta/0000_snapshot.json +0 -309
- package/drizzle/meta/_journal.json +0 -13
- package/drizzle.config.ts +0 -10
- package/public/.well-known/ucp +0 -25
- package/public/android-chrome-192x192.png +0 -0
- package/public/android-chrome-512x512.png +0 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/brand.css +0 -321
- package/public/directory.html +0 -701
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/guides/bigcommerce.html +0 -743
- package/public/guides/fastucp.html +0 -838
- package/public/guides/magento.html +0 -779
- package/public/guides/shopify.html +0 -726
- package/public/guides/squarespace.html +0 -749
- package/public/guides/wix.html +0 -747
- package/public/guides/woocommerce.html +0 -733
- package/public/index.html +0 -3835
- package/public/learn.html +0 -396
- package/public/logo.jpeg +0 -0
- package/public/og-image-icon.png +0 -0
- package/public/og-image.png +0 -0
- package/public/robots.txt +0 -6
- package/public/site.webmanifest +0 -31
- package/public/sitemap.xml +0 -69
- package/public/social/linkedin-banner-1128x191.png +0 -0
- package/public/social/temp.PNG +0 -0
- package/public/social/x-header-1500x500.png +0 -0
- package/public/verify.html +0 -410
- package/scripts/generate-favicons.js +0 -44
- package/scripts/generate-ico.js +0 -23
- package/scripts/generate-og-image.js +0 -45
- package/scripts/reset-db.ts +0 -77
- package/scripts/seed-db.ts +0 -71
- package/scripts/setup-benchmark-db.js +0 -70
- package/src/api/server.ts +0 -266
- package/src/cli/index.ts +0 -302
- package/src/compliance/compliance-generator.ts +0 -452
- package/src/compliance/index.ts +0 -28
- package/src/compliance/types.ts +0 -170
- package/src/db/index.ts +0 -28
- package/src/db/schema.ts +0 -84
- package/src/feed-analyzer/index.ts +0 -34
- package/src/feed-analyzer/types.ts +0 -354
- package/src/generator/key-generator.ts +0 -124
- package/src/generator/profile-builder.ts +0 -402
- package/src/index.ts +0 -105
- package/src/security/security-scanner.ts +0 -604
- package/src/security/types.ts +0 -55
- package/src/services/directory.ts +0 -434
- package/src/simulator/agent-simulator.ts +0 -941
- package/src/types/generator.ts +0 -140
- package/src/types/ucp-profile.ts +0 -140
- package/src/types/validation.ts +0 -89
- package/src/validator/index.ts +0 -194
- package/src/validator/network-validator.ts +0 -417
- package/src/validator/rules-validator.ts +0 -297
- package/src/validator/structural-validator.ts +0 -476
- package/tests/fixtures/non-compliant-profile.json +0 -25
- package/tests/fixtures/official-sample-profile.json +0 -75
- package/tests/integration/benchmark.test.ts +0 -207
- package/tests/integration/database.test.ts +0 -163
- package/tests/integration/directory-api.test.ts +0 -268
- package/tests/integration/simulate-api.test.ts +0 -230
- package/tests/integration/validate-api.test.ts +0 -269
- package/tests/setup.ts +0 -15
- package/tests/unit/agent-simulator.test.ts +0 -575
- package/tests/unit/compliance-generator.test.ts +0 -374
- package/tests/unit/directory-service.test.ts +0 -272
- package/tests/unit/feed-analyzer.test.ts +0 -517
- package/tests/unit/lint-suggestions.test.ts +0 -423
- package/tests/unit/official-samples.test.ts +0 -211
- package/tests/unit/pdf-report.test.ts +0 -390
- package/tests/unit/sdk-validator.test.ts +0 -531
- package/tests/unit/security-scanner.test.ts +0 -410
- package/tests/unit/validation.test.ts +0 -390
- package/tsconfig.json +0 -20
- package/vercel.json +0 -34
- package/vitest.config.ts +0 -22
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stripe Service
|
|
4
|
+
* Handles all Stripe-related operations including:
|
|
5
|
+
* - Checkout session creation
|
|
6
|
+
* - Subscription management
|
|
7
|
+
* - Customer portal
|
|
8
|
+
* - Webhook events
|
|
9
|
+
* Production deployment ready
|
|
10
|
+
*/
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.STRIPE_PRICE_IDS = exports.stripe = void 0;
|
|
16
|
+
exports.getStripe = getStripe;
|
|
17
|
+
exports.priceIdToTier = priceIdToTier;
|
|
18
|
+
exports.createCheckoutSession = createCheckoutSession;
|
|
19
|
+
exports.createCustomerPortalSession = createCustomerPortalSession;
|
|
20
|
+
exports.startTrialWithoutPayment = startTrialWithoutPayment;
|
|
21
|
+
exports.handleWebhookEvent = handleWebhookEvent;
|
|
22
|
+
exports.verifyWebhookSignature = verifyWebhookSignature;
|
|
23
|
+
exports.getSubscriptionDetails = getSubscriptionDetails;
|
|
24
|
+
exports.cancelSubscription = cancelSubscription;
|
|
25
|
+
exports.resumeSubscription = resumeSubscription;
|
|
26
|
+
exports.updateSubscription = updateSubscription;
|
|
27
|
+
const stripe_1 = __importDefault(require("stripe"));
|
|
28
|
+
const index_js_1 = require("../db/index.js");
|
|
29
|
+
const utils_js_1 = require("../db/utils.js");
|
|
30
|
+
const email_js_1 = require("./email.js");
|
|
31
|
+
const notifications_js_1 = require("./notifications.js");
|
|
32
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
33
|
+
// Initialize Stripe lazily to avoid crashing on startup
|
|
34
|
+
// Use test keys in development, production keys in production
|
|
35
|
+
const isProduction = process.env.NODE_ENV === 'production';
|
|
36
|
+
const stripeSecretKey = isProduction
|
|
37
|
+
? process.env.STRIPE_SECRET_KEY
|
|
38
|
+
: (process.env.STRIPE_TEST_SECRET_KEY || process.env.STRIPE_SECRET_KEY);
|
|
39
|
+
// Log Stripe mode on startup
|
|
40
|
+
console.log(`[Stripe] Mode: ${isProduction ? 'PRODUCTION' : 'TEST'}`);
|
|
41
|
+
console.log(`[Stripe] Secret key present: ${!!stripeSecretKey}`);
|
|
42
|
+
console.log(`[Stripe] Key starts with: ${stripeSecretKey?.substring(0, 7) || 'NONE'}`);
|
|
43
|
+
let stripeInstance = null;
|
|
44
|
+
/**
|
|
45
|
+
* Get the Stripe instance, throwing an error if not configured.
|
|
46
|
+
* This allows the app to start even without Stripe keys,
|
|
47
|
+
* failing only when Stripe features are actually used.
|
|
48
|
+
*/
|
|
49
|
+
function getStripe() {
|
|
50
|
+
if (!stripeInstance) {
|
|
51
|
+
if (!stripeSecretKey) {
|
|
52
|
+
throw new Error('STRIPE_SECRET_KEY environment variable is required for payment features');
|
|
53
|
+
}
|
|
54
|
+
stripeInstance = new stripe_1.default(stripeSecretKey, {});
|
|
55
|
+
}
|
|
56
|
+
return stripeInstance;
|
|
57
|
+
}
|
|
58
|
+
// Legacy export for backward compatibility - lazy getter
|
|
59
|
+
exports.stripe = new Proxy({}, {
|
|
60
|
+
get(_, prop) {
|
|
61
|
+
return getStripe()[prop];
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
// Stripe Price IDs (to be set from environment or config)
|
|
65
|
+
// Use test price IDs in development, production price IDs in production
|
|
66
|
+
const isProductionEnv = process.env.NODE_ENV === 'production';
|
|
67
|
+
exports.STRIPE_PRICE_IDS = {
|
|
68
|
+
// Starter tier ($9/mo)
|
|
69
|
+
starter_monthly: isProductionEnv
|
|
70
|
+
? (process.env.STRIPE_PRICE_STARTER_MONTHLY || 'price_starter_monthly')
|
|
71
|
+
: (process.env.STRIPE_TEST_PRICE_STARTER_MONTHLY || process.env.STRIPE_PRICE_STARTER_MONTHLY || 'price_starter_monthly'),
|
|
72
|
+
starter_annual: isProductionEnv
|
|
73
|
+
? (process.env.STRIPE_PRICE_STARTER_ANNUAL || 'price_starter_annual')
|
|
74
|
+
: (process.env.STRIPE_TEST_PRICE_STARTER_ANNUAL || process.env.STRIPE_PRICE_STARTER_ANNUAL || 'price_starter_annual'),
|
|
75
|
+
// Pro tier ($19/mo) - ready for future use
|
|
76
|
+
pro_monthly: isProductionEnv
|
|
77
|
+
? (process.env.STRIPE_PRICE_PRO_MONTHLY || 'price_pro_monthly')
|
|
78
|
+
: (process.env.STRIPE_TEST_PRICE_PRO_MONTHLY || process.env.STRIPE_PRICE_PRO_MONTHLY || 'price_pro_monthly'),
|
|
79
|
+
pro_annual: isProductionEnv
|
|
80
|
+
? (process.env.STRIPE_PRICE_PRO_ANNUAL || 'price_pro_annual')
|
|
81
|
+
: (process.env.STRIPE_TEST_PRICE_PRO_ANNUAL || process.env.STRIPE_PRICE_PRO_ANNUAL || 'price_pro_annual'),
|
|
82
|
+
// Business tier ($49/mo) - deferred until traction
|
|
83
|
+
business_monthly: isProductionEnv
|
|
84
|
+
? (process.env.STRIPE_PRICE_BUSINESS_MONTHLY || 'price_business_monthly')
|
|
85
|
+
: (process.env.STRIPE_TEST_PRICE_BUSINESS_MONTHLY || process.env.STRIPE_PRICE_BUSINESS_MONTHLY || 'price_business_monthly'),
|
|
86
|
+
business_annual: isProductionEnv
|
|
87
|
+
? (process.env.STRIPE_PRICE_BUSINESS_ANNUAL || 'price_business_annual')
|
|
88
|
+
: (process.env.STRIPE_TEST_PRICE_BUSINESS_ANNUAL || process.env.STRIPE_PRICE_BUSINESS_ANNUAL || 'price_business_annual'),
|
|
89
|
+
};
|
|
90
|
+
// Log price IDs on startup
|
|
91
|
+
console.log(`[Stripe] Price IDs:`, {
|
|
92
|
+
starter_monthly: exports.STRIPE_PRICE_IDS.starter_monthly,
|
|
93
|
+
starter_annual: exports.STRIPE_PRICE_IDS.starter_annual,
|
|
94
|
+
pro_monthly: exports.STRIPE_PRICE_IDS.pro_monthly,
|
|
95
|
+
pro_annual: exports.STRIPE_PRICE_IDS.pro_annual,
|
|
96
|
+
});
|
|
97
|
+
/**
|
|
98
|
+
* Map Stripe price ID to subscription tier
|
|
99
|
+
*/
|
|
100
|
+
function priceIdToTier(priceId) {
|
|
101
|
+
// Check business tier first (most specific)
|
|
102
|
+
const businessPrices = [
|
|
103
|
+
exports.STRIPE_PRICE_IDS.business_monthly,
|
|
104
|
+
exports.STRIPE_PRICE_IDS.business_annual,
|
|
105
|
+
];
|
|
106
|
+
if (businessPrices.includes(priceId) || priceId.includes('business')) {
|
|
107
|
+
return 'business';
|
|
108
|
+
}
|
|
109
|
+
// Check pro tier
|
|
110
|
+
const proPrices = [
|
|
111
|
+
exports.STRIPE_PRICE_IDS.pro_monthly,
|
|
112
|
+
exports.STRIPE_PRICE_IDS.pro_annual,
|
|
113
|
+
];
|
|
114
|
+
if (proPrices.includes(priceId) || priceId.includes('pro')) {
|
|
115
|
+
return 'pro';
|
|
116
|
+
}
|
|
117
|
+
// Check starter tier
|
|
118
|
+
const starterPrices = [
|
|
119
|
+
exports.STRIPE_PRICE_IDS.starter_monthly,
|
|
120
|
+
exports.STRIPE_PRICE_IDS.starter_annual,
|
|
121
|
+
];
|
|
122
|
+
if (starterPrices.includes(priceId) || priceId.includes('starter')) {
|
|
123
|
+
return 'starter';
|
|
124
|
+
}
|
|
125
|
+
return 'free';
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Create a Stripe checkout session for a new subscription
|
|
129
|
+
*/
|
|
130
|
+
async function createCheckoutSession(params) {
|
|
131
|
+
const { userId, userEmail, priceId, successUrl, cancelUrl, trialDays } = params;
|
|
132
|
+
// Create or retrieve Stripe customer
|
|
133
|
+
const customers = await exports.stripe.customers.list({
|
|
134
|
+
email: userEmail,
|
|
135
|
+
limit: 1,
|
|
136
|
+
});
|
|
137
|
+
let customerId;
|
|
138
|
+
if (customers.data.length > 0) {
|
|
139
|
+
customerId = customers.data[0].id;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const customer = await exports.stripe.customers.create({
|
|
143
|
+
email: userEmail,
|
|
144
|
+
metadata: {
|
|
145
|
+
userId,
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
customerId = customer.id;
|
|
149
|
+
}
|
|
150
|
+
// Create checkout session
|
|
151
|
+
const sessionParams = {
|
|
152
|
+
customer: customerId,
|
|
153
|
+
mode: 'subscription',
|
|
154
|
+
payment_method_types: ['card'],
|
|
155
|
+
locale: 'en', // Force English locale for international users
|
|
156
|
+
line_items: [
|
|
157
|
+
{
|
|
158
|
+
price: priceId,
|
|
159
|
+
quantity: 1,
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
success_url: successUrl,
|
|
163
|
+
cancel_url: cancelUrl,
|
|
164
|
+
metadata: {
|
|
165
|
+
userId,
|
|
166
|
+
},
|
|
167
|
+
subscription_data: {
|
|
168
|
+
metadata: {
|
|
169
|
+
userId,
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
// Add trial period if specified
|
|
174
|
+
if (trialDays && trialDays > 0) {
|
|
175
|
+
sessionParams.subscription_data = {
|
|
176
|
+
...sessionParams.subscription_data,
|
|
177
|
+
trial_period_days: trialDays,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return await exports.stripe.checkout.sessions.create(sessionParams);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Create a customer portal session for managing subscription
|
|
184
|
+
*/
|
|
185
|
+
async function createCustomerPortalSession(params) {
|
|
186
|
+
const { customerId, returnUrl } = params;
|
|
187
|
+
return await exports.stripe.billingPortal.sessions.create({
|
|
188
|
+
customer: customerId,
|
|
189
|
+
return_url: returnUrl,
|
|
190
|
+
locale: 'en', // Force English locale for portal
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Start a free trial without requiring a credit card
|
|
195
|
+
* Creates a Stripe customer for future conversion, and a local subscription record
|
|
196
|
+
*
|
|
197
|
+
* @param userId - The user's ID in our database
|
|
198
|
+
* @param userEmail - The user's email address
|
|
199
|
+
* @param userName - Optional user name
|
|
200
|
+
* @param trialDays - Number of trial days (default 7)
|
|
201
|
+
* @returns The created Stripe customer ID and trial end date
|
|
202
|
+
*/
|
|
203
|
+
async function startTrialWithoutPayment(params) {
|
|
204
|
+
const { userId, userEmail, userName, trialDays = 7 } = params;
|
|
205
|
+
const db = (0, index_js_1.getDb)();
|
|
206
|
+
// Check if customer already exists in Stripe
|
|
207
|
+
const existingCustomers = await exports.stripe.customers.list({
|
|
208
|
+
email: userEmail,
|
|
209
|
+
limit: 1,
|
|
210
|
+
});
|
|
211
|
+
let customerId;
|
|
212
|
+
if (existingCustomers.data.length > 0) {
|
|
213
|
+
customerId = existingCustomers.data[0].id;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// Create new Stripe customer (no payment method required)
|
|
217
|
+
const customer = await exports.stripe.customers.create({
|
|
218
|
+
email: userEmail,
|
|
219
|
+
name: userName || undefined,
|
|
220
|
+
metadata: {
|
|
221
|
+
userId,
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
customerId = customer.id;
|
|
225
|
+
}
|
|
226
|
+
// Calculate trial end date
|
|
227
|
+
const trialEndsAt = new Date();
|
|
228
|
+
trialEndsAt.setDate(trialEndsAt.getDate() + trialDays);
|
|
229
|
+
// Update or create subscription in our database
|
|
230
|
+
await (0, utils_js_1.upsertSubscription)({
|
|
231
|
+
userId,
|
|
232
|
+
stripeSubscriptionId: null, // No Stripe subscription yet - will be created when they add payment
|
|
233
|
+
tier: 'starter',
|
|
234
|
+
status: 'trialing',
|
|
235
|
+
currentPeriodEnd: trialEndsAt,
|
|
236
|
+
});
|
|
237
|
+
// Update user with Stripe customer ID
|
|
238
|
+
await db.update(index_js_1.users)
|
|
239
|
+
.set({
|
|
240
|
+
stripeCustomerId: customerId,
|
|
241
|
+
updatedAt: new Date(),
|
|
242
|
+
})
|
|
243
|
+
.where((0, drizzle_orm_1.eq)(index_js_1.users.id, userId));
|
|
244
|
+
console.log(`[Stripe] Started trial for user ${userId} (customer: ${customerId}), ends: ${trialEndsAt.toISOString()}`);
|
|
245
|
+
return { customerId, trialEndsAt };
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Handle Stripe webhook events
|
|
249
|
+
*/
|
|
250
|
+
async function handleWebhookEvent(event) {
|
|
251
|
+
const db = (0, index_js_1.getDb)();
|
|
252
|
+
switch (event.type) {
|
|
253
|
+
case 'checkout.session.completed': {
|
|
254
|
+
const session = event.data.object;
|
|
255
|
+
await handleCheckoutCompleted(session);
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
case 'customer.subscription.created': {
|
|
259
|
+
const subscription = event.data.object;
|
|
260
|
+
await handleSubscriptionChange(subscription, true);
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
case 'customer.subscription.updated': {
|
|
264
|
+
const subscription = event.data.object;
|
|
265
|
+
await handleSubscriptionChange(subscription, false);
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
case 'customer.subscription.deleted': {
|
|
269
|
+
const subscription = event.data.object;
|
|
270
|
+
await handleSubscriptionDeleted(subscription);
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
case 'invoice.paid': {
|
|
274
|
+
const invoice = event.data.object;
|
|
275
|
+
await handleInvoicePaid(invoice);
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
case 'invoice.payment_failed': {
|
|
279
|
+
const invoice = event.data.object;
|
|
280
|
+
await handleInvoicePaymentFailed(invoice);
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
default:
|
|
284
|
+
console.log(`Unhandled event type: ${event.type}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Handle checkout.session.completed event
|
|
289
|
+
*/
|
|
290
|
+
async function handleCheckoutCompleted(session) {
|
|
291
|
+
const userId = session.metadata?.userId;
|
|
292
|
+
if (!userId) {
|
|
293
|
+
console.error('No userId in session metadata');
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
// Update user's Stripe customer ID if not already set
|
|
297
|
+
if (session.customer && typeof session.customer === 'string') {
|
|
298
|
+
const db = (0, index_js_1.getDb)();
|
|
299
|
+
// TODO: Update user's stripeCustomerId in database
|
|
300
|
+
// For now, the customer ID is available in session.customer
|
|
301
|
+
}
|
|
302
|
+
// The subscription will be created via customer.subscription.created event
|
|
303
|
+
console.log(`Checkout completed for user ${userId}`);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Handle subscription created/updated events
|
|
307
|
+
*/
|
|
308
|
+
async function handleSubscriptionChange(subscription, isNew = false) {
|
|
309
|
+
const userId = subscription.metadata?.userId;
|
|
310
|
+
if (!userId) {
|
|
311
|
+
console.error('No userId in subscription metadata');
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
// Get the price ID from the subscription
|
|
315
|
+
const firstItem = subscription.items.data[0];
|
|
316
|
+
const priceId = firstItem?.price.id;
|
|
317
|
+
if (!priceId) {
|
|
318
|
+
console.error('No price ID in subscription');
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
// Determine tier from price ID
|
|
322
|
+
const tier = priceIdToTier(priceId);
|
|
323
|
+
// Determine status
|
|
324
|
+
let status;
|
|
325
|
+
switch (subscription.status) {
|
|
326
|
+
case 'active':
|
|
327
|
+
status = 'active';
|
|
328
|
+
break;
|
|
329
|
+
case 'canceled':
|
|
330
|
+
case 'unpaid':
|
|
331
|
+
status = 'canceled';
|
|
332
|
+
break;
|
|
333
|
+
case 'past_due':
|
|
334
|
+
status = 'past_due';
|
|
335
|
+
break;
|
|
336
|
+
case 'trialing':
|
|
337
|
+
status = 'trialing';
|
|
338
|
+
break;
|
|
339
|
+
default:
|
|
340
|
+
status = 'active';
|
|
341
|
+
}
|
|
342
|
+
// Get current_period_end - check subscription root first, then items (API version compatibility)
|
|
343
|
+
const currentPeriodEndTimestamp = subscription.current_period_end
|
|
344
|
+
?? firstItem?.current_period_end;
|
|
345
|
+
if (!currentPeriodEndTimestamp) {
|
|
346
|
+
console.error('No current_period_end found in subscription or items');
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
// Upsert subscription in database
|
|
350
|
+
await (0, utils_js_1.upsertSubscription)({
|
|
351
|
+
userId,
|
|
352
|
+
tier,
|
|
353
|
+
status,
|
|
354
|
+
stripeSubscriptionId: subscription.id,
|
|
355
|
+
stripePriceId: priceId,
|
|
356
|
+
currentPeriodEnd: new Date(currentPeriodEndTimestamp * 1000),
|
|
357
|
+
});
|
|
358
|
+
console.log(`Subscription ${subscription.status} for user ${userId}, tier: ${tier}`);
|
|
359
|
+
// Send welcome email for new subscriptions (not updates)
|
|
360
|
+
if (isNew && tier !== 'free') {
|
|
361
|
+
try {
|
|
362
|
+
const db = (0, index_js_1.getDb)();
|
|
363
|
+
const [user] = await db.select().from(index_js_1.users).where((0, drizzle_orm_1.eq)(index_js_1.users.id, userId)).limit(1);
|
|
364
|
+
if (user) {
|
|
365
|
+
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://ucptools.dev';
|
|
366
|
+
await (0, email_js_1.sendWelcomeEmail)({
|
|
367
|
+
to: {
|
|
368
|
+
email: user.email,
|
|
369
|
+
name: user.name || undefined,
|
|
370
|
+
},
|
|
371
|
+
dashboardUrl: `${baseUrl}/dashboard`,
|
|
372
|
+
});
|
|
373
|
+
console.log(`Welcome email sent to ${user.email}`);
|
|
374
|
+
// Send Slack notification for new signup (fire-and-forget)
|
|
375
|
+
(0, notifications_js_1.notifySignup)({ id: userId, email: user.email, name: user.name }, { tier, status });
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
console.error('Failed to send welcome email:', error);
|
|
380
|
+
// Don't throw - welcome email failure shouldn't break subscription flow
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Handle subscription deleted event
|
|
386
|
+
*/
|
|
387
|
+
async function handleSubscriptionDeleted(subscription) {
|
|
388
|
+
const userId = subscription.metadata?.userId;
|
|
389
|
+
if (!userId) {
|
|
390
|
+
console.error('No userId in subscription metadata');
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
// Get current_period_end - check subscription root first, then items (API version compatibility)
|
|
394
|
+
const firstItem = subscription.items.data[0];
|
|
395
|
+
const currentPeriodEndTimestamp = subscription.current_period_end
|
|
396
|
+
?? firstItem?.current_period_end;
|
|
397
|
+
// Update subscription to canceled and downgrade to free
|
|
398
|
+
await (0, utils_js_1.upsertSubscription)({
|
|
399
|
+
userId,
|
|
400
|
+
tier: 'free',
|
|
401
|
+
status: 'canceled',
|
|
402
|
+
stripeSubscriptionId: subscription.id,
|
|
403
|
+
currentPeriodEnd: currentPeriodEndTimestamp ? new Date(currentPeriodEndTimestamp * 1000) : new Date(),
|
|
404
|
+
});
|
|
405
|
+
console.log(`Subscription canceled for user ${userId}, downgraded to free`);
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Handle invoice.paid event
|
|
409
|
+
*/
|
|
410
|
+
async function handleInvoicePaid(invoice) {
|
|
411
|
+
const subscriptionId = invoice.subscription;
|
|
412
|
+
if (!subscriptionId || typeof subscriptionId !== 'string') {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
// Retrieve subscription to update status
|
|
416
|
+
const subscription = await exports.stripe.subscriptions.retrieve(subscriptionId);
|
|
417
|
+
await handleSubscriptionChange(subscription);
|
|
418
|
+
console.log(`Invoice paid for subscription ${subscriptionId}`);
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Handle invoice.payment_failed event
|
|
422
|
+
*/
|
|
423
|
+
async function handleInvoicePaymentFailed(invoice) {
|
|
424
|
+
const subscriptionId = invoice.subscription;
|
|
425
|
+
if (!subscriptionId || typeof subscriptionId !== 'string') {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
const userId = invoice.subscription_details?.metadata?.userId;
|
|
429
|
+
if (!userId) {
|
|
430
|
+
console.error('No userId in invoice metadata');
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
// Update subscription status to past_due
|
|
434
|
+
await (0, utils_js_1.upsertSubscription)({
|
|
435
|
+
userId,
|
|
436
|
+
status: 'past_due',
|
|
437
|
+
});
|
|
438
|
+
console.log(`Payment failed for subscription ${subscriptionId}, user ${userId}`);
|
|
439
|
+
// TODO: Send email notification to user
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Verify Stripe webhook signature
|
|
443
|
+
*/
|
|
444
|
+
function verifyWebhookSignature(payload, signature, secret) {
|
|
445
|
+
return exports.stripe.webhooks.constructEvent(payload, signature, secret);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Get subscription details for a user
|
|
449
|
+
*/
|
|
450
|
+
async function getSubscriptionDetails(stripeSubscriptionId) {
|
|
451
|
+
try {
|
|
452
|
+
return await exports.stripe.subscriptions.retrieve(stripeSubscriptionId);
|
|
453
|
+
}
|
|
454
|
+
catch (error) {
|
|
455
|
+
console.error('Error retrieving subscription:', error);
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Cancel a subscription at period end
|
|
461
|
+
*/
|
|
462
|
+
async function cancelSubscription(stripeSubscriptionId) {
|
|
463
|
+
return await exports.stripe.subscriptions.update(stripeSubscriptionId, {
|
|
464
|
+
cancel_at_period_end: true,
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Resume a canceled subscription
|
|
469
|
+
*/
|
|
470
|
+
async function resumeSubscription(stripeSubscriptionId) {
|
|
471
|
+
return await exports.stripe.subscriptions.update(stripeSubscriptionId, {
|
|
472
|
+
cancel_at_period_end: false,
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Update subscription to a new price (upgrade/downgrade)
|
|
477
|
+
*/
|
|
478
|
+
async function updateSubscription(stripeSubscriptionId, newPriceId) {
|
|
479
|
+
const subscription = await exports.stripe.subscriptions.retrieve(stripeSubscriptionId);
|
|
480
|
+
return await exports.stripe.subscriptions.update(stripeSubscriptionId, {
|
|
481
|
+
items: [
|
|
482
|
+
{
|
|
483
|
+
id: subscription.items.data[0].id,
|
|
484
|
+
price: newPriceId,
|
|
485
|
+
},
|
|
486
|
+
],
|
|
487
|
+
proration_behavior: 'always_invoice',
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
//# sourceMappingURL=stripe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../src/services/stripe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation History Service
|
|
3
|
+
*
|
|
4
|
+
* Manages storage and retrieval of validation history for domains.
|
|
5
|
+
* Supports both authenticated users (via monitoredDomains) and
|
|
6
|
+
* anonymous public access (with limited history).
|
|
7
|
+
*/
|
|
8
|
+
import { type ValidationResult } from './validation.js';
|
|
9
|
+
export interface ValidationHistoryEntry {
|
|
10
|
+
id: string;
|
|
11
|
+
domainId: string;
|
|
12
|
+
score: number | null;
|
|
13
|
+
grade: string | null;
|
|
14
|
+
hasUcp: boolean | null;
|
|
15
|
+
issuesCount: number | null;
|
|
16
|
+
errorsCount: number | null;
|
|
17
|
+
warningsCount: number | null;
|
|
18
|
+
validatedAt: Date;
|
|
19
|
+
}
|
|
20
|
+
export interface ValidationTrend {
|
|
21
|
+
direction: 'improving' | 'declining' | 'stable' | 'insufficient_data';
|
|
22
|
+
scoreChange: number;
|
|
23
|
+
periodDays: number;
|
|
24
|
+
dataPoints: number;
|
|
25
|
+
}
|
|
26
|
+
export interface DomainHistoryResult {
|
|
27
|
+
domain: string;
|
|
28
|
+
currentScore: number | null;
|
|
29
|
+
currentGrade: string | null;
|
|
30
|
+
trend: ValidationTrend;
|
|
31
|
+
history: ValidationHistoryEntry[];
|
|
32
|
+
lastValidatedAt: Date | null;
|
|
33
|
+
}
|
|
34
|
+
export interface PublicHistoryResult {
|
|
35
|
+
domain: string;
|
|
36
|
+
history: Array<{
|
|
37
|
+
score: number | null;
|
|
38
|
+
grade: string | null;
|
|
39
|
+
hasUcp: boolean | null;
|
|
40
|
+
validatedAt: Date;
|
|
41
|
+
}>;
|
|
42
|
+
trend: ValidationTrend;
|
|
43
|
+
limitedAccess: boolean;
|
|
44
|
+
message?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Store a validation result in history
|
|
48
|
+
*/
|
|
49
|
+
export declare function storeValidationHistory(domainId: string, result: ValidationResult): Promise<ValidationHistoryEntry | null>;
|
|
50
|
+
/**
|
|
51
|
+
* Get validation history for a monitored domain (authenticated user)
|
|
52
|
+
*/
|
|
53
|
+
export declare function getValidationHistory(domainId: string, limit?: number, daysBack?: number): Promise<ValidationHistoryEntry[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Calculate trend from history entries
|
|
56
|
+
*/
|
|
57
|
+
export declare function calculateTrend(history: ValidationHistoryEntry[]): ValidationTrend;
|
|
58
|
+
/**
|
|
59
|
+
* Get domain history with trend analysis (for authenticated users)
|
|
60
|
+
*/
|
|
61
|
+
export declare function getDomainHistory(domainId: string, daysBack?: number): Promise<DomainHistoryResult | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Get public history for a domain (limited to 3 entries for anonymous users)
|
|
64
|
+
* This looks up by domain name, not by user's monitored domain ID
|
|
65
|
+
*/
|
|
66
|
+
export declare function getPublicDomainHistory(domainName: string, isAuthenticated?: boolean): Promise<PublicHistoryResult>;
|
|
67
|
+
/**
|
|
68
|
+
* Get the previous validation entry for a domain (for diffing)
|
|
69
|
+
* Returns the most recent entry excluding the given ID.
|
|
70
|
+
*/
|
|
71
|
+
export declare function getPreviousValidation(domainId: string, excludeId?: string): Promise<{
|
|
72
|
+
id: string;
|
|
73
|
+
resultJson: string | null;
|
|
74
|
+
score: number | null;
|
|
75
|
+
grade: string | null;
|
|
76
|
+
} | null>;
|
|
77
|
+
/**
|
|
78
|
+
* Update a validation history entry with severity and change summary
|
|
79
|
+
*/
|
|
80
|
+
export declare function updateHistorySeverity(historyId: string, severity: string, changesSummary: string): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Run validation and store history for a monitored domain
|
|
83
|
+
*/
|
|
84
|
+
export declare function validateAndStoreHistory(domainId: string, domainName: string): Promise<{
|
|
85
|
+
result: ValidationResult;
|
|
86
|
+
historyEntry: ValidationHistoryEntry | null;
|
|
87
|
+
}>;
|
|
88
|
+
/**
|
|
89
|
+
* Get validation history statistics
|
|
90
|
+
*/
|
|
91
|
+
export declare function getHistoryStats(domainId: string): Promise<{
|
|
92
|
+
totalValidations: number;
|
|
93
|
+
averageScore: number;
|
|
94
|
+
bestScore: number;
|
|
95
|
+
worstScore: number;
|
|
96
|
+
firstValidation: Date | null;
|
|
97
|
+
lastValidation: Date | null;
|
|
98
|
+
}>;
|
|
99
|
+
//# sourceMappingURL=validation-history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-history.d.ts","sourceRoot":"","sources":["../../src/services/validation-history.ts"],"names":[],"mappings":"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"}
|