Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(core): fix require.context shim for graphql deploys (#2903)
- Loading branch information
1 parent
f298d48
commit 808c459
Showing
9 changed files
with
178 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
require('./_interopReexport')(module.exports, require('./lib/_exports/_internal')) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/** | ||
* esm/commonjs interop reexport helper | ||
* this should be used instead of doing `module.exports = require('./some/file') | ||
* since that doesn't work properly with esm imports from the consuming end | ||
* @param moduleExports export object from the exporting module | ||
* @param importedModule the imported module to be reexported | ||
*/ | ||
module.exports = function _interopReexport(moduleExports, importedModule) { | ||
Object.defineProperty(moduleExports, '__esModule', { | ||
value: true, | ||
}) | ||
|
||
Object.defineProperty(moduleExports, 'default', { | ||
enumerable: true, | ||
get: function get() { | ||
return importedModule.default | ||
}, | ||
}) | ||
|
||
Object.keys(importedModule).forEach(function (key) { | ||
if (key === 'default' || key === '__esModule') return | ||
if (key in moduleExports && moduleExports[key] === importedModule[key]) return | ||
Object.defineProperty(moduleExports, key, { | ||
enumerable: true, | ||
get: function get() { | ||
return importedModule[key] | ||
}, | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {createRequireContext} from '../util/createRequireContext' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// intentionally left blank for now since this package have never had any official package exports before | ||
export {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import path from 'path' | ||
import klaw from 'klaw-sync' | ||
|
||
/** | ||
* https://webpack.js.org/guides/dependency-management/#requirecontext | ||
*/ | ||
interface WebpackRequireContextFactory { | ||
( | ||
directory: string, | ||
useSubdirectories?: boolean, | ||
regExp?: RegExp, | ||
mode?: 'sync' | ||
): WebpackRequireContext | ||
} | ||
|
||
/** | ||
* https://webpack.js.org/guides/dependency-management/#context-module-api | ||
*/ | ||
interface WebpackRequireContext { | ||
(request: string): unknown | ||
|
||
id: string | ||
keys(): string[] | ||
resolve(request: string): unknown | ||
} | ||
|
||
/** | ||
* note, options are primarily for testing | ||
*/ | ||
interface CreateRequireContextOptions { | ||
require?: (request: string) => unknown | ||
resolve?: (request: string) => string | ||
} | ||
|
||
const globalRequire = require | ||
|
||
export function createRequireContext( | ||
dirname: string, | ||
{ | ||
require = globalRequire, | ||
resolve = globalRequire.resolve.bind(globalRequire), | ||
}: CreateRequireContextOptions = {} | ||
): WebpackRequireContextFactory { | ||
function requireContext( | ||
directory: string, | ||
recursive = true, | ||
regExp = /.*/ | ||
): WebpackRequireContext { | ||
console.warn('Usage of `require.context` is deprecated and will break in a future release.') | ||
|
||
try { | ||
const basedir = path.resolve(dirname, directory) | ||
|
||
const keys = klaw(basedir, { | ||
depthLimit: recursive ? 30 : 0, | ||
}) | ||
.filter((item) => !item.stats.isDirectory() && regExp.test(item.path)) | ||
// use relative paths for the keys | ||
.map((item) => path.relative(basedir, item.path)) | ||
// if the path.resolve doesn't prefixed with `./` then add it. | ||
// note it could be upward `../` so we need the conditional | ||
.map((filename) => (filename.startsWith('.') ? filename : `./${filename}`)) | ||
|
||
// eslint-disable-next-line no-inner-declarations | ||
function context(request: string) { | ||
// eslint-disable-next-line import/no-dynamic-require | ||
return require(path.join(basedir, request)) | ||
} | ||
|
||
Object.defineProperty(context, 'id', { | ||
get: () => { | ||
console.warn('`require.context` `context.id` is not supported.') | ||
return '' | ||
}, | ||
}) | ||
|
||
Object.defineProperty(context, 'keys', { | ||
// NOTE: this keys method does not match the behavior of webpack's | ||
// require.context context because it does not return all possible keys | ||
// | ||
// e.g. `./module-a/index.js` | ||
// would return `['./module-a', './module-a/index', './module-a/index.js']` | ||
value: () => keys, | ||
}) | ||
|
||
Object.defineProperty(context, 'resolve', { | ||
value: (request: string) => resolve(path.join(basedir, request)), | ||
}) | ||
|
||
return context as WebpackRequireContext | ||
} catch (contextErr) { | ||
contextErr.message = `Error running require.context():\n\n${contextErr.message}` | ||
throw contextErr | ||
} | ||
} | ||
|
||
return requireContext | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/** | ||
* This file exposes a "register" function which hacks in a `require.context`function, | ||
* mirroring webpacks version (https://webpack.js.org/guides/dependency-management/#requirecontext) | ||
* | ||
* Basically allows you to do `require.context('./types', true, /\.js$/)` to import multiple | ||
* files at the same time. While generally not advised (given it's a webpack-only thing), | ||
* people are already using it in the wild, so it breaks when trying to deploy GraphQL APIs, | ||
* or when running scripts using `sanity exec`. | ||
* | ||
* We have to inject the `require.context` function to each required file, which is done by | ||
* overriding injecting a small script that runs before the start of each file. | ||
*/ | ||
|
||
import path from 'path' | ||
import {addHook} from 'pirates' | ||
|
||
type Revert = ReturnType<typeof addHook> | ||
let revert: Revert | undefined | ||
|
||
const augmentRequire = (dirname: string) => | ||
`if (typeof require !== 'undefined') {const {createRequireContext} = require('@sanity/core/_internal');require.context = createRequireContext(${JSON.stringify( | ||
dirname | ||
)});};` | ||
|
||
export function register(): Revert { | ||
if (revert) return revert | ||
|
||
revert = addHook((code, filename) => `${augmentRequire(path.dirname(filename))}${code}`, { | ||
exts: ['.js', '.ts', '.tsx'], | ||
ignoreNodeModules: true, | ||
}) | ||
|
||
return revert | ||
} |
808c459
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
studio-workshop – ./dev/workshop
studio-workshop.sanity.build
studio-workshop-git-next.sanity.build
808c459
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
test-studio – ./
test-studio-git-next.sanity.build
test-studio.sanity.build
808c459
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
perf-studio – ./
perf-studio.sanity.build
perf-studio-git-next.sanity.build