@sanity/export 3.40.0 → 3.41.1
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/README.md +5 -0
- package/package.json +2 -2
- package/src/AssetHandler.js +1 -1
- package/src/export.js +7 -3
- package/src/filterSystemDocuments.js +5 -0
- package/src/getDocumentCursorStream.js +45 -33
- package/src/util/rimraf.js +1 -4
package/README.md
CHANGED
|
@@ -42,6 +42,11 @@ exportDataset({
|
|
|
42
42
|
|
|
43
43
|
// Run 12 concurrent asset downloads
|
|
44
44
|
assetConcurrency: 12,
|
|
45
|
+
|
|
46
|
+
// What mode to use when exporting documents, can be eiter `stream`(default) or `cursor`.
|
|
47
|
+
// Cursor mode might help when dealing with large datasets, but might yield inconsistent results if the dataset is mutated during export.
|
|
48
|
+
// Default: 'stream'
|
|
49
|
+
mode: 'stream',
|
|
45
50
|
})
|
|
46
51
|
```
|
|
47
52
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/export",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.41.1",
|
|
4
4
|
"description": "Export Sanity documents and assets",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"lodash": "^4.17.21",
|
|
39
39
|
"mississippi": "^4.0.0",
|
|
40
40
|
"p-queue": "^2.3.0",
|
|
41
|
-
"rimraf": "^
|
|
41
|
+
"rimraf": "^6.0.1",
|
|
42
42
|
"split2": "^4.2.0",
|
|
43
43
|
"tar": "^7.0.1",
|
|
44
44
|
"yaml": "^2.4.2"
|
package/src/AssetHandler.js
CHANGED
|
@@ -2,7 +2,7 @@ const crypto = require('crypto')
|
|
|
2
2
|
const {mkdirSync, createWriteStream} = require('fs')
|
|
3
3
|
const path = require('path')
|
|
4
4
|
const {parse: parseUrl, format: formatUrl} = require('url')
|
|
5
|
-
const {omit
|
|
5
|
+
const {omit} = require('lodash')
|
|
6
6
|
const miss = require('mississippi')
|
|
7
7
|
const PQueue = require('p-queue')
|
|
8
8
|
const pkg = require('../package.json')
|
package/src/export.js
CHANGED
|
@@ -91,7 +91,7 @@ async function exportDataset(opts) {
|
|
|
91
91
|
debug('Archive finished')
|
|
92
92
|
})
|
|
93
93
|
|
|
94
|
-
debug('Getting dataset export stream')
|
|
94
|
+
debug('Getting dataset export stream, mode: "%s"', options.mode)
|
|
95
95
|
onProgress({step: 'Exporting documents...'})
|
|
96
96
|
|
|
97
97
|
let documentCount = 0
|
|
@@ -120,8 +120,12 @@ async function exportDataset(opts) {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
const inputStream = await getDocumentInputStream(options)
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
if (inputStream.statusCode) {
|
|
124
|
+
debug('Got HTTP %d', inputStream.statusCode)
|
|
125
|
+
}
|
|
126
|
+
if (inputStream.headers) {
|
|
127
|
+
debug('Response headers: %o', inputStream.headers)
|
|
128
|
+
}
|
|
125
129
|
|
|
126
130
|
let debugTimer = null
|
|
127
131
|
function scheduleDebugTimer() {
|
|
@@ -2,6 +2,7 @@ const miss = require('mississippi')
|
|
|
2
2
|
const debug = require('./debug')
|
|
3
3
|
|
|
4
4
|
const isSystemDocument = (doc) => doc && doc._id && doc._id.indexOf('_.') === 0
|
|
5
|
+
const isCursor = (doc) => doc && !doc._id && doc.nextCursor !== undefined
|
|
5
6
|
|
|
6
7
|
module.exports = () =>
|
|
7
8
|
miss.through.obj((doc, enc, callback) => {
|
|
@@ -9,6 +10,10 @@ module.exports = () =>
|
|
|
9
10
|
debug('%s is a system document, skipping', doc && doc._id)
|
|
10
11
|
return callback()
|
|
11
12
|
}
|
|
13
|
+
if (isCursor(doc)) {
|
|
14
|
+
debug('%o is a cursor, skipping', doc)
|
|
15
|
+
return callback()
|
|
16
|
+
}
|
|
12
17
|
|
|
13
18
|
return callback(null, doc)
|
|
14
19
|
})
|
|
@@ -1,60 +1,66 @@
|
|
|
1
1
|
const {Transform} = require('node:stream')
|
|
2
2
|
|
|
3
3
|
const pkg = require('../package.json')
|
|
4
|
+
const debug = require('./debug')
|
|
4
5
|
const requestStream = require('./requestStream')
|
|
5
6
|
|
|
7
|
+
// same regex as split2 is using by default: https://github.com/mcollina/split2/blob/53432f54bd5bf422bd55d91d38f898b6c9496fc1/index.js#L86
|
|
8
|
+
const splitRegex = /\r?\n/
|
|
9
|
+
|
|
6
10
|
module.exports = async (options) => {
|
|
7
11
|
let streamsInflight = 0
|
|
12
|
+
function decrementInflight(stream) {
|
|
13
|
+
streamsInflight--
|
|
14
|
+
if (streamsInflight === 0) {
|
|
15
|
+
stream.end()
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
8
19
|
const stream = new Transform({
|
|
9
20
|
async transform(chunk, encoding, callback) {
|
|
10
21
|
if (encoding !== 'buffer' && encoding !== 'string') {
|
|
11
22
|
callback(null, chunk)
|
|
12
23
|
return
|
|
13
24
|
}
|
|
25
|
+
this.push(chunk, encoding)
|
|
14
26
|
|
|
15
27
|
let parsedChunk = null
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// this can happen if the chunk is not a JSON object. We just pass it through and let the caller handle it.
|
|
21
|
-
}
|
|
28
|
+
for (const chunkStr of chunk.toString().split(splitRegex)) {
|
|
29
|
+
if (chunkStr.trim() === '') {
|
|
30
|
+
continue
|
|
31
|
+
}
|
|
22
32
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
streamsInflight++
|
|
33
|
+
try {
|
|
34
|
+
parsedChunk = JSON.parse(chunkStr)
|
|
35
|
+
} catch (err) {
|
|
36
|
+
// Ignore JSON parse errors
|
|
37
|
+
// this can happen if the chunk is not a JSON object. We just pass it through and let the caller handle it.
|
|
38
|
+
debug('Failed to parse JSON chunk, ignoring', err, chunkStr)
|
|
39
|
+
}
|
|
31
40
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
if (
|
|
42
|
+
parsedChunk !== null &&
|
|
43
|
+
typeof parsedChunk === 'object' &&
|
|
44
|
+
'nextCursor' in parsedChunk &&
|
|
45
|
+
typeof parsedChunk.nextCursor === 'string' &&
|
|
46
|
+
!('_id' in parsedChunk)
|
|
47
|
+
) {
|
|
48
|
+
debug('Got next cursor "%s", fetching next stream', parsedChunk.nextCursor)
|
|
49
|
+
streamsInflight++
|
|
40
50
|
|
|
41
|
-
|
|
42
|
-
|
|
51
|
+
const reqStream = await startStream(options, parsedChunk.nextCursor)
|
|
52
|
+
reqStream.on('end', () => decrementInflight(this))
|
|
53
|
+
reqStream.pipe(this, {end: false})
|
|
54
|
+
}
|
|
43
55
|
}
|
|
44
56
|
|
|
45
|
-
callback(
|
|
57
|
+
callback()
|
|
46
58
|
},
|
|
47
59
|
})
|
|
48
60
|
|
|
49
61
|
streamsInflight++
|
|
50
62
|
const reqStream = await startStream(options, '')
|
|
51
|
-
reqStream.on('end', () =>
|
|
52
|
-
streamsInflight--
|
|
53
|
-
if (streamsInflight === 0) {
|
|
54
|
-
stream.end()
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
|
|
63
|
+
reqStream.on('end', () => decrementInflight(stream))
|
|
58
64
|
reqStream.pipe(stream, {end: false})
|
|
59
65
|
return stream
|
|
60
66
|
}
|
|
@@ -69,5 +75,11 @@ function startStream(options, nextCursor) {
|
|
|
69
75
|
...(token ? {Authorization: `Bearer ${token}`} : {}),
|
|
70
76
|
}
|
|
71
77
|
|
|
72
|
-
|
|
78
|
+
debug('Starting stream with cursor "%s"', nextCursor)
|
|
79
|
+
|
|
80
|
+
return requestStream({url, headers, maxRetries: options.maxRetries}).then((res) => {
|
|
81
|
+
debug('Got stream with HTTP %d', res.statusCode)
|
|
82
|
+
|
|
83
|
+
return res
|
|
84
|
+
})
|
|
73
85
|
}
|
package/src/util/rimraf.js
CHANGED