poops 1.5.3 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/poops.js CHANGED
@@ -3,6 +3,7 @@
3
3
  import chokidar from 'chokidar'
4
4
  import connect from 'connect'
5
5
  import Copy from './lib/copy.js'
6
+ import runExec, { validateExec } from './lib/exec.js'
6
7
  import { pathExists, doesFileBelongToPath, pathContainsPathSegment, deriveWatchDirs } from './lib/utils/helpers.js'
7
8
  import http from 'node:http'
8
9
  import os from 'node:os'
@@ -98,6 +99,10 @@ function styleOutputs(config) {
98
99
  : path.join(entry.out, path.basename(entry.in).replace(/\.(sass|scss)$/i, '.css'))))
99
100
  }
100
101
 
102
+ // Per-stage shell hooks (config.exec). Runs after a stage compiles in both
103
+ // build and watch; see lib/exec.js. `hook(stage)` binds config + cwd here.
104
+ const hook = (stage) => runExec(config, cwd, stage)
105
+
101
106
  function setupLiveReloadServer(config) {
102
107
  if (!config.livereload) return
103
108
  liveReloadServer = livereload.createServer({ port: config.livereload_port })
@@ -132,33 +137,33 @@ function setupWatchers(config, modules) {
132
137
  // exactly this file's entries; shared by change/add/unlink via rebuild.
133
138
  modules.markups.invalidate(file)
134
139
  if (/(\.m?jsx?|\.tsx?)$/i.test(file) && !isBuildOutput(file)) {
135
- modules.scripts.compile().then(() => reload()).catch(err => console.error(err))
140
+ modules.scripts.compile().then(() => { hook('scripts'); reload() }).catch(err => console.error(err))
136
141
 
137
142
  if (modules.reactor.belongsToReactor(file)) {
138
143
  modules.reactor.compile().then(() => {
139
144
  if (modules.reactor.renderedChanged) {
140
145
  config.reactorData = modules.reactor.getRendered()
141
- modules.markups.compile().then(() => modules.postcss.compile()).then(() => reload()).catch(err => console.error(err))
146
+ modules.markups.compile().then(() => modules.postcss.compile()).then(() => { hook('markup'); reload() }).catch(err => console.error(err))
142
147
  }
143
148
  }).catch(err => console.error(err))
144
149
  }
145
150
  }
146
151
  if (/(\.sass|\.scss|\.css)$/i.test(file) && !isBuildOutput(file)) {
147
152
  modules.styles.compile().then(() => modules.postcss.compile())
148
- .then(() => styleOutputs(config).forEach((out) => reload(out)))
153
+ .then(() => { hook('styles'); styleOutputs(config).forEach((out) => reload(out)) })
149
154
  .catch(err => console.error(err))
150
155
  }
151
156
  if (/(\.html|\.xml|\.rss|\.atom|\.njk|\.liquid|\.md)$/i.test(file)) {
152
157
  // Incremental: re-render only the pages whose last render touched this
153
158
  // file; falls back to a full compile for anything it can't prove safe
154
159
  // (deletions, new files, collection members, engines without dep info).
155
- modules.markups.compileIncremental(file).then(() => modules.postcss.compile()).then(() => reload()).catch(err => console.error(err))
160
+ modules.markups.compileIncremental(file).then(() => modules.postcss.compile()).then(() => { hook('markup'); reload() }).catch(err => console.error(err))
156
161
  }
157
162
 
158
163
  if (/(\.json|\.ya?ml)$/i.test(file)) {
159
164
  // Engine-owned markup with a data extension (Shopify templates/*.json)
160
165
  // goes incremental; real data files reload globals + full compile.
161
- modules.markups.compileDataChange(file).then(() => reload()).catch(err => console.error(err))
166
+ modules.markups.compileDataChange(file).then(() => { hook('markup'); reload() }).catch(err => console.error(err))
162
167
  }
163
168
  }
164
169
 
@@ -174,13 +179,13 @@ function setupWatchers(config, modules) {
174
179
  modules.images.compile()
175
180
  .then(() => modules.markups.compile())
176
181
  .then(() => modules.postcss.compile())
177
- .then(() => reload())
182
+ .then(() => { hook('images'); hook('markup'); reload() })
178
183
  .catch(err => console.error(err))
179
184
  }
180
185
  // A copied .css (e.g. the styles compiler's own output landing in a copy
181
186
  // source) stays a hot-swap; any other copied file needs a full reload.
182
187
  doesFileBelongToPath(file, config.copy) && modules.copy.execute()
183
- .then(() => reload(/\.css$/i.test(file) ? file : undefined))
188
+ .then(() => { hook('copy'); reload(/\.css$/i.test(file) ? file : undefined) })
184
189
  .catch(err => console.error(err))
185
190
  }
186
191
 
@@ -207,7 +212,7 @@ function setupWatchers(config, modules) {
207
212
  modules.images.remove(file)
208
213
  .then(() => modules.markups.compile())
209
214
  .then(() => modules.postcss.compile())
210
- .then(() => reload())
215
+ .then(() => { hook('images'); hook('markup'); reload() })
211
216
  .catch(err => console.error(err))
212
217
  }
213
218
  rebuild(file)
@@ -218,7 +223,7 @@ function setupWatchers(config, modules) {
218
223
  modules.markups.invalidate(dirPath) // prefix match drops every template under it
219
224
  modules.markups.removeOutput(dirPath)
220
225
  if (doesFileBelongToPath(dirPath, config.markup)) {
221
- modules.markups.compile().then(() => modules.postcss.compile()).then(() => reload()).catch(err => console.error(err))
226
+ modules.markups.compile().then(() => modules.postcss.compile()).then(() => { hook('markup'); reload() }).catch(err => console.error(err))
222
227
  }
223
228
  modules.copy.unlink(dirPath, doesFileBelongToPath(dirPath, config.copy))
224
229
  }
@@ -241,6 +246,7 @@ function setupWatchers(config, modules) {
241
246
 
242
247
  // Main function 💩
243
248
  async function poops() {
249
+ validateExec(config)
244
250
  const styles = new Styles(config)
245
251
  const postcss = new PostCSS(config)
246
252
  const reactor = new Reactor(config)
@@ -259,12 +265,19 @@ async function poops() {
259
265
 
260
266
  await step(() => styles.compile())
261
267
  await step(() => reactor.compile())
268
+ failed = hook('reactor') || failed
262
269
  config.reactorData = reactor.getRendered()
263
270
  await step(() => scripts.compile())
271
+ failed = hook('scripts') || failed
264
272
  await step(() => images.compile()) // before markups: engines read the poops-images cache
273
+ failed = hook('images') || failed
265
274
  await step(() => markups.compile())
275
+ failed = hook('markup') || failed
266
276
  await step(() => postcss.compile())
277
+ failed = hook('styles') || failed // after PostCSS so the CSS is final
267
278
  await step(() => copy.execute())
279
+ failed = hook('copy') || failed
280
+ failed = hook('build') || failed
268
281
 
269
282
  if (build || (!config.watch && !config.livereload && !config.serve)) {
270
283
  process.exit(failed || hasLoggedErrors() ? 1 : 0)