Spaces:
Running
Running
ling-open-studio / node_modules /next /dist /server /app-render /instant-validation /instant-samples.js
| ; | |
| Object.defineProperty(exports, "__esModule", { | |
| value: true | |
| }); | |
| 0 && (module.exports = { | |
| assertRootParamInSamples: null, | |
| createCookiesFromSample: null, | |
| createDraftModeForValidation: null, | |
| createExhaustiveParamsProxy: null, | |
| createExhaustiveSearchParamsProxy: null, | |
| createExhaustiveURLSearchParamsProxy: null, | |
| createHeadersFromSample: null, | |
| createRelativeURLFromSamples: null, | |
| createValidationSampleTracking: null, | |
| trackMissingSampleError: null, | |
| trackMissingSampleErrorAndThrow: null | |
| }); | |
| function _export(target, all) { | |
| for(var name in all)Object.defineProperty(target, name, { | |
| enumerable: true, | |
| get: all[name] | |
| }); | |
| } | |
| _export(exports, { | |
| assertRootParamInSamples: function() { | |
| return assertRootParamInSamples; | |
| }, | |
| createCookiesFromSample: function() { | |
| return createCookiesFromSample; | |
| }, | |
| createDraftModeForValidation: function() { | |
| return createDraftModeForValidation; | |
| }, | |
| createExhaustiveParamsProxy: function() { | |
| return createExhaustiveParamsProxy; | |
| }, | |
| createExhaustiveSearchParamsProxy: function() { | |
| return createExhaustiveSearchParamsProxy; | |
| }, | |
| createExhaustiveURLSearchParamsProxy: function() { | |
| return createExhaustiveURLSearchParamsProxy; | |
| }, | |
| createHeadersFromSample: function() { | |
| return createHeadersFromSample; | |
| }, | |
| createRelativeURLFromSamples: function() { | |
| return createRelativeURLFromSamples; | |
| }, | |
| createValidationSampleTracking: function() { | |
| return createValidationSampleTracking; | |
| }, | |
| trackMissingSampleError: function() { | |
| return trackMissingSampleError; | |
| }, | |
| trackMissingSampleErrorAndThrow: function() { | |
| return trackMissingSampleErrorAndThrow; | |
| } | |
| }); | |
| const _cookies = require("../../web/spec-extension/cookies"); | |
| const _requestcookies = require("../../web/spec-extension/adapters/request-cookies"); | |
| const _headers = require("../../web/spec-extension/adapters/headers"); | |
| const _getsegmentparam = require("../../../shared/lib/router/utils/get-segment-param"); | |
| const _parserelativeurl = require("../../../shared/lib/router/utils/parse-relative-url"); | |
| const _invarianterror = require("../../../shared/lib/invariant-error"); | |
| const _instantvalidationerror = require("./instant-validation-error"); | |
| const _workunitasyncstorageexternal = require("../work-unit-async-storage.external"); | |
| const _reflectutils = require("../../../shared/lib/utils/reflect-utils"); | |
| function createValidationSampleTracking() { | |
| return { | |
| missingSampleErrors: [] | |
| }; | |
| } | |
| function getExpectedSampleTracking() { | |
| let validationSampleTracking = null; | |
| const workUnitStore = _workunitasyncstorageexternal.workUnitAsyncStorage.getStore(); | |
| if (workUnitStore) { | |
| switch(workUnitStore.type){ | |
| case 'request': | |
| case 'validation-client': | |
| // TODO(instant-validation-build): do we need any special handling for caches? | |
| validationSampleTracking = workUnitStore.validationSampleTracking ?? null; | |
| break; | |
| case 'cache': | |
| case 'private-cache': | |
| case 'unstable-cache': | |
| case 'prerender-legacy': | |
| case 'prerender-ppr': | |
| case 'prerender-client': | |
| case 'prerender': | |
| case 'prerender-runtime': | |
| case 'generate-static-params': | |
| break; | |
| default: | |
| workUnitStore; | |
| } | |
| } | |
| if (!validationSampleTracking) { | |
| throw Object.defineProperty(new _invarianterror.InvariantError('Expected to have a workUnitStore that provides validationSampleTracking'), "__NEXT_ERROR_CODE", { | |
| value: "E1110", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| return validationSampleTracking; | |
| } | |
| function trackMissingSampleError(error) { | |
| const validationSampleTracking = getExpectedSampleTracking(); | |
| validationSampleTracking.missingSampleErrors.push(error); | |
| } | |
| function trackMissingSampleErrorAndThrow(error) { | |
| // TODO(instant-validation-build): this should abort the render | |
| trackMissingSampleError(error); | |
| throw error; | |
| } | |
| function createCookiesFromSample(sampleCookies, route) { | |
| const declaredNames = new Set(); | |
| const cookies = new _cookies.RequestCookies(new Headers()); | |
| if (sampleCookies) { | |
| for (const cookie of sampleCookies){ | |
| declaredNames.add(cookie.name); | |
| if (cookie.value !== null) { | |
| cookies.set(cookie.name, cookie.value); | |
| } | |
| } | |
| } | |
| const sealed = _requestcookies.RequestCookiesAdapter.seal(cookies); | |
| return new Proxy(sealed, { | |
| get (target, prop, receiver) { | |
| if (prop === 'has') { | |
| const originalMethod = Reflect.get(target, prop, receiver); | |
| const wrappedMethod = function(name) { | |
| if (!declaredNames.has(name)) { | |
| trackMissingSampleErrorAndThrow(createMissingCookieSampleError(route, name)); | |
| } | |
| return originalMethod.call(target, name); | |
| }; | |
| return wrappedMethod; | |
| } | |
| if (prop === 'get') { | |
| const originalMethod = Reflect.get(target, prop, receiver); | |
| const wrappedMethod = function(nameOrCookie) { | |
| let name; | |
| if (typeof nameOrCookie === 'string') { | |
| name = nameOrCookie; | |
| } else if (nameOrCookie && typeof nameOrCookie === 'object' && typeof nameOrCookie.name === 'string') { | |
| name = nameOrCookie.name; | |
| } else { | |
| // This is an invalid input. Pass it through to the original method so it can error. | |
| return originalMethod.call(target, nameOrCookie); | |
| } | |
| if (!declaredNames.has(name)) { | |
| trackMissingSampleErrorAndThrow(createMissingCookieSampleError(route, name)); | |
| } | |
| return originalMethod.call(target, name); | |
| }; | |
| return wrappedMethod; | |
| } | |
| // TODO(instant-validation-build): what should getAll do? | |
| // Maybe we should only allow it if there's an array (possibly empty?) | |
| return Reflect.get(target, prop, receiver); | |
| } | |
| }); | |
| } | |
| function createMissingCookieSampleError(route, name) { | |
| return Object.defineProperty(new _instantvalidationerror.InstantValidationError(`Route "${route}" accessed cookie "${name}" which is not defined in the \`samples\` ` + `of \`unstable_instant\`. Add it to the sample's \`cookies\` array, ` + `or \`{ name: "${name}", value: null }\` if it should be absent.`), "__NEXT_ERROR_CODE", { | |
| value: "E1115", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| function createHeadersFromSample(rawSampleHeaders, sampleCookies, route) { | |
| // If we have cookie samples, add a `cookie` header to match. | |
| // Accessing it will be implicitly allowed by the proxy -- | |
| // if the user defined some cookies, accessing the "cookie" header is also fine. | |
| const sampleHeaders = rawSampleHeaders ? [ | |
| ...rawSampleHeaders | |
| ] : []; | |
| if (sampleHeaders.find(([name])=>name.toLowerCase() === 'cookie')) { | |
| throw Object.defineProperty(new _instantvalidationerror.InstantValidationError('Invalid sample: Defining cookies via a "cookie" header is not supported. Use `cookies: [{ name: ..., value: ... }]` instead.'), "__NEXT_ERROR_CODE", { | |
| value: "E1111", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| if (sampleCookies) { | |
| const cookieHeaderValue = sampleCookies.toString(); | |
| sampleHeaders.push([ | |
| 'cookie', | |
| // if the `cookies` samples were empty, or they were all `null`, then we have no cookies, | |
| // and the header isn't present, but should remains readable, so we set it to null. | |
| cookieHeaderValue !== '' ? cookieHeaderValue : null | |
| ]); | |
| } | |
| const declaredNames = new Set(); | |
| const headersInit = {}; | |
| for (const [name, value] of sampleHeaders){ | |
| declaredNames.add(name.toLowerCase()); | |
| if (value !== null) { | |
| headersInit[name.toLowerCase()] = value; | |
| } | |
| } | |
| const sealed = _headers.HeadersAdapter.seal(_headers.HeadersAdapter.from(headersInit)); | |
| return new Proxy(sealed, { | |
| get (target, prop, receiver) { | |
| if (prop === 'get' || prop === 'has') { | |
| const originalMethod = Reflect.get(target, prop, receiver); | |
| const patchedMethod = function(rawName) { | |
| const name = rawName.toLowerCase(); | |
| if (!declaredNames.has(name)) { | |
| trackMissingSampleErrorAndThrow(Object.defineProperty(new _instantvalidationerror.InstantValidationError(`Route "${route}" accessed header "${name}" which is not defined in the \`samples\` ` + `of \`unstable_instant\`. Add it to the sample's \`headers\` array, ` + `or \`["${name}", null]\` if it should be absent.`), "__NEXT_ERROR_CODE", { | |
| value: "E1116", | |
| enumerable: false, | |
| configurable: true | |
| })); | |
| } | |
| // typescript can't reconcile a union of functions with a union of return types, | |
| // so we have to cast the original return type away | |
| return originalMethod.call(target, name); | |
| }; | |
| return patchedMethod; | |
| } | |
| return Reflect.get(target, prop, receiver); | |
| } | |
| }); | |
| } | |
| function createDraftModeForValidation() { | |
| // Create a minimal DraftModeProvider-compatible object | |
| // that always reports draft mode as disabled. | |
| // | |
| // private properties that can't be set from outside the class. | |
| return { | |
| get isEnabled () { | |
| return false; | |
| }, | |
| enable () { | |
| throw Object.defineProperty(new Error('Draft mode cannot be enabled during build-time instant validation.'), "__NEXT_ERROR_CODE", { | |
| value: "E1092", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| }, | |
| disable () { | |
| throw Object.defineProperty(new Error('Draft mode cannot be disabled during build-time instant validation.'), "__NEXT_ERROR_CODE", { | |
| value: "E1094", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| }; | |
| } | |
| function createExhaustiveParamsProxy(underlyingParams, declaredParamNames, route) { | |
| return new Proxy(underlyingParams, { | |
| get (target, prop, receiver) { | |
| if (typeof prop === 'string' && !_reflectutils.wellKnownProperties.has(prop) && // Only error when accessing a param that is part of the route but wasn't provided. | |
| // accessing properties that aren't expected to be a valid param value is fine. | |
| prop in underlyingParams && !declaredParamNames.has(prop)) { | |
| trackMissingSampleErrorAndThrow(Object.defineProperty(new _instantvalidationerror.InstantValidationError(`Route "${route}" accessed param "${prop}" which is not defined in the \`samples\` ` + `of \`unstable_instant\`. Add it to the sample's \`params\` object.`), "__NEXT_ERROR_CODE", { | |
| value: "E1095", | |
| enumerable: false, | |
| configurable: true | |
| })); | |
| } | |
| return Reflect.get(target, prop, receiver); | |
| } | |
| }); | |
| } | |
| function createExhaustiveSearchParamsProxy(searchParams, declaredSearchParamNames, route) { | |
| return new Proxy(searchParams, { | |
| get (target, prop, receiver) { | |
| if (typeof prop === 'string' && !_reflectutils.wellKnownProperties.has(prop) && !declaredSearchParamNames.has(prop)) { | |
| trackMissingSampleErrorAndThrow(createMissingSearchParamSampleError(route, prop)); | |
| } | |
| return Reflect.get(target, prop, receiver); | |
| }, | |
| has (target, prop) { | |
| if (typeof prop === 'string' && !_reflectutils.wellKnownProperties.has(prop) && !declaredSearchParamNames.has(prop)) { | |
| trackMissingSampleErrorAndThrow(createMissingSearchParamSampleError(route, prop)); | |
| } | |
| return Reflect.has(target, prop); | |
| } | |
| }); | |
| } | |
| function createExhaustiveURLSearchParamsProxy(searchParams, declaredSearchParamNames, route) { | |
| return new Proxy(searchParams, { | |
| get (target, prop, receiver) { | |
| // Intercept method calls that access specific param names | |
| if (prop === 'get' || prop === 'getAll' || prop === 'has') { | |
| const originalMathod = Reflect.get(target, prop, receiver); | |
| return (name)=>{ | |
| if (typeof name === 'string' && !declaredSearchParamNames.has(name)) { | |
| trackMissingSampleErrorAndThrow(createMissingSearchParamSampleError(route, name)); | |
| } | |
| return originalMathod.call(target, name); | |
| }; | |
| } | |
| const value = Reflect.get(target, prop, receiver); | |
| // Prevent `TypeError: Value of "this" must be of type URLSearchParams` for methods | |
| if (typeof value === 'function' && !Object.hasOwn(target, prop)) { | |
| return value.bind(target); | |
| } | |
| return value; | |
| } | |
| }); | |
| } | |
| function createMissingSearchParamSampleError(route, name) { | |
| return Object.defineProperty(new _instantvalidationerror.InstantValidationError(`Route "${route}" accessed searchParam "${name}" which is not defined in the \`samples\` ` + `of \`unstable_instant\`. Add it to the sample's \`searchParams\` object, ` + `or \`{ "${name}": null }\` if it should be absent.`), "__NEXT_ERROR_CODE", { | |
| value: "E1098", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| function createRelativeURLFromSamples(route, sampleParams, sampleSearchParams) { | |
| // Build searchParams query object and URL search string from sample | |
| const pathname = createPathnameFromRouteAndSampleParams(route, sampleParams ?? {}); | |
| let search = ''; | |
| if (sampleSearchParams) { | |
| const qs = createURLSearchParamsFromSample(sampleSearchParams).toString(); | |
| if (qs) { | |
| search = '?' + qs; | |
| } | |
| } | |
| return (0, _parserelativeurl.parseRelativeUrl)(pathname + search, undefined, true); | |
| } | |
| function createURLSearchParamsFromSample(sampleSearchParams) { | |
| const result = new URLSearchParams(); | |
| if (sampleSearchParams) { | |
| for (const [key, value] of Object.entries(sampleSearchParams)){ | |
| if (value === null || value === undefined) continue; | |
| if (Array.isArray(value)) { | |
| for (const v of value){ | |
| result.append(key, v); | |
| } | |
| } else { | |
| result.set(key, value); | |
| } | |
| } | |
| } | |
| return result; | |
| } | |
| /** | |
| * Substitute sample params into `workStore.route` to create a plausible pathname. | |
| * TODO(instant-validation-build): this logic is somewhat hacky and likely incomplete, | |
| * but it should be good enough for some initial testing. | |
| */ function createPathnameFromRouteAndSampleParams(route, params) { | |
| let interpolatedSegments = []; | |
| const rawSegments = route.split('/'); | |
| for (const rawSegment of rawSegments){ | |
| const param = (0, _getsegmentparam.getSegmentParam)(rawSegment); | |
| if (param) { | |
| switch(param.paramType){ | |
| case 'catchall': | |
| case 'optional-catchall': | |
| { | |
| let paramValue = params[param.paramName]; | |
| if (paramValue === undefined) { | |
| // The value for the param was not provided. `usePathname` will detect this and throw | |
| // before this can surface to userspace. Use `[...NAME]` as a placeholder for the param value | |
| // in case it pops up somewhere unexpectedly. | |
| paramValue = [ | |
| rawSegment | |
| ]; | |
| } else if (!Array.isArray(paramValue)) { | |
| // NOTE: this happens outside of render, so we don't need `trackMissingSampleErrorAndThrow` | |
| throw Object.defineProperty(new _instantvalidationerror.InstantValidationError(`Expected sample param value for segment '${rawSegment}' to be an array of strings, got ${typeof paramValue}`), "__NEXT_ERROR_CODE", { | |
| value: "E1104", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| interpolatedSegments.push(...paramValue.map((v)=>encodeURIComponent(v))); | |
| break; | |
| } | |
| case 'dynamic': | |
| { | |
| let paramValue = params[param.paramName]; | |
| if (paramValue === undefined) { | |
| // The value for the param was not provided. `usePathname` will detect this and throw | |
| // before this can surface to userspace. Use `[NAME]` as a placeholder for the param value | |
| // in case it pops up somewhere unexpectedly. | |
| paramValue = rawSegment; | |
| } else if (typeof paramValue !== 'string') { | |
| // NOTE: this happens outside of render, so we don't need `trackMissingSampleErrorAndThrow` | |
| throw Object.defineProperty(new _instantvalidationerror.InstantValidationError(`Expected sample param value for segment '${rawSegment}' to be a string, got ${typeof paramValue}`), "__NEXT_ERROR_CODE", { | |
| value: "E1108", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| interpolatedSegments.push(encodeURIComponent(paramValue)); | |
| break; | |
| } | |
| case 'catchall-intercepted-(..)(..)': | |
| case 'catchall-intercepted-(.)': | |
| case 'catchall-intercepted-(..)': | |
| case 'catchall-intercepted-(...)': | |
| case 'dynamic-intercepted-(..)(..)': | |
| case 'dynamic-intercepted-(.)': | |
| case 'dynamic-intercepted-(..)': | |
| case 'dynamic-intercepted-(...)': | |
| { | |
| // TODO(instant-validation-build): i don't know how these are supposed to work, or if we can even get them here | |
| throw Object.defineProperty(new _invarianterror.InvariantError('Not implemented: Validation of interception routes'), "__NEXT_ERROR_CODE", { | |
| value: "E1106", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| default: | |
| { | |
| param.paramType; | |
| } | |
| } | |
| } else { | |
| interpolatedSegments.push(rawSegment); | |
| } | |
| } | |
| return interpolatedSegments.join('/'); | |
| } | |
| function assertRootParamInSamples(workStore, sampleParams, paramName) { | |
| if (sampleParams && paramName in sampleParams) { | |
| // The param is defined in the samples. | |
| } else { | |
| const route = workStore.route; | |
| trackMissingSampleErrorAndThrow(Object.defineProperty(new _instantvalidationerror.InstantValidationError(`Route "${route}" accessed root param "${paramName}" which is not defined in the \`samples\` ` + `of \`unstable_instant\`. Add it to the sample's \`params\` object.`), "__NEXT_ERROR_CODE", { | |
| value: "E1114", | |
| enumerable: false, | |
| configurable: true | |
| })); | |
| } | |
| } | |
| //# sourceMappingURL=instant-samples.js.map |