runtime-caching-converter.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. "use strict";
  2. /*
  3. Copyright 2018 Google LLC
  4. Use of this source code is governed by an MIT-style
  5. license that can be found in the LICENSE file or at
  6. https://opensource.org/licenses/MIT.
  7. */
  8. Object.defineProperty(exports, "__esModule", { value: true });
  9. exports.runtimeCachingConverter = void 0;
  10. const common_tags_1 = require("common-tags");
  11. const errors_1 = require("./errors");
  12. const stringify_without_comments_1 = require("./stringify-without-comments");
  13. /**
  14. * Given a set of options that configures runtime caching behavior, convert it
  15. * to the equivalent Workbox method calls.
  16. *
  17. * @param {ModuleRegistry} moduleRegistry
  18. * @param {Object} options See
  19. * https://developers.google.com/web/tools/workbox/modules/workbox-build#generateSW-runtimeCaching
  20. * @return {string} A JSON string representing the equivalent options.
  21. *
  22. * @private
  23. */
  24. function getOptionsString(moduleRegistry, options = {}) {
  25. const plugins = [];
  26. const handlerOptions = {};
  27. for (const optionName of Object.keys(options)) {
  28. if (options[optionName] === undefined) {
  29. continue;
  30. }
  31. switch (optionName) {
  32. // Using a library here because JSON.stringify won't handle functions.
  33. case 'plugins': {
  34. plugins.push(...options.plugins.map(stringify_without_comments_1.stringifyWithoutComments));
  35. break;
  36. }
  37. // These are the option properties that we want to pull out, so that
  38. // they're passed to the handler constructor.
  39. case 'cacheName':
  40. case 'networkTimeoutSeconds':
  41. case 'fetchOptions':
  42. case 'matchOptions': {
  43. handlerOptions[optionName] = options[optionName];
  44. break;
  45. }
  46. // The following cases are all shorthands for creating a plugin with a
  47. // given configuration.
  48. case 'backgroundSync': {
  49. const name = options.backgroundSync.name;
  50. const plugin = moduleRegistry.use('workbox-background-sync', 'BackgroundSyncPlugin');
  51. let pluginCode = `new ${plugin}(${JSON.stringify(name)}`;
  52. if (options.backgroundSync.options) {
  53. pluginCode += `, ${(0, stringify_without_comments_1.stringifyWithoutComments)(options.backgroundSync.options)}`;
  54. }
  55. pluginCode += `)`;
  56. plugins.push(pluginCode);
  57. break;
  58. }
  59. case 'broadcastUpdate': {
  60. const channelName = options.broadcastUpdate.channelName;
  61. const opts = Object.assign({ channelName }, options.broadcastUpdate.options);
  62. const plugin = moduleRegistry.use('workbox-broadcast-update', 'BroadcastUpdatePlugin');
  63. plugins.push(`new ${plugin}(${(0, stringify_without_comments_1.stringifyWithoutComments)(opts)})`);
  64. break;
  65. }
  66. case 'cacheableResponse': {
  67. const plugin = moduleRegistry.use('workbox-cacheable-response', 'CacheableResponsePlugin');
  68. plugins.push(`new ${plugin}(${(0, stringify_without_comments_1.stringifyWithoutComments)(options.cacheableResponse)})`);
  69. break;
  70. }
  71. case 'expiration': {
  72. const plugin = moduleRegistry.use('workbox-expiration', 'ExpirationPlugin');
  73. plugins.push(`new ${plugin}(${(0, stringify_without_comments_1.stringifyWithoutComments)(options.expiration)})`);
  74. break;
  75. }
  76. case 'precacheFallback': {
  77. const plugin = moduleRegistry.use('workbox-precaching', 'PrecacheFallbackPlugin');
  78. plugins.push(`new ${plugin}(${(0, stringify_without_comments_1.stringifyWithoutComments)(options.precacheFallback)})`);
  79. break;
  80. }
  81. case 'rangeRequests': {
  82. const plugin = moduleRegistry.use('workbox-range-requests', 'RangeRequestsPlugin');
  83. // There are no configuration options for the constructor.
  84. plugins.push(`new ${plugin}()`);
  85. break;
  86. }
  87. default: {
  88. throw new Error(
  89. // In the default case optionName is typed as 'never'.
  90. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
  91. `${errors_1.errors['bad-runtime-caching-config']} ${optionName}`);
  92. }
  93. }
  94. }
  95. if (Object.keys(handlerOptions).length > 0 || plugins.length > 0) {
  96. const optionsString = JSON.stringify(handlerOptions).slice(1, -1);
  97. return (0, common_tags_1.oneLine) `{
  98. ${optionsString ? optionsString + ',' : ''}
  99. plugins: [${plugins.join(', ')}]
  100. }`;
  101. }
  102. else {
  103. return '';
  104. }
  105. }
  106. function runtimeCachingConverter(moduleRegistry, runtimeCaching) {
  107. return runtimeCaching
  108. .map((entry) => {
  109. const method = entry.method || 'GET';
  110. if (!entry.urlPattern) {
  111. throw new Error(errors_1.errors['urlPattern-is-required']);
  112. }
  113. if (!entry.handler) {
  114. throw new Error(errors_1.errors['handler-is-required']);
  115. }
  116. if (entry.options &&
  117. entry.options.networkTimeoutSeconds &&
  118. entry.handler !== 'NetworkFirst') {
  119. throw new Error(errors_1.errors['invalid-network-timeout-seconds']);
  120. }
  121. // urlPattern might be a string, a RegExp object, or a function.
  122. // If it's a string, it needs to be quoted.
  123. const matcher = typeof entry.urlPattern === 'string'
  124. ? JSON.stringify(entry.urlPattern)
  125. : entry.urlPattern;
  126. const registerRoute = moduleRegistry.use('workbox-routing', 'registerRoute');
  127. if (typeof entry.handler === 'string') {
  128. const optionsString = getOptionsString(moduleRegistry, entry.options);
  129. const handler = moduleRegistry.use('workbox-strategies', entry.handler);
  130. const strategyString = `new ${handler}(${optionsString})`;
  131. return `${registerRoute}(${matcher.toString()}, ${strategyString}, '${method}');\n`;
  132. }
  133. else if (typeof entry.handler === 'function') {
  134. return `${registerRoute}(${matcher.toString()}, ${entry.handler.toString()}, '${method}');\n`;
  135. }
  136. // '' will be filtered out.
  137. return '';
  138. })
  139. .filter((entry) => Boolean(entry));
  140. }
  141. exports.runtimeCachingConverter = runtimeCachingConverter;