fontdue-js 2.22.0 → 2.22.2
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/CHANGELOG.md +9 -0
- package/dist/components/ConfigContext.d.ts +3 -0
- package/dist/components/ConfigContext.js +2 -1
- package/dist/components/FontdueProvider/FontdueProviderClientComponent.js +2 -0
- package/dist/components/elements/StoreModalUnifiedCheckout.js +7 -3
- package/dist/corsError.d.ts +1 -0
- package/dist/corsError.js +16 -9
- package/dist/global-shim.d.ts +1 -0
- package/dist/global-shim.js +8 -0
- package/dist/relay/environment.js +51 -42
- package/package.json +1 -1
- package/dist-bundle/FontdueProvider.js +0 -6
- package/dist-bundle/FontdueProvider.js.map +0 -1
- package/dist-bundle/TypeTester.js +0 -7
- package/dist-bundle/TypeTester.js.map +0 -1
- package/dist-bundle/TypeTester.preload.js +0 -75
- package/dist-bundle/TypeTester.preload.js.map +0 -1
- package/dist-bundle/chunks/ComponentsContext-CmkN9J4X.js +0 -20843
- package/dist-bundle/chunks/ComponentsContext-CmkN9J4X.js.map +0 -1
- package/dist-bundle/chunks/CorsErrorModal-C1g_-3Re.js +0 -95
- package/dist-bundle/chunks/CorsErrorModal-C1g_-3Re.js.map +0 -1
- package/dist-bundle/chunks/TypeTesterStandalone-BMWuv8Ca.js +0 -27486
- package/dist-bundle/chunks/TypeTesterStandalone-BMWuv8Ca.js.map +0 -1
- package/dist-bundle/chunks/consent-DMvR5rEh.js +0 -84
- package/dist-bundle/chunks/consent-DMvR5rEh.js.map +0 -1
- package/dist-bundle/chunks/index-BNSbxp7B.js +0 -78
- package/dist-bundle/chunks/index-BNSbxp7B.js.map +0 -1
- package/dist-bundle/chunks/index-C4ak9qTL.js +0 -423
- package/dist-bundle/chunks/index-C4ak9qTL.js.map +0 -1
- package/dist-bundle/chunks/index-DsvF5W13.js +0 -159
- package/dist-bundle/chunks/index-DsvF5W13.js.map +0 -1
- package/dist-bundle/chunks/index-o29NNufd.js +0 -131
- package/dist-bundle/chunks/index-o29NNufd.js.map +0 -1
- package/dist-bundle/index.js +0 -23
- package/dist-bundle/index.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## 2.22.2
|
|
2
|
+
|
|
3
|
+
- Fixed country order variables (e.g. *Fair Price Adjustment*) not updating when the licensee country changed at checkout. The unified checkout now clears the option id when syncing the licensee country to a country-type variable, so the server can re-evaluate the multiplier against the new country.
|
|
4
|
+
|
|
5
|
+
## 2.22.1
|
|
6
|
+
|
|
7
|
+
- Added `corsErrorModal` config option (default `true`). Set to `false` on `<FontdueProvider>` or the script-tag config to suppress the CORS error modal entirely while keeping console warnings and auto-reload polling.
|
|
8
|
+
- GraphQL requests now retry up to 2 times (with a 1s delay) before falling through to CORS error detection. Transient network failures no longer trigger a false-positive CORS modal.
|
|
9
|
+
|
|
1
10
|
## 2.22.0
|
|
2
11
|
|
|
3
12
|
- **`features="*"` wildcard on `<TypeTester>` and `<TypeTesters>`** to expose every OpenType feature each font supports without curating a list. Custom *stylistic set* names defined by the foundry are picked up automatically. Works on both the standalone `<fontdue-type-tester>` HTML element and the React `<TypeTester>` / `<TypeTesters>` components.
|
|
@@ -29,6 +29,7 @@ export interface Config {
|
|
|
29
29
|
typeTester?: TypeTesterConfig;
|
|
30
30
|
stripe?: StripeConfig;
|
|
31
31
|
tracking?: TrackingConfig;
|
|
32
|
+
corsErrorModal?: boolean;
|
|
32
33
|
}
|
|
33
34
|
export declare const makeConfig: (config?: Config) => {
|
|
34
35
|
typeTester: {
|
|
@@ -99,6 +100,7 @@ export declare const makeConfig: (config?: Config) => {
|
|
|
99
100
|
consentMessage: string | undefined;
|
|
100
101
|
segment: SegmentConfig | undefined;
|
|
101
102
|
};
|
|
103
|
+
corsErrorModal: boolean;
|
|
102
104
|
};
|
|
103
105
|
declare const _default: React.Context<{
|
|
104
106
|
typeTester: {
|
|
@@ -169,5 +171,6 @@ declare const _default: React.Context<{
|
|
|
169
171
|
consentMessage: string | undefined;
|
|
170
172
|
segment: SegmentConfig | undefined;
|
|
171
173
|
};
|
|
174
|
+
corsErrorModal: boolean;
|
|
172
175
|
}>;
|
|
173
176
|
export default _default;
|
|
@@ -79,7 +79,8 @@ const makeConfig = config => {
|
|
|
79
79
|
consentRequired: (config === null || config === void 0 ? void 0 : (_config$tracking2 = config.tracking) === null || _config$tracking2 === void 0 ? void 0 : _config$tracking2.consentRequired) ?? false,
|
|
80
80
|
consentMessage: config === null || config === void 0 ? void 0 : (_config$tracking3 = config.tracking) === null || _config$tracking3 === void 0 ? void 0 : _config$tracking3.consentMessage,
|
|
81
81
|
segment: config === null || config === void 0 ? void 0 : (_config$tracking4 = config.tracking) === null || _config$tracking4 === void 0 ? void 0 : _config$tracking4.segment
|
|
82
|
-
}
|
|
82
|
+
},
|
|
83
|
+
corsErrorModal: (config === null || config === void 0 ? void 0 : config.corsErrorModal) ?? true
|
|
83
84
|
};
|
|
84
85
|
};
|
|
85
86
|
exports.makeConfig = makeConfig;
|
|
@@ -15,6 +15,7 @@ var _reducer = require("../../reducer");
|
|
|
15
15
|
var _ComponentsContext = _interopRequireDefault(require("../ComponentsContext"));
|
|
16
16
|
var _UrlContext = _interopRequireDefault(require("../UrlContext"));
|
|
17
17
|
var _retryImport = _interopRequireDefault(require("../../retryImport"));
|
|
18
|
+
var _corsError = require("../../corsError");
|
|
18
19
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
20
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
20
21
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
@@ -35,6 +36,7 @@ function FontdueProviderClientComponent(_ref) {
|
|
|
35
36
|
stripeIntegration
|
|
36
37
|
});
|
|
37
38
|
const configValue = (0, _ConfigContext.makeConfig)(config);
|
|
39
|
+
(0, _corsError.setCorsModalEnabled)(configValue.corsErrorModal);
|
|
38
40
|
const storeRef = (0, _react.useRef)(store ?? (0, _reducer.createDefaultStore)(config));
|
|
39
41
|
return /*#__PURE__*/_react.default.createElement(_reactRelay.RelayEnvironmentProvider, {
|
|
40
42
|
environment: environment
|
|
@@ -354,13 +354,17 @@ function StoreModalUnifiedCheckout(_ref2) {
|
|
|
354
354
|
// Only update if the country has actually changed
|
|
355
355
|
if (countryVariableSelection.countryCode === licenseeIdentity.country) return;
|
|
356
356
|
|
|
357
|
-
// Build updated selections array
|
|
357
|
+
// Build updated selections array. For country-type variables, send
|
|
358
|
+
// countryCode and clear orderVariableOptionId — the server derives the
|
|
359
|
+
// option from the country. Carrying forward the previous country's option
|
|
360
|
+
// id conflicts with the new country's option.
|
|
358
361
|
const updatedSelections = order.orderVariableSelections.map(selection => {
|
|
359
362
|
var _selection$orderVaria;
|
|
363
|
+
const isCountryVariable = selection.orderVariable.variableType === 'country';
|
|
360
364
|
return {
|
|
361
365
|
orderVariableId: selection.orderVariable.id,
|
|
362
|
-
orderVariableOptionId: ((_selection$orderVaria = selection.orderVariableOption) === null || _selection$orderVaria === void 0 ? void 0 : _selection$orderVaria.id) ?? null,
|
|
363
|
-
countryCode:
|
|
366
|
+
orderVariableOptionId: isCountryVariable ? null : ((_selection$orderVaria = selection.orderVariableOption) === null || _selection$orderVaria === void 0 ? void 0 : _selection$orderVaria.id) ?? null,
|
|
367
|
+
countryCode: isCountryVariable ? licenseeIdentity.country : selection.countryCode ?? null
|
|
364
368
|
};
|
|
365
369
|
});
|
|
366
370
|
|
package/dist/corsError.d.ts
CHANGED
package/dist/corsError.js
CHANGED
|
@@ -4,12 +4,17 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.handlePossibleCorsError = handlePossibleCorsError;
|
|
7
|
+
exports.setCorsModalEnabled = setCorsModalEnabled;
|
|
7
8
|
var _retryImport = _interopRequireDefault(require("./retryImport"));
|
|
8
9
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
10
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
10
11
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
11
12
|
let detected = false;
|
|
12
13
|
let navigating = false;
|
|
14
|
+
let modalEnabled = true;
|
|
15
|
+
function setCorsModalEnabled(enabled) {
|
|
16
|
+
modalEnabled = enabled;
|
|
17
|
+
}
|
|
13
18
|
if (typeof window !== 'undefined') {
|
|
14
19
|
window.addEventListener('beforeunload', () => {
|
|
15
20
|
navigating = true;
|
|
@@ -52,15 +57,17 @@ async function isCorsBlocked(fetchUrl) {
|
|
|
52
57
|
}
|
|
53
58
|
function showCorsError(origin, fetchUrl) {
|
|
54
59
|
console.error(`[Fontdue] Cross-origin request to ${fetchUrl} was blocked.\n\n` + `Your website (${origin}) is not listed as an allowed origin ` + `in your Fontdue CORS settings.\n\n` + `To fix this:\n` + `1. Log in to your Fontdue dashboard\n` + `2. Go to Settings \u2192 Security\n` + `3. Add "${origin}" to the "Cross-origin API access" field\n` + `4. Save \u2014 this page will reload automatically`);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
if (modalEnabled) {
|
|
61
|
+
(0, _retryImport.default)(() => Promise.resolve().then(() => _interopRequireWildcard(require('./components/CorsErrorModal')))).then(_ref => {
|
|
62
|
+
let {
|
|
63
|
+
renderCorsErrorModal
|
|
64
|
+
} = _ref;
|
|
65
|
+
renderCorsErrorModal(origin, fetchUrl);
|
|
66
|
+
}).catch(() => {
|
|
67
|
+
// Chunk failed to load — the console.error above already
|
|
68
|
+
// told the developer what's wrong.
|
|
69
|
+
});
|
|
70
|
+
}
|
|
64
71
|
startPolling(fetchUrl);
|
|
65
72
|
}
|
|
66
73
|
function handlePossibleCorsError(error, fetchUrl) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// fbjs (transitive via draft-js) references Node's `global` at module init.
|
|
2
|
+
// Browsers don't define `global`, so hydration blows up with a ReferenceError.
|
|
3
|
+
// ESM evaluates imports in source order, so importing this first ensures the
|
|
4
|
+
// alias is in place before fbjs/setImmediate evaluates.
|
|
5
|
+
if (typeof globalThis.global === 'undefined') {
|
|
6
|
+
globalThis.global = globalThis;
|
|
7
|
+
}
|
|
8
|
+
export {};
|
|
@@ -23,52 +23,61 @@ const CACHE_TTL = 10 * 1000; // 10 seconds, to resolve preloaded results
|
|
|
23
23
|
function createNetworkFetch(options) {
|
|
24
24
|
return async function networkFetch(request, variables) {
|
|
25
25
|
const url = (FONTDUE_URL && `${FONTDUE_URL}/graphql`) ?? ((options === null || options === void 0 ? void 0 : options.url) ?? '') + '/graphql';
|
|
26
|
-
let
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
26
|
+
for (let attempt = 0; attempt <= 2; attempt++) {
|
|
27
|
+
try {
|
|
28
|
+
const resp = await fetch(url + `?queryName=${request.name}`, {
|
|
29
|
+
method: 'POST',
|
|
30
|
+
credentials: 'include',
|
|
31
|
+
headers: {
|
|
32
|
+
Accept: 'application/json',
|
|
33
|
+
'Content-Type': 'application/json',
|
|
34
|
+
'fontdue-stripe-integration': STRIPE_INTEGRATION ?? ((options === null || options === void 0 ? void 0 : options.stripeIntegration) || 'dynamic'),
|
|
35
|
+
'fontdue-client-version': _package.version
|
|
36
|
+
},
|
|
37
|
+
body: JSON.stringify({
|
|
38
|
+
query: request.text,
|
|
39
|
+
variables
|
|
40
|
+
}),
|
|
41
|
+
// @ts-ignore
|
|
42
|
+
next: {
|
|
43
|
+
tags: ['graphql', `operation:${request.name}`]
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const json = await resp.json();
|
|
47
|
+
|
|
48
|
+
// GraphQL returns exceptions (for example, a missing required variable) in the "errors"
|
|
49
|
+
// property of the response. If any exceptions occurred when processing the request,
|
|
50
|
+
// throw an error to indicate to the developer what went wrong.
|
|
51
|
+
if (Array.isArray(json.errors)) {
|
|
52
|
+
var _json$errors, _error$extensions;
|
|
53
|
+
const error = (_json$errors = json.errors) === null || _json$errors === void 0 ? void 0 : _json$errors[0];
|
|
54
|
+
console.error('GraphQL Error:', {
|
|
55
|
+
message: error.message,
|
|
56
|
+
code: (_error$extensions = error.extensions) === null || _error$extensions === void 0 ? void 0 : _error$extensions.code,
|
|
57
|
+
path: error.path
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return json;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
// Retry on network errors (TypeError) before falling through to CORS detection
|
|
63
|
+
if (attempt < 2 && error instanceof TypeError) {
|
|
64
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
65
|
+
continue;
|
|
44
66
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
if ((0, _corsError.handlePossibleCorsError)(error, url)) {
|
|
68
|
+
return {
|
|
69
|
+
data: undefined,
|
|
70
|
+
errors: [{
|
|
71
|
+
message: 'Cross-origin request blocked'
|
|
72
|
+
}]
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
throw error;
|
|
54
76
|
}
|
|
55
|
-
throw error;
|
|
56
77
|
}
|
|
57
|
-
const json = await resp.json();
|
|
58
78
|
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
// throw an error to indicate to the developer what went wrong.
|
|
62
|
-
if (Array.isArray(json.errors)) {
|
|
63
|
-
var _json$errors, _error$extensions;
|
|
64
|
-
const error = (_json$errors = json.errors) === null || _json$errors === void 0 ? void 0 : _json$errors[0];
|
|
65
|
-
console.error('GraphQL Error:', {
|
|
66
|
-
message: error.message,
|
|
67
|
-
code: (_error$extensions = error.extensions) === null || _error$extensions === void 0 ? void 0 : _error$extensions.code,
|
|
68
|
-
path: error.path
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
return json;
|
|
79
|
+
// Unreachable — final iteration either returns or throws
|
|
80
|
+
throw new Error('Unexpected: exhausted retries');
|
|
72
81
|
};
|
|
73
82
|
}
|
|
74
83
|
const networkFetch = createNetworkFetch();
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FontdueProvider.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import './chunks/ComponentsContext-CmkN9J4X.js';
|
|
3
|
-
export { T as TypeTesterStandalonePreloadedQueryRenderer, a as default } from './chunks/TypeTesterStandalone-BMWuv8Ca.js';
|
|
4
|
-
import 'react';
|
|
5
|
-
import './index.js';
|
|
6
|
-
import 'react-dom';
|
|
7
|
-
//# sourceMappingURL=TypeTester.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TypeTester.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import React__default from 'react';
|
|
2
|
-
import { c as createNetworkFetch } from './chunks/ComponentsContext-CmkN9J4X.js';
|
|
3
|
-
import { T as TypeTesterStandalonePreloadedQueryRenderer, n as node } from './chunks/TypeTesterStandalone-BMWuv8Ca.js';
|
|
4
|
-
import { F as FontdueProvider } from './chunks/index-C4ak9qTL.js';
|
|
5
|
-
import './index.js';
|
|
6
|
-
import 'react-dom';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* RELAY CACHE KEY NORMALIZATION
|
|
10
|
-
*
|
|
11
|
-
* This type transformation is required to fix a cache key inconsistency issue in Relay.
|
|
12
|
-
*
|
|
13
|
-
* THE PROBLEM:
|
|
14
|
-
* Relay's `getOperationVariables()` function always includes ALL argumentDefinitions
|
|
15
|
-
* from the GraphQL operation, even optional ones, setting them to their defaultValue
|
|
16
|
-
* (typically null). This means when Relay generates cache keys, it creates entries like:
|
|
17
|
-
*
|
|
18
|
-
* Cache Key A: { collectionId: "123", tags: null, excludeTags: null, selectable: true }
|
|
19
|
-
* Cache Key B: { collectionId: "123", selectable: true } // when optional vars omitted
|
|
20
|
-
*
|
|
21
|
-
* Even though these represent the same logical query, they produce different cache keys
|
|
22
|
-
* because `JSON.stringify(stableCopy(variables))` serializes them differently.
|
|
23
|
-
*
|
|
24
|
-
* (This is possibly caused by NextJS RSC data serialization and hydration)
|
|
25
|
-
*
|
|
26
|
-
* THE ROOT CAUSE:
|
|
27
|
-
* - GraphQL schema defines: `$tags: [String!], $excludeTags: [String!]` (optional)
|
|
28
|
-
* - TypeScript generates: `tags?: ReadonlyArray<string> | null`
|
|
29
|
-
* - Relay's argumentDefinitions include: `{ name: "tags", defaultValue: null }`
|
|
30
|
-
* - getOperationVariables() always sets: `operationVariables[def.name] = def.defaultValue`
|
|
31
|
-
*
|
|
32
|
-
* THE SOLUTION:
|
|
33
|
-
* RequireAllWithNull<T> transforms optional properties to required properties with
|
|
34
|
-
* explicit null values, forcing callers to be consistent. This ensures server-side
|
|
35
|
-
* preloaded queries and client-side cache lookups use identical variable structures.
|
|
36
|
-
*
|
|
37
|
-
* USAGE:
|
|
38
|
-
* Instead of: { tags, excludeTags } // undefined values
|
|
39
|
-
* Use: { tags: tags ?? null, excludeTags: excludeTags ?? null } // explicit nulls
|
|
40
|
-
*
|
|
41
|
-
* This eliminates cache misses caused by variable structure inconsistencies between
|
|
42
|
-
* server-side rendering and client-side Relay operations.
|
|
43
|
-
*/
|
|
44
|
-
|
|
45
|
-
// Call into raw network fetch to get serializable GraphQL query response
|
|
46
|
-
// This response will be sent to the client to "warm" the QueryResponseCache
|
|
47
|
-
// to avoid the client fetches.
|
|
48
|
-
async function loadSerializableQuery(query, variables, options) {
|
|
49
|
-
if (!('params' in query)) throw new Error('Params not found in query, is it a fragment instead of a query?');
|
|
50
|
-
const fetcher = createNetworkFetch(options);
|
|
51
|
-
const response = await fetcher(query.params, variables);
|
|
52
|
-
return {
|
|
53
|
-
params: query.params,
|
|
54
|
-
variables,
|
|
55
|
-
response
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async function loadTypeTesterQuery(variables, options) {
|
|
60
|
-
return loadSerializableQuery(node, {
|
|
61
|
-
familyName: variables.familyName,
|
|
62
|
-
styleName: variables.styleName,
|
|
63
|
-
selectable: variables.selectable ?? true
|
|
64
|
-
}, options);
|
|
65
|
-
}
|
|
66
|
-
// Self-wraps with FontdueProvider so consumers don't need to. The provider
|
|
67
|
-
// state is a module-level singleton under the hood, so multiple
|
|
68
|
-
// TypeTesterPreloaded (or other *Preloaded) components on a page all share
|
|
69
|
-
// one Relay env + Redux store + auxiliary UI.
|
|
70
|
-
function TypeTesterPreloaded(props) {
|
|
71
|
-
return /*#__PURE__*/React__default.createElement(FontdueProvider, null, /*#__PURE__*/React__default.createElement(TypeTesterStandalonePreloadedQueryRenderer, props));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export { TypeTesterPreloaded, loadTypeTesterQuery };
|
|
75
|
-
//# sourceMappingURL=TypeTester.preload.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TypeTester.preload.js","sources":["../src/relay/loadSerializableQuery.ts","../src/components/TypeTester/TypeTesterStandalone.preload.tsx"],"sourcesContent":["import {\n GraphQLResponse,\n GraphQLTaggedNode,\n OperationType,\n RequestParameters,\n VariablesOf,\n} from 'relay-runtime';\nimport { createNetworkFetch } from './environment';\n\nexport interface SerializablePreloadedQuery<TQuery extends OperationType> {\n params: RequestParameters;\n variables: VariablesOf<TQuery>;\n response: GraphQLResponse;\n}\n\n/**\n * RELAY CACHE KEY NORMALIZATION\n *\n * This type transformation is required to fix a cache key inconsistency issue in Relay.\n *\n * THE PROBLEM:\n * Relay's `getOperationVariables()` function always includes ALL argumentDefinitions\n * from the GraphQL operation, even optional ones, setting them to their defaultValue\n * (typically null). This means when Relay generates cache keys, it creates entries like:\n *\n * Cache Key A: { collectionId: \"123\", tags: null, excludeTags: null, selectable: true }\n * Cache Key B: { collectionId: \"123\", selectable: true } // when optional vars omitted\n *\n * Even though these represent the same logical query, they produce different cache keys\n * because `JSON.stringify(stableCopy(variables))` serializes them differently.\n *\n * (This is possibly caused by NextJS RSC data serialization and hydration)\n *\n * THE ROOT CAUSE:\n * - GraphQL schema defines: `$tags: [String!], $excludeTags: [String!]` (optional)\n * - TypeScript generates: `tags?: ReadonlyArray<string> | null`\n * - Relay's argumentDefinitions include: `{ name: \"tags\", defaultValue: null }`\n * - getOperationVariables() always sets: `operationVariables[def.name] = def.defaultValue`\n *\n * THE SOLUTION:\n * RequireAllWithNull<T> transforms optional properties to required properties with\n * explicit null values, forcing callers to be consistent. This ensures server-side\n * preloaded queries and client-side cache lookups use identical variable structures.\n *\n * USAGE:\n * Instead of: { tags, excludeTags } // undefined values\n * Use: { tags: tags ?? null, excludeTags: excludeTags ?? null } // explicit nulls\n *\n * This eliminates cache misses caused by variable structure inconsistencies between\n * server-side rendering and client-side Relay operations.\n */\ntype RequireAllWithNull<T> = {\n [K in keyof T]-?: T[K] | null;\n};\n\nexport interface LoadSerializableQueryOptions {\n url?: string;\n stripeIntegration?: 'card-element' | 'dynamic';\n}\n\n// Call into raw network fetch to get serializable GraphQL query response\n// This response will be sent to the client to \"warm\" the QueryResponseCache\n// to avoid the client fetches.\nexport default async function loadSerializableQuery<TQuery extends OperationType>(\n query: GraphQLTaggedNode,\n variables: RequireAllWithNull<VariablesOf<TQuery>>,\n options?: LoadSerializableQueryOptions,\n): Promise<SerializablePreloadedQuery<TQuery>> {\n if (!('params' in query))\n throw new Error('Params not found in query, is it a fragment instead of a query?');\n const fetcher = createNetworkFetch(options);\n const response = await fetcher(query.params, variables);\n\n return {\n params: query.params,\n variables,\n response,\n };\n}\n","import React from 'react';\nimport loadSerializableQuery, {\n LoadSerializableQueryOptions,\n SerializablePreloadedQuery,\n} from '../../relay/loadSerializableQuery';\nimport TypeTesterStandaloneQueryNode, {\n TypeTesterStandaloneQuery,\n} from '../../__generated__/TypeTesterStandaloneQuery.graphql';\nimport FontdueProvider from '../FontdueProvider';\nimport { TypeTesterStandalonePreloadedQueryRenderer } from './TypeTesterStandalone';\n\nexport type TypeTesterPreloadedQuery =\n SerializablePreloadedQuery<TypeTesterStandaloneQuery>;\n\nexport interface LoadTypeTesterQueryVariables {\n familyName: string;\n styleName: string;\n selectable?: boolean;\n}\n\nexport async function loadTypeTesterQuery(\n variables: LoadTypeTesterQueryVariables,\n options?: LoadSerializableQueryOptions,\n): Promise<TypeTesterPreloadedQuery> {\n return loadSerializableQuery<TypeTesterStandaloneQuery>(\n TypeTesterStandaloneQueryNode,\n {\n familyName: variables.familyName,\n styleName: variables.styleName,\n selectable: variables.selectable ?? true,\n },\n options,\n );\n}\n\ntype RendererProps = React.ComponentProps<typeof TypeTesterStandalonePreloadedQueryRenderer>;\n\n// Self-wraps with FontdueProvider so consumers don't need to. The provider\n// state is a module-level singleton under the hood, so multiple\n// TypeTesterPreloaded (or other *Preloaded) components on a page all share\n// one Relay env + Redux store + auxiliary UI.\nexport function TypeTesterPreloaded(props: RendererProps) {\n return (\n <FontdueProvider>\n <TypeTesterStandalonePreloadedQueryRenderer {...props} />\n </FontdueProvider>\n );\n}\n"],"names":["loadSerializableQuery","query","variables","options","Error","fetcher","createNetworkFetch","response","params","loadTypeTesterQuery","TypeTesterStandaloneQueryNode","familyName","styleName","selectable","TypeTesterPreloaded","props","React","createElement","FontdueProvider","TypeTesterStandalonePreloadedQueryRenderer"],"mappings":";;;;;;;AAeA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAUA;AACA;AACA;AACe,eAAeA,qBAAqBA,CACjDC,KAAwB,EACxBC,SAAkD,EAClDC,OAAsC,EACO;EAC7C,IAAI,EAAE,QAAQ,IAAIF,KAAK,CAAC,EACtB,MAAM,IAAIG,KAAK,CAAC,iEAAiE,CAAC;AACpF,EAAA,MAAMC,OAAO,GAAGC,kBAAkB,CAACH,OAAO,CAAC;EAC3C,MAAMI,QAAQ,GAAG,MAAMF,OAAO,CAACJ,KAAK,CAACO,MAAM,EAAEN,SAAS,CAAC;EAEvD,OAAO;IACLM,MAAM,EAAEP,KAAK,CAACO,MAAM;IACpBN,SAAS;AACTK,IAAAA;GACD;AACH;;AC1DO,eAAeE,mBAAmBA,CACvCP,SAAuC,EACvCC,OAAsC,EACH;EACnC,OAAOH,qBAAqB,CAC1BU,IAA6B,EAC7B;IACEC,UAAU,EAAET,SAAS,CAACS,UAAU;IAChCC,SAAS,EAAEV,SAAS,CAACU,SAAS;AAC9BC,IAAAA,UAAU,EAAEX,SAAS,CAACW,UAAU,IAAI;GACrC,EACDV,OACF,CAAC;AACH;AAIA;AACA;AACA;AACA;AACO,SAASW,mBAAmBA,CAACC,KAAoB,EAAE;AACxD,EAAA,oBACEC,cAAA,CAAAC,aAAA,CAACC,eAAe,EAAA,IAAA,eACdF,cAAA,CAAAC,aAAA,CAACE,0CAA0C,EAAKJ,KAAQ,CACzC,CAAC;AAEtB;;;;"}
|