Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@skava/bs / src / config / oneConfig / getClientBundleEntryAssets.ts
Size: Mime:
/* eslint-disable max-statements */
/**
 * @file resolves the entry assets available from our client bundle
 * @see scripts/.plugins
 * @name getClientBundleEntryAssets
 */
import { resolve } from 'path'
import { isString } from 'exotic'
import { exists, readJSON } from '@skava/persistence/dist/adapters/server'
import { getAbsoluteUrl } from './getDynamicPaths'

interface ManifestOutput {
  [key: string]: string | ManifestOutput
}

let resultCache

function validateAssetsPath(assetsFilePath: string) {
  if (!exists(assetsFilePath)) {
    const errorMessage = `
      We could not find the "${assetsFilePath}" file,
      which contains a list of the assets of the client bundle.
      Please ensure that the client bundle has been built.
    `

    const noAssets = new Error(errorMessage)
    throw noAssets
  }
}

function validateAssetEntryPointForIndex(
  index?: ManifestOutput | string | undefined | any
) {
  if (typeof index === 'undefined') {
    throw new Error(
      'No asset data found for expected "index" entry chunk of client bundle.'
    )
  }
}

function validateHackPath(assetObjJs: string) {
  if (!isString(assetObjJs)) {
    const value = JSON.stringify(assetObjJs, undefined, 2)
    const error = 'must remap a string path. received: ' + value
    throw new TypeError(error)
  }
}

/**
 * 1. add dynamic port
 * 2. assert https unless localhost
 * 3. validate
 */
function hackPath(assetObjJs: string = '') {
  validateHackPath(assetObjJs)
  const original = assetObjJs

  const FINAL_URL = getAbsoluteUrl()

  return assetObjJs
    .replace('http://localhost:3000', FINAL_URL)
    .replace('https://localhost:3000', FINAL_URL)
}

const toActualPath = (x: string) =>
  x.includes('client') ? x.split('/').pop() : x

/**
 * @desc retrieves the js/css for the named chunks that belong to our client bundle.
 *
 * @note the order of the chunk names is important. The same ordering will be
 *       used when rendering the scripts.
 *
 * This is useful to us for a couple of reasons:
 *   - It allows us to target the assets for a specific chunk, thereby only
 *     loading the assets we know we will need for a specific request.
 *   - The assets are hashed, and therefore they can't be "manually" added
 *     to the render logic.  Having this method allows us to easily fetch
 *     the respective assets simply by using a chunk name. :)
 *
 * @example dist/dist/bundle/client/assets.json
 *    {"index":{"js":"http://0.0.0.0:5555/client/index.js"}}
 *
 * @example dist/dist/bundle/server/assets.json
 *    {"index":{"js":"http://0.0.0.0:5555/server/index.js"}}
 */
function getClientBundleEntryAssets() {
  // Return the assets json cache if it exists.
  // In development mode we always read the assets json file from disk to avoid
  // any cases where an older version gets cached.

  // @NOTE disabled @hack
  // if (process.env.NODE_ENV === 'production' && resultCache) {
  //   return resultCache
  // }

  // const assetDir = process.env.BUILD_CONFIG_CLIENT_ASSETS_PATH
  // const assetFileName = process.env.BUNDLE_ASSETS_FILE_NAME
  const assetDir =
    process.env.BUILD_CONFIG_CLIENT_ASSETS_PATH + '/dist/bundled/client/'
  const assetFileName = 'manifest.json'
  const assetFilePathRelative = `${assetDir}/${assetFileName}`
  const assetsFilePath = resolve(assetFilePathRelative)

  validateAssetsPath(assetsFilePath)
  const assetsJSONCache = readJSON(assetsFilePath)
  const outputPaths = Object.values(assetsJSONCache)
  const outputNames = Object.keys(assetsJSONCache)
  const index = outputPaths[0]
  validateAssetEntryPointForIndex(index)

  // @todo - this duplicates!!!
  const assetObj = {
    jsList: [...outputPaths.map(toActualPath)],
  }

  resultCache = assetObj
  return resultCache
}

export { getClientBundleEntryAssets }
export default getClientBundleEntryAssets