@sanity/export 3.38.0 → 3.38.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/export",
3
- "version": "3.38.0",
3
+ "version": "3.38.2",
4
4
  "description": "Export Sanity documents and assets",
5
5
  "keywords": [
6
6
  "sanity",
package/src/constants.js CHANGED
@@ -20,3 +20,9 @@ exports.ASSET_DOWNLOAD_MAX_RETRIES = 10
20
20
  * @internal
21
21
  */
22
22
  exports.ASSET_DOWNLOAD_CONCURRENCY = 8
23
+
24
+ /**
25
+ * How frequently we will `debug` log while streaming the documents.
26
+ * @internal
27
+ */
28
+ exports.DOCUMENT_STREAM_DEBUG_INTERVAL = 10000
package/src/export.js CHANGED
@@ -17,6 +17,7 @@ const stringifyStream = require('./stringifyStream')
17
17
  const tryParseJson = require('./tryParseJson')
18
18
  const rimraf = require('./util/rimraf')
19
19
  const validateOptions = require('./validateOptions')
20
+ const {DOCUMENT_STREAM_DEBUG_INTERVAL} = require('./constants')
20
21
 
21
22
  const noop = () => null
22
23
 
@@ -39,6 +40,9 @@ async function exportDataset(opts) {
39
40
 
40
41
  const prefix = `${opts.dataset}-export-${slugDate}`
41
42
  const tmpDir = path.join(os.tmpdir(), prefix)
43
+ fs.mkdirSync(tmpDir, {recursive: true})
44
+ const dataPath = path.join(tmpDir, 'data.ndjson')
45
+
42
46
  const cleanup = () =>
43
47
  rimraf(tmpDir).catch((err) => {
44
48
  debug(`Error while cleaning up temporary files: ${err.message}`)
@@ -90,11 +94,14 @@ async function exportDataset(opts) {
90
94
  onProgress({step: 'Exporting documents...'})
91
95
 
92
96
  let documentCount = 0
97
+ let lastDocumentID = null
93
98
  let lastReported = Date.now()
94
- const reportDocumentCount = (chunk, enc, cb) => {
99
+ const reportDocumentCount = (doc, enc, cb) => {
95
100
  ++documentCount
96
101
 
97
102
  const now = Date.now()
103
+ // We report to the `onProgress` handler every 50 ms.
104
+ // It's up to the caller to not do too much expensive work.
98
105
  if (now - lastReported > 50) {
99
106
  onProgress({
100
107
  step: 'Exporting documents...',
@@ -106,13 +113,30 @@ async function exportDataset(opts) {
106
113
  lastReported = now
107
114
  }
108
115
 
109
- cb(null, chunk)
116
+ lastDocumentID = doc._id
117
+
118
+ cb(null, doc)
110
119
  }
111
120
 
112
121
  const inputStream = await getDocumentsStream(options)
113
122
  debug('Got HTTP %d', inputStream.statusCode)
114
123
  debug('Response headers: %o', inputStream.headers)
115
124
 
125
+ let debugTimer = null
126
+ function scheduleDebugTimer() {
127
+ debugTimer = setTimeout(() => {
128
+ debug('Still streaming documents', {
129
+ documentCount,
130
+ lastDocumentID,
131
+ })
132
+
133
+ // Schedule another tick:
134
+ scheduleDebugTimer()
135
+ }, DOCUMENT_STREAM_DEBUG_INTERVAL)
136
+ }
137
+
138
+ scheduleDebugTimer()
139
+
116
140
  const jsonStream = miss.pipeline(
117
141
  inputStream,
118
142
  logFirstChunk(),
@@ -122,13 +146,15 @@ async function exportDataset(opts) {
122
146
  assetStreamHandler,
123
147
  filterDocumentTypes(options.types),
124
148
  options.drafts ? miss.through.obj() : filterDrafts(),
149
+ miss.through.obj(reportDocumentCount),
125
150
  stringifyStream(),
126
- miss.through(reportDocumentCount),
127
151
  )
128
152
 
129
- miss.finished(jsonStream, async (err) => {
153
+ miss.pipe(jsonStream, fs.createWriteStream(dataPath), async (err) => {
154
+ if (debugTimer !== null) clearTimeout(debugTimer)
155
+
130
156
  if (err) {
131
- debug('Export stream error: ', err)
157
+ debug(`Export stream error @ ${lastDocumentID}/${documentCount}: `, err)
132
158
  reject(err)
133
159
  return
134
160
  }
@@ -141,6 +167,9 @@ async function exportDataset(opts) {
141
167
  update: true,
142
168
  })
143
169
 
170
+ debug('Adding data.ndjson to archive')
171
+ archive.file(dataPath, {name: 'data.ndjson', prefix})
172
+
144
173
  if (!options.raw && options.assets) {
145
174
  onProgress({step: 'Downloading assets...'})
146
175
  }
@@ -197,7 +226,6 @@ async function exportDataset(opts) {
197
226
  debug('Archive warning: %s', err.message)
198
227
  })
199
228
 
200
- archive.append(jsonStream, {name: 'data.ndjson', prefix})
201
229
  miss.pipe(archive, outputStream, onComplete)
202
230
 
203
231
  async function onComplete(err) {
@@ -205,6 +233,7 @@ async function exportDataset(opts) {
205
233
  await cleanup()
206
234
 
207
235
  if (!err) {
236
+ debug('Export completed')
208
237
  resolve({
209
238
  outputPath: options.outputPath,
210
239
  documentCount,
@@ -2,18 +2,26 @@ const miss = require('mississippi')
2
2
 
3
3
  module.exports = () =>
4
4
  miss.through.obj((doc, enc, callback) => {
5
- if (doc.error && doc.statusCode) {
6
- callback(
7
- new Error(
8
- ['Export', `HTTP ${doc.statusCode}`, doc.error, doc.message]
9
- .filter((part) => typeof part === 'string')
10
- .join(': '),
11
- ),
12
- )
5
+ // check if the document passed contains a document attribtue first, and return early.
6
+ if (doc._id) {
7
+ callback(null, doc)
13
8
  return
14
9
  }
15
10
 
16
- if (!doc._id && doc.error) {
11
+ if (doc.error) {
12
+ // if we got a statusCode we can decorate the error with it
13
+ if (doc.statusCode) {
14
+ callback(
15
+ new Error(
16
+ ['Export', `HTTP ${doc.statusCode}`, doc.error, doc.message]
17
+ .filter((part) => typeof part === 'string')
18
+ .join(': '),
19
+ ),
20
+ )
21
+ return
22
+ }
23
+
24
+ // no statusCode, just serialize and return the error
17
25
  callback(new Error(doc.error.description || doc.error.message || JSON.stringify(doc)))
18
26
  return
19
27
  }