next-page-config.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = nextPageConfig;
  6. var _core = require("next/dist/compiled/babel/core");
  7. var _constants = require("../../../shared/lib/constants");
  8. function nextPageConfig({ types: t }) {
  9. return {
  10. visitor: {
  11. Program: {
  12. enter (path, state) {
  13. path.traverse({
  14. ExportDeclaration (exportPath, exportState) {
  15. var ref;
  16. if (_core.types.isExportNamedDeclaration(exportPath) && ((ref = exportPath.node.specifiers) == null ? void 0 : ref.some((specifier)=>{
  17. return (t.isIdentifier(specifier.exported) ? specifier.exported.name : specifier.exported.value) === CONFIG_KEY;
  18. })) && _core.types.isStringLiteral(exportPath.node.source)) {
  19. throw new Error(errorMessage(exportState, "Expected object but got export from"));
  20. }
  21. },
  22. ExportNamedDeclaration (exportPath, exportState) {
  23. var ref, ref1;
  24. if (exportState.bundleDropped || !exportPath.node.declaration && exportPath.node.specifiers.length === 0) {
  25. return;
  26. }
  27. const config = {};
  28. const declarations = [
  29. ...((ref = exportPath.node.declaration) == null ? void 0 : ref.declarations) || [],
  30. (ref1 = exportPath.scope.getBinding(CONFIG_KEY)) == null ? void 0 : ref1.path.node,
  31. ].filter(Boolean);
  32. for (const specifier of exportPath.node.specifiers){
  33. if ((t.isIdentifier(specifier.exported) ? specifier.exported.name : specifier.exported.value) === CONFIG_KEY) {
  34. // export {} from 'somewhere'
  35. if (_core.types.isStringLiteral(exportPath.node.source)) {
  36. throw new Error(errorMessage(exportState, `Expected object but got import`));
  37. // import hello from 'world'
  38. // export { hello as config }
  39. } else if (_core.types.isIdentifier(specifier.local)) {
  40. var ref2;
  41. if (_core.types.isImportSpecifier((ref2 = exportPath.scope.getBinding(specifier.local.name)) == null ? void 0 : ref2.path.node)) {
  42. throw new Error(errorMessage(exportState, `Expected object but got import`));
  43. }
  44. }
  45. }
  46. }
  47. for (const declaration of declarations){
  48. if (!_core.types.isIdentifier(declaration.id, {
  49. name: CONFIG_KEY
  50. })) {
  51. continue;
  52. }
  53. let { init } = declaration;
  54. if (_core.types.isTSAsExpression(init)) {
  55. init = init.expression;
  56. }
  57. if (!_core.types.isObjectExpression(init)) {
  58. const got = init ? init.type : "undefined";
  59. throw new Error(errorMessage(exportState, `Expected object but got ${got}`));
  60. }
  61. for (const prop of init.properties){
  62. if (_core.types.isSpreadElement(prop)) {
  63. throw new Error(errorMessage(exportState, `Property spread is not allowed`));
  64. }
  65. const { name } = prop.key;
  66. if (_core.types.isIdentifier(prop.key, {
  67. name: "amp"
  68. })) {
  69. if (!_core.types.isObjectProperty(prop)) {
  70. throw new Error(errorMessage(exportState, `Invalid property "${name}"`));
  71. }
  72. if (!_core.types.isBooleanLiteral(prop.value) && !_core.types.isStringLiteral(prop.value)) {
  73. throw new Error(errorMessage(exportState, `Invalid value for "${name}"`));
  74. }
  75. config.amp = prop.value.value;
  76. }
  77. }
  78. }
  79. if (config.amp === true) {
  80. var ref3, ref4;
  81. if (!((ref3 = exportState.file) == null ? void 0 : (ref4 = ref3.opts) == null ? void 0 : ref4.caller.isDev)) {
  82. // don't replace bundle in development so HMR can track
  83. // dependencies and trigger reload when they are changed
  84. replaceBundle(exportPath, t);
  85. }
  86. exportState.bundleDropped = true;
  87. return;
  88. }
  89. }
  90. }, state);
  91. }
  92. }
  93. }
  94. };
  95. }
  96. const CONFIG_KEY = "config";
  97. // replace program path with just a variable with the drop identifier
  98. function replaceBundle(path, t) {
  99. path.parentPath.replaceWith(t.program([
  100. t.variableDeclaration("const", [
  101. t.variableDeclarator(t.identifier(_constants.STRING_LITERAL_DROP_BUNDLE), t.stringLiteral(`${_constants.STRING_LITERAL_DROP_BUNDLE} ${Date.now()}`)),
  102. ]),
  103. ], []));
  104. }
  105. function errorMessage(state, details) {
  106. const pageName = (state.filename || "").split(state.cwd || "").pop() || "unknown";
  107. return `Invalid page config export found. ${details} in file ${pageName}. See: https://nextjs.org/docs/messages/invalid-page-config`;
  108. }
  109. //# sourceMappingURL=next-page-config.js.map