1 | const path = require('path')
|
2 | const chalk = require('chalk')
|
3 | const fs = require('fs-extra')
|
4 | const stripIndents = require('common-tags/lib/stripIndents')
|
5 | const resolveVideos = require('../prepare/resolve-videos')
|
6 | const getScriptsAndTitle = require('../prepare/get-scripts-and-title')
|
7 | const getAnimatePublished = require('./get-animate-published')
|
8 | const getComponentInfo = require('../util/get-component-info')
|
9 | const getSnippetInfo = require('../util/get-snippet-info')
|
10 | const blinkInfo = require('../info/index')
|
11 | const Promise = require('bluebird')
|
12 | const toml = require('toml')
|
13 | const getHeaders = require('../util/get-headers')
|
14 | const fsOpts = { encoding: 'utf8' }
|
15 | const kitInfo = require('../util/get-kit-info')
|
16 |
|
17 | const addContentLength = (format) => {
|
18 | const p = {}
|
19 | Object.keys(format).forEach((key) => {
|
20 | p[key] = getHeaders(format[key].uri).then((headers) => {
|
21 | format[key].contentLength = parseInt(headers['content-length'], 10)
|
22 | return format[key]
|
23 | })
|
24 | })
|
25 | return Promise.props(p)
|
26 | }
|
27 |
|
28 | module.exports = async ({ env, program, pkg }) => {
|
29 | try {
|
30 | const srcPath = path.join(program.cwd, './src')
|
31 | const distPath = path.join(program.cwd, './dist')
|
32 | const blinkPath = path.join(program.cwd, './blink.toml')
|
33 | const targetsPath = path.join(program.cwd, './package.json')
|
34 | const manifestPath = path.join(distPath, './manifest.json')
|
35 | const componentsPath = env.comp
|
36 | const [manifestBase, templateOutputs] = await Promise.all([
|
37 | fs.readFile(blinkPath, fsOpts)
|
38 | .catch((err) => {
|
39 | console.log(chalk.red('⚠️ Can\'t find blink.toml file. You may be in the wrong directory'))
|
40 | return Promise.reject(err)
|
41 | })
|
42 | .then((body) => {
|
43 | if (!program.silent) console.log(`✅ Using ${chalk.underline(blinkPath)}`)
|
44 | return toml.parse(body)
|
45 | })
|
46 | .then((blink) => resolveVideos(blink))
|
47 | .then((blink) => {
|
48 | const p = {}
|
49 | Object.keys(blink.videos).forEach((key) => {
|
50 | const video = blink.videos[key]
|
51 | p[key] = Promise.props({
|
52 | hd: addContentLength(video.hd),
|
53 | sd: addContentLength(video.sd),
|
54 | playlists: Promise.resolve(video.playlists),
|
55 | originalKey: Promise.resolve(video.originalKey),
|
56 | outputs: Promise.resolve(video.outputs)
|
57 | })
|
58 | })
|
59 | return Promise.props(p).then((results) => {
|
60 | blink.videos = results
|
61 | return blink
|
62 | })
|
63 | }),
|
64 | fs.readdir(srcPath, fsOpts)
|
65 | .catch((err) => {
|
66 | console.log(chalk.red('⚠️ Can\'t find src directory. You may be in the wrong directory'))
|
67 | return Promise.reject(err)
|
68 | })
|
69 | .then((filesList) => getAnimatePublished(srcPath, filesList))
|
70 | .catch((err) => {
|
71 | console.log(chalk.red('⚠️ You may not have published the creative yet'))
|
72 | return Promise.reject(err)
|
73 | })
|
74 | .then((files) => fs.readFile(path.join(srcPath, files.html), fsOpts))
|
75 | .then((template) => getScriptsAndTitle(template))
|
76 | ])
|
77 | const { title, width, height } = templateOutputs
|
78 | const blinkPkg = fs.readJsonSync(targetsPath, fsOpts)
|
79 | const blinkTargets = blinkPkg && blinkPkg.blink && blinkPkg.blink.targets
|
80 | const components = await getComponentInfo(path.join(srcPath, `${title}.js`), componentsPath, blinkTargets)
|
81 | const snippets = await getSnippetInfo(path.join(srcPath, `${title}.js`))
|
82 | const manifest = Object.assign({}, manifestBase, { targets: components.targets })
|
83 | const kitType = kitInfo(program, 'type')
|
84 | if (kitType !== 'display') {
|
85 | const blinkData = await blinkInfo({ program, pkg })
|
86 | if (blinkData.blinkCli.outdated) {
|
87 | console.log(stripIndents(chalk`
|
88 | {red ⚠️ Using blink-cli version ${pkg.version} (not up to date)}
|
89 | {red Update to latest ({italic npm i -g @tremorvideo/blink-cli})}
|
90 | `))
|
91 | }
|
92 | if (blinkData.starterKits.outdated) {
|
93 | console.log(stripIndents(chalk`
|
94 | {red ⚠️ Using starter-kits version ${blinkData.starterKits.version} (not up to date)}
|
95 | {red Update creative to latest (${pkg.starterKitVersion})}
|
96 | `))
|
97 | }
|
98 | if (blinkData.blinkCli.outdated || blinkData.starterKits.outdated) {
|
99 | console.log(chalk.red('Updating to latest versions before uploading is recommended!'))
|
100 | }
|
101 | manifest.blinkVersions = {
|
102 | blinkCli: blinkData.blinkCli.version,
|
103 | apl: (!env.withoutApl && blinkData.apl) ? blinkData.apl.version : 'none',
|
104 | blink: blinkData.blink.version,
|
105 | starterKit: blinkData.starterKits.version,
|
106 | blinkComponents: components.components,
|
107 | blinkSnippets: snippets
|
108 | }
|
109 | } else {
|
110 | manifest.blinkVersions = {
|
111 | blinkCli: null,
|
112 | apl: 'none',
|
113 | blink: null,
|
114 | blinkComponents: components.components,
|
115 | starterKit: null,
|
116 | blinkSnippets: snippets
|
117 | }
|
118 | }
|
119 | manifest.mediaFiles = [
|
120 | {
|
121 | id: title,
|
122 | delivery: 'progressive',
|
123 | type: 'application/javascript',
|
124 | bitrate: 466,
|
125 | width,
|
126 | height,
|
127 | maintainAspectRatio: true,
|
128 | scalable: true,
|
129 | apiFramework: 'VPAID'
|
130 | }
|
131 | ]
|
132 | manifest.refWidth = width
|
133 | manifest.refHeight = height
|
134 | manifest.general = manifestBase.general || {}
|
135 | manifest.general.bridgeId = title
|
136 | const tvEvents = manifestBase.tvEvents || manifestBase.tvCustomEvents
|
137 | const trackableEvents = tvEvents.trackableEvents || tvEvents.thirdPartyPixels || []
|
138 | const clickThruEvents = tvEvents.uri || []
|
139 | const designerEvents = (manifestBase.designerEvents && manifestBase.designerEvents.trackableEvents) || []
|
140 | const designerClickThrus = (manifestBase.designerEvents && manifestBase.designerEvents.uri) || []
|
141 | const allConfigurables = new Set(trackableEvents.concat(clickThruEvents, designerEvents, designerClickThrus, components.events))
|
142 | manifest.tvCustomEvents = [...allConfigurables].map((k) => {
|
143 | const parts = k.split('_')
|
144 | const configurable = {
|
145 | name: k,
|
146 | kind: parts[0] || '',
|
147 | context: parts[1] || '',
|
148 | args: parts.slice(2),
|
149 | uri: clickThruEvents.includes(k) || designerClickThrus.includes(k),
|
150 | thirdPartyPixels: trackableEvents.includes(k) || designerEvents.includes(k) || components.events.includes(k)
|
151 | }
|
152 | return configurable
|
153 | })
|
154 | if (kitType !== 'display') {
|
155 |
|
156 | manifest.tvCustomEvents.unshift({
|
157 | name: 'Engagement_Third_Party',
|
158 | kind: 'Engagement',
|
159 | context: 'Third_Party',
|
160 | args: [],
|
161 | uri: false,
|
162 | thirdPartyPixels: true
|
163 | })
|
164 | }
|
165 | if (manifest.tvEvents) delete manifest.tvEvents
|
166 | if (manifest.designerEvents) delete manifest.designerEvents
|
167 | await fs.outputFile(manifestPath, JSON.stringify(manifest, null, 2), fsOpts)
|
168 | if (!program.silent) console.log('✅ Built manifest.json')
|
169 | return manifest
|
170 | } catch (err) {
|
171 | console.log(chalk.red('⚠️ manifest.json did NOT build'))
|
172 | return Promise.reject(err)
|
173 | }
|
174 | }
|