@brandlab-digital/site-next 1.0.0-rc.2 → 1.0.0-rc.21

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 (88) hide show
  1. package/dist/analytics.d.ts +23 -0
  2. package/dist/analytics.d.ts.map +1 -1
  3. package/dist/analytics.js +61 -0
  4. package/dist/analytics.js.map +1 -1
  5. package/dist/blog.d.ts.map +1 -1
  6. package/dist/blog.js +5 -2
  7. package/dist/blog.js.map +1 -1
  8. package/dist/contact/attribution.d.ts +11 -0
  9. package/dist/contact/attribution.d.ts.map +1 -0
  10. package/dist/contact/attribution.js +145 -0
  11. package/dist/contact/attribution.js.map +1 -0
  12. package/dist/contact/client.d.ts +7 -1
  13. package/dist/contact/client.d.ts.map +1 -1
  14. package/dist/contact/client.js +32 -1
  15. package/dist/contact/client.js.map +1 -1
  16. package/dist/contact/context.d.ts +4 -0
  17. package/dist/contact/context.d.ts.map +1 -1
  18. package/dist/contact/context.js +56 -7
  19. package/dist/contact/context.js.map +1 -1
  20. package/dist/contact/contract.d.ts +3 -4
  21. package/dist/contact/contract.d.ts.map +1 -1
  22. package/dist/contact/contract.js +3 -5
  23. package/dist/contact/contract.js.map +1 -1
  24. package/dist/contact/email.d.ts +1 -0
  25. package/dist/contact/email.d.ts.map +1 -1
  26. package/dist/contact/email.js +137 -54
  27. package/dist/contact/email.js.map +1 -1
  28. package/dist/contact/image-sanitizer.d.ts +1 -1
  29. package/dist/contact/image-sanitizer.d.ts.map +1 -1
  30. package/dist/contact/image-sanitizer.js +12 -17
  31. package/dist/contact/image-sanitizer.js.map +1 -1
  32. package/dist/contact/index.d.ts +1 -0
  33. package/dist/contact/index.d.ts.map +1 -1
  34. package/dist/contact/index.js +2 -0
  35. package/dist/contact/index.js.map +1 -1
  36. package/dist/contact/production.d.ts +3 -1
  37. package/dist/contact/production.d.ts.map +1 -1
  38. package/dist/contact/production.js +31 -60
  39. package/dist/contact/production.js.map +1 -1
  40. package/dist/contact/resend.d.ts +1 -1
  41. package/dist/contact/resend.js +1 -1
  42. package/dist/contact/server-entry.d.ts +13 -0
  43. package/dist/contact/server-entry.d.ts.map +1 -0
  44. package/dist/contact/server-entry.js +13 -0
  45. package/dist/contact/server-entry.js.map +1 -0
  46. package/dist/contact/server.d.ts.map +1 -1
  47. package/dist/contact/server.js +27 -28
  48. package/dist/contact/server.js.map +1 -1
  49. package/dist/contact/shared.d.ts +3 -6
  50. package/dist/contact/shared.d.ts.map +1 -1
  51. package/dist/contact/shared.js.map +1 -1
  52. package/dist/google-reviews-client.d.ts +20 -0
  53. package/dist/google-reviews-client.d.ts.map +1 -0
  54. package/dist/google-reviews-client.js +85 -0
  55. package/dist/google-reviews-client.js.map +1 -0
  56. package/dist/google-reviews-durable.d.ts +22 -0
  57. package/dist/google-reviews-durable.d.ts.map +1 -0
  58. package/dist/google-reviews-durable.js +81 -0
  59. package/dist/google-reviews-durable.js.map +1 -0
  60. package/dist/google-reviews-server.d.ts +58 -0
  61. package/dist/google-reviews-server.d.ts.map +1 -0
  62. package/dist/google-reviews-server.js +151 -0
  63. package/dist/google-reviews-server.js.map +1 -0
  64. package/dist/google-reviews-ui.d.ts +599 -0
  65. package/dist/google-reviews-ui.d.ts.map +1 -0
  66. package/dist/google-reviews-ui.js +188 -0
  67. package/dist/google-reviews-ui.js.map +1 -0
  68. package/dist/google-reviews.d.ts +4 -322
  69. package/dist/google-reviews.d.ts.map +1 -1
  70. package/dist/google-reviews.js +4 -252
  71. package/dist/google-reviews.js.map +1 -1
  72. package/dist/google-tag-plan.d.ts +19 -0
  73. package/dist/google-tag-plan.d.ts.map +1 -0
  74. package/dist/google-tag-plan.js +85 -0
  75. package/dist/google-tag-plan.js.map +1 -0
  76. package/dist/google-tag.d.ts +17 -0
  77. package/dist/google-tag.d.ts.map +1 -0
  78. package/dist/google-tag.js +18 -0
  79. package/dist/google-tag.js.map +1 -0
  80. package/dist/instrumentation-client.d.ts +2 -0
  81. package/dist/instrumentation-client.d.ts.map +1 -1
  82. package/dist/instrumentation-client.js +39 -3
  83. package/dist/instrumentation-client.js.map +1 -1
  84. package/dist/redis-rest.d.ts +12 -0
  85. package/dist/redis-rest.d.ts.map +1 -0
  86. package/dist/redis-rest.js +83 -0
  87. package/dist/redis-rest.js.map +1 -0
  88. package/package.json +29 -36
@@ -0,0 +1,151 @@
1
+ import 'server-only';
2
+ import { createGooglePlaceReviewsUnavailableSnapshot, fetchGooglePlaceReviewsSnapshot, normalizeGooglePlaceId, normalizeGooglePlaceReviewsMode, } from '@brandlab-digital/site-core/google-reviews';
3
+ import { createRedisGooglePlaceReviewsQuotaGuard } from './google-reviews-durable.js';
4
+ import { createBrandlabUpstashRedisEvalClient } from './redis-rest.js';
5
+ export const BRANDLAB_GOOGLE_REVIEWS_PRODUCTION_RUNTIME = 'brandlab-google-reviews-production-v1';
6
+ export const BRANDLAB_GOOGLE_REVIEWS_ENVIRONMENT_NAMES = {
7
+ apiKey: 'GOOGLE_MAPS_PLATFORM_API_KEY',
8
+ redisRestUrl: 'UPSTASH_REDIS_REST_URL',
9
+ redisRestToken: 'UPSTASH_REDIS_REST_TOKEN',
10
+ };
11
+ export const GOOGLE_PLACE_REVIEWS_UNAVAILABLE_HEADERS = {
12
+ 'Cache-Control': 'private, no-store, max-age=0',
13
+ Pragma: 'no-cache',
14
+ 'X-Content-Type-Options': 'nosniff',
15
+ };
16
+ export const GOOGLE_PLACE_REVIEWS_AVAILABLE_HEADERS = GOOGLE_PLACE_REVIEWS_UNAVAILABLE_HEADERS;
17
+ const inFlightByFetcher = new WeakMap();
18
+ function coalescingKey(options) {
19
+ return JSON.stringify([
20
+ normalizeGooglePlaceId(options.placeId) ?? '',
21
+ normalizeGooglePlaceReviewsMode(options.mode),
22
+ options.maxReviews ?? null,
23
+ options.fallbackGoogleMapsUri ?? '',
24
+ ]);
25
+ }
26
+ async function loadGooglePlaceReviewsSnapshot(options) {
27
+ const placeId = normalizeGooglePlaceId(options.placeId);
28
+ const mode = normalizeGooglePlaceReviewsMode(options.mode);
29
+ if (!options.apiKey?.trim() || !placeId) {
30
+ return { snapshot: await fetchGooglePlaceReviewsSnapshot(options) };
31
+ }
32
+ if (typeof options.quotaGuard !== 'function') {
33
+ return {
34
+ snapshot: createGooglePlaceReviewsUnavailableSnapshot('quota-guard-unavailable', options.fallbackGoogleMapsUri, mode),
35
+ forcedStatus: 503,
36
+ };
37
+ }
38
+ let decision;
39
+ try {
40
+ decision = await options.quotaGuard({ placeId });
41
+ if (typeof decision?.allowed !== 'boolean' ||
42
+ (decision.retryAfterSeconds !== undefined && (!Number.isSafeInteger(decision.retryAfterSeconds) ||
43
+ decision.retryAfterSeconds < 1 ||
44
+ decision.retryAfterSeconds > 86_400))) {
45
+ throw new Error('Invalid quota decision.');
46
+ }
47
+ }
48
+ catch {
49
+ return {
50
+ snapshot: createGooglePlaceReviewsUnavailableSnapshot('quota-guard-unavailable', options.fallbackGoogleMapsUri, mode),
51
+ forcedStatus: 503,
52
+ };
53
+ }
54
+ if (!decision.allowed) {
55
+ return {
56
+ snapshot: createGooglePlaceReviewsUnavailableSnapshot('quota-exhausted', options.fallbackGoogleMapsUri, mode),
57
+ forcedStatus: 429,
58
+ ...(decision.retryAfterSeconds
59
+ ? { retryAfterSeconds: decision.retryAfterSeconds }
60
+ : {}),
61
+ };
62
+ }
63
+ return { snapshot: await fetchGooglePlaceReviewsSnapshot(options) };
64
+ }
65
+ function getGooglePlaceReviewsRequest(options) {
66
+ const fetcher = options.fetcher ?? fetch;
67
+ const requests = inFlightByFetcher.get(fetcher) ?? new Map();
68
+ inFlightByFetcher.set(fetcher, requests);
69
+ const key = coalescingKey(options);
70
+ const existing = requests.get(key);
71
+ if (existing)
72
+ return existing;
73
+ const request = loadGooglePlaceReviewsSnapshot(options).finally(() => {
74
+ requests.delete(key);
75
+ if (requests.size === 0)
76
+ inFlightByFetcher.delete(fetcher);
77
+ });
78
+ requests.set(key, request);
79
+ return request;
80
+ }
81
+ /** Low-level route response for tests and approved custom adapters. */
82
+ export async function createGooglePlaceReviewsRouteResponse(options) {
83
+ const result = await getGooglePlaceReviewsRequest(options);
84
+ const headers = new Headers(options.responseInit?.headers);
85
+ Object.entries(GOOGLE_PLACE_REVIEWS_AVAILABLE_HEADERS).forEach(([name, value]) => {
86
+ headers.set(name, value);
87
+ });
88
+ if (result.retryAfterSeconds) {
89
+ headers.set('Retry-After', String(result.retryAfterSeconds));
90
+ }
91
+ return Response.json(result.snapshot, {
92
+ ...options.responseInit,
93
+ status: result.forcedStatus ?? options.responseInit?.status,
94
+ headers,
95
+ });
96
+ }
97
+ function requiredEnvironment(environment, name) {
98
+ const value = environment[name];
99
+ if (typeof value !== 'string' ||
100
+ value.length < 1 ||
101
+ value.length > 8_192 ||
102
+ /[\u0000-\u001f\u007f]/.test(value)) {
103
+ throw new Error(`Required Google reviews environment variable ${name} is unavailable.`);
104
+ }
105
+ return value;
106
+ }
107
+ /**
108
+ * Creates the one approved production route: live no-store Places data,
109
+ * durable per-project quota protection and no persisted review content.
110
+ */
111
+ export function createBrandlabGooglePlaceReviewsProductionRuntime(options) {
112
+ if ((options.fetcher || options.now) &&
113
+ options.environment.NODE_ENV !== 'test') {
114
+ throw new Error('Google reviews transport and clock overrides are available only in test mode.');
115
+ }
116
+ const apiKey = requiredEnvironment(options.environment, BRANDLAB_GOOGLE_REVIEWS_ENVIRONMENT_NAMES.apiKey);
117
+ const redisRestUrl = requiredEnvironment(options.environment, BRANDLAB_GOOGLE_REVIEWS_ENVIRONMENT_NAMES.redisRestUrl);
118
+ const redisRestToken = requiredEnvironment(options.environment, BRANDLAB_GOOGLE_REVIEWS_ENVIRONMENT_NAMES.redisRestToken);
119
+ const fetcher = options.fetcher ?? fetch;
120
+ const redis = createBrandlabUpstashRedisEvalClient({
121
+ url: redisRestUrl,
122
+ token: redisRestToken,
123
+ fetcher,
124
+ });
125
+ const quotaGuard = createRedisGooglePlaceReviewsQuotaGuard({
126
+ redis,
127
+ projectId: options.projectId,
128
+ monthlyRequestLimit: options.monthlyRequestLimit,
129
+ ...(options.namespace ? { namespace: options.namespace } : {}),
130
+ ...(options.now ? { now: options.now } : {}),
131
+ });
132
+ const mode = normalizeGooglePlaceReviewsMode(options.mode);
133
+ return {
134
+ runtimeKind: BRANDLAB_GOOGLE_REVIEWS_PRODUCTION_RUNTIME,
135
+ mode,
136
+ routeHandler: () => createGooglePlaceReviewsRouteResponse({
137
+ apiKey,
138
+ placeId: options.placeId,
139
+ mode,
140
+ ...(mode === 'full' && options.maxReviews !== undefined
141
+ ? { maxReviews: options.maxReviews }
142
+ : {}),
143
+ ...(options.fallbackGoogleMapsUri
144
+ ? { fallbackGoogleMapsUri: options.fallbackGoogleMapsUri }
145
+ : {}),
146
+ quotaGuard,
147
+ fetcher,
148
+ }),
149
+ };
150
+ }
151
+ //# sourceMappingURL=google-reviews-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-reviews-server.js","sourceRoot":"","sources":["../src/google-reviews-server.ts"],"names":[],"mappings":"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"}