class ZendeskAppsSupport::Package

Constants

DEFAULT_LAYOUT
DEFAULT_SCSS
LOCATIONS_WITH_ICONS_PER_PRODUCT
MANIFEST_FILENAME
REQUIREMENTS_FILENAME
SRC_TEMPLATE

Attributes

lib_root[R]
root[R]
warnings[R]

Public Class Methods

has_custom_object_requirements?(requirements_hash) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 218
def self.has_custom_object_requirements?(requirements_hash)
  return false if requirements_hash.nil?

  custom_object_requirements = requirements_hash.fetch(AppRequirement::CUSTOM_OBJECTS_KEY, {})
  types = custom_object_requirements.fetch(AppRequirement::CUSTOM_OBJECTS_TYPE_KEY, [])
  relationships = custom_object_requirements.fetch(AppRequirement::CUSTOM_OBJECTS_RELATIONSHIP_TYPE_KEY, [])

  (types | relationships).any?
end
new(dir, is_cached = true) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 26
def initialize(dir, is_cached = true)
  @root     = Pathname.new(File.expand_path(dir))
  @lib_root = Pathname.new(File.join(root, 'lib'))

  @is_cached = is_cached # disabled by ZAT for development
  @warnings = []
end

Public Instance Methods

app_css() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 228
def app_css
  return File.read(path_to('app.scss')) if has_file?('app.scss')
  return File.read(path_to('app.css')) if has_file?('app.css')
  ''
end
app_js() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 234
def app_js
  if @is_cached
    @app_js ||= read_file('app.js')
  else
    read_file('app.js')
  end
end
assets() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 70
def assets
  @assets ||= Dir.chdir(root) do
    Dir['assets/**/*'].select { |f| File.file?(f) }
  end
end
compile(options) click to toggle source

this is not really compile_js, it compiles the whole app including scss for v1 apps

# File lib/zendesk_apps_support/package.rb, line 128
def compile(options)
  begin
    app_id = options.fetch(:app_id)
    asset_url_prefix = options.fetch(:assets_dir)
    name = options.fetch(:app_name)
  rescue KeyError => e
    raise ArgumentError, e.message
  end

  locale = options.fetch(:locale, 'en')

  source = manifest.iframe_only? ? nil : app_js
  app_class_name = "app-#{app_id}"
  # if no_template is an array, we still need the templates
  templates = manifest.no_template == true ? {} : compiled_templates(app_id, asset_url_prefix)

  SRC_TEMPLATE.result(
    name: name,
    version: manifest.version,
    source: source,
    app_class_properties: manifest.app_class_properties,
    asset_url_prefix: asset_url_prefix,
    logo_asset_hash: generate_logo_hash(manifest.products),
    location_icons: location_icons,
    app_class_name: app_class_name,
    author: manifest.author,
    translations: manifest.iframe_only? ? nil : runtime_translations(translations_for(locale)),
    framework_version: manifest.framework_version,
    templates: templates,
    modules: commonjs_modules,
    iframe_only: manifest.iframe_only?
  )
end
Also aliased as: compile_js
compile_js(options)
Alias for: compile
compiled_templates(app_id, asset_url_prefix) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 189
def compiled_templates(app_id, asset_url_prefix)
  compiler = ZendeskAppsSupport::StylesheetCompiler.new(DEFAULT_SCSS + app_css, app_id, asset_url_prefix)
  compiled_css = compiler.compile(sassc: manifest.enabled_experiments.include?('newCssCompiler'))

  layout = templates['layout'] || DEFAULT_LAYOUT.result

  templates.tap do |templates|
    templates['layout'] = "<style>\n#{compiled_css}</style>\n#{layout}"
  end
end
files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 88
def files
  files = []
  Dir[root.join('**/**')].each do |f|
    next unless File.file?(f)
    relative_file_name = f.sub(%r{#{root}/?}, '')
    next if relative_file_name =~ %r{^tmp/}
    files << AppFile.new(self, relative_file_name)
  end
  files
end
has_file?(path) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 206
def has_file?(path)
  File.file?(path_to(path))
end
has_requirements?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 214
def has_requirements?
  has_file?(REQUIREMENTS_FILENAME)
end
has_svgs?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 210
def has_svgs?
  svg_files.any?
end
html_files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 107
def html_files
  @html_files ||= files.select { |f| f =~ %r{.*\.html?$} }
end
iframe_only?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 242
def iframe_only?
  manifest.iframe_only?
end
is_no_template() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 179
def is_no_template
  manifest.no_template?
end
js_files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 103
def js_files
  @js_files ||= files.select { |f| f =~ %r{^.*\.jsx?$} }
end
lib_files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 111
def lib_files
  @lib_files ||= js_files.select { |f| f =~ %r{^lib/} }
end
locales() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 84
def locales
  translations.keys
end
location_icons() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 281
def location_icons
  Hash.new { |h, k| h[k] = {} }.tap do |location_icons|
    manifest.location_options.each do |location_options|
      # no location information in the manifest
      next unless location_options.location

      product = location_options.location.product
      location_name = location_options.location.name
      # the location on the product does not support icons
      next unless LOCATIONS_WITH_ICONS_PER_PRODUCT.fetch(product, []).include?(location_name)

      host = location_options.location.product.name
      product_directory = manifest.products.count > 1 ? "#{host}/" : ''
      location_icons[host][location_name] = build_location_icons_hash(location_name, product_directory)
    end
  end
end
manifest() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 170
def manifest
  @manifest ||= Manifest.new(read_file(MANIFEST_FILENAME))
end
manifest_json() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 165
def manifest_json
  @manifest_json ||= read_json(MANIFEST_FILENAME)
end
no_template_locations() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 184
def no_template_locations
  manifest.no_template_locations
end
path_to(file) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 76
def path_to(file)
  File.join(root, file)
end
requirements_json() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 174
def requirements_json
  return nil unless has_requirements?
  @requirements ||= read_json(REQUIREMENTS_FILENAME, object_class: Manifest::NoOverrideHash)
end
requirements_path() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 80
def requirements_path
  path_to(REQUIREMENTS_FILENAME)
end
svg_files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 115
def svg_files
  @svg_files ||= files.select { |f| f =~ %r{^assets/.*\.svg$} }
end
template_files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 119
def template_files
  files.select { |f| f =~ %r{^templates/.*\.hdbs$} }
end
templates() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 247
def templates
  templates_dir = path_to('templates')
  Dir["#{templates_dir}/*.hdbs"].each_with_object({}) do |file, memo|
    str = File.read(file)
    str.chomp!
    memo[File.basename(file, File.extname(file))] = str
    memo
  end
end
text_files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 99
def text_files
  @text_files ||= files.select { |f| f =~ %r{.*(html?|xml|js|json?)$} }
end
translation_files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 123
def translation_files
  files.select { |f| f =~ %r{^translations/} }
end
translations() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 257
def translations
  return @translations if @is_cached && @translations

  @translations = begin
    translation_dir = path_to('translations')
    return {} unless File.directory?(translation_dir)

    locale_path = "#{translation_dir}/#{manifest.default_locale}.json"
    default_translations = process_translations(locale_path, default_locale: true)

    Dir["#{translation_dir}/*.json"].each_with_object({}) do |path, memo|
      locale = File.basename(path, File.extname(path))

      locale_translations = if locale == manifest.default_locale
                              default_translations
                            else
                              deep_merge_hash(default_translations, process_translations(path))
                            end

      memo[locale] = locale_translations
    end
  end
end
translations_for(locale) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 200
def translations_for(locale)
  trans = translations
  return trans[locale] if trans[locale]
  trans[manifest.default_locale]
end
validate(marketplace: true, skip_marketplace_translations: false) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 34
def validate(marketplace: true, skip_marketplace_translations: false)
  errors = []
  errors << Validations::Manifest.call(self)

  if has_valid_manifest?(errors)
    errors << Validations::Marketplace.call(self) if marketplace
    errors << Validations::Source.call(self)
    errors << Validations::Translations.call(self, skip_marketplace_translations: skip_marketplace_translations)
    errors << Validations::Requirements.call(self)

    # only adds warnings
    Validations::SecureSettings.call(self)
    Validations::Requests.call(self)

    unless manifest.requirements_only? || manifest.marketing_only? || manifest.iframe_only?
      errors << Validations::Templates.call(self)
      errors << Validations::Stylesheets.call(self)
    end
  end

  errors << Validations::Banner.call(self) if has_banner?
  errors << Validations::Svg.call(self) if has_svgs?
  errors << Validations::Mime.call(self)

  # only adds warnings
  Validations::Secrets.call(self)

  errors.flatten.compact
end
validate!(marketplace: true, skip_marketplace_translations: false) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 64
def validate!(marketplace: true, skip_marketplace_translations: false)
  errors = validate(marketplace: marketplace, skip_marketplace_translations: skip_marketplace_translations)
  raise errors.first if errors.any?
  true
end

Private Instance Methods

build_location_icons_hash(location, product_directory) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 342
def build_location_icons_hash(location, product_directory)
  inactive_png = "icon_#{location}_inactive.png"
  if has_file?("assets/#{product_directory}icon_#{location}.svg")
    build_svg_icon_hash(location, product_directory)
  elsif has_file?("assets/#{product_directory}#{inactive_png}")
    build_png_icons_hash(location, product_directory)
  else
    {}
  end
end
build_png_icons_hash(location, product_directory) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 358
def build_png_icons_hash(location, product_directory)
  inactive_png = "#{product_directory}icon_#{location}_inactive.png"
  {
    'inactive' => inactive_png
  }.tap do |icon_state_hash|
    %w[active hover].each do |state|
      specific_png = "#{product_directory}icon_#{location}_#{state}.png"
      selected_png = has_file?("assets/#{specific_png}") ? specific_png : inactive_png
      icon_state_hash[state] = selected_png
    end
  end
end
build_svg_icon_hash(location, product_directory) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 353
def build_svg_icon_hash(location, product_directory)
  cache_busting_param = "?#{Time.now.to_i}" unless @is_cached
  { 'svg' => "#{product_directory}icon_#{location}.svg#{cache_busting_param}" }
end
commonjs_modules() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 371
def commonjs_modules
  return {} unless has_lib_js?

  lib_files.each_with_object({}) do |file, modules|
    name          = file.relative_path.gsub(/^lib\//, '')
    content       = file.read
    modules[name] = content
  end
end
deep_merge_hash(h, another_h) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 381
def deep_merge_hash(h, another_h)
  result_h = h.dup
  another_h.each do |key, value|
    result_h[key] = if h.key?(key) && h[key].is_a?(Hash) && value.is_a?(Hash)
                      deep_merge_hash(h[key], value)
                    else
                      value
                    end
  end
  result_h
end
generate_logo_hash(products) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 301
def generate_logo_hash(products)
  {}.tap do |logo_hash|
    products.each do |product|
      product_directory = products.count > 1 ? "#{product.name.downcase}/" : ''
      logo_hash[product.name.downcase] = "#{product_directory}logo-small.png"
    end
  end
end
has_banner?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 338
def has_banner?
  has_file?('assets/banner.png')
end
has_lib_js?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 330
def has_lib_js?
  lib_files.any?
end
has_manifest?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 334
def has_manifest?
  has_file?(MANIFEST_FILENAME)
end
has_valid_manifest?(errors) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 310
def has_valid_manifest?(errors)
  has_manifest? && errors.flatten.empty?
end
process_translations(locale_path, default_locale: false) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 323
def process_translations(locale_path, default_locale: false)
  translations = File.exist?(locale_path) ? JSON.parse(File.read(locale_path)) : {}
  translations['app'].delete('name') if !default_locale && translations.key?('app')
  translations['app'].delete('package') if translations.key?('app')
  remove_zendesk_keys(translations)
end
read_file(path) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 393
def read_file(path)
  File.read(path_to(path))
end
read_json(path, parser_opts = {}) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 397
def read_json(path, parser_opts = {})
  file = read_file(path)
  JSON.parse(read_file(path), parser_opts) unless file.nil?
end
runtime_translations(translations) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 314
def runtime_translations(translations)
  result = translations.dup
  result.delete('name')
  result.delete('short_description')
  result.delete('long_description')
  result.delete('installation_instructions')
  result
end