@sanity/export 3.0.1-dev-preview.0 → 3.0.1-findability.147

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,19 +1,18 @@
1
1
  {
2
2
  "name": "@sanity/export",
3
- "version": "3.0.1-dev-preview.0",
3
+ "version": "3.0.1-findability.147+8b2f6c2afe",
4
4
  "description": "Export Sanity documents and assets",
5
- "main": "./lib/export.js",
6
- "types": "./lib/dts/src/export.d.ts",
5
+ "main": "./src/export.js",
6
+ "files": [
7
+ "src"
8
+ ],
7
9
  "engines": {
8
10
  "node": ">=14.0.0"
9
11
  },
10
12
  "author": "Sanity.io <hello@sanity.io>",
11
13
  "license": "MIT",
12
14
  "scripts": {
13
- "build": "../../../bin/pkg-utils transpile --target node",
14
- "clean": "rimraf lib",
15
- "test": "jest",
16
- "watch": "../../../bin/pkg-utils transpile --target node --watch"
15
+ "test": "jest"
17
16
  },
18
17
  "keywords": [
19
18
  "sanity",
@@ -49,5 +48,5 @@
49
48
  "url": "https://github.com/sanity-io/sanity/issues"
50
49
  },
51
50
  "homepage": "https://www.sanity.io/",
52
- "gitHead": "174eea8e59f8d7f4f1d9661de99f76aa683601f3"
51
+ "gitHead": "8b2f6c2afe0fbb21c7557c90057745732d21b877"
53
52
  }
@@ -125,7 +125,7 @@ class AssetHandler {
125
125
  const isImage = assetDoc._type === 'sanity.imageAsset'
126
126
 
127
127
  const url = parseUrl(assetDoc.url, true)
128
- if (isImage && ['cdn.sanity.io', 'cdn.sanity.work'].includes(url.hostname)) {
128
+ if (isImage && ['cdn.sanity.io', 'cdn.sanity.work'].includes(url.hostname) && token) {
129
129
  headers.Authorization = `Bearer ${token}`
130
130
  url.query = {...(url.query || {}), dlRaw: 'true'}
131
131
  }
@@ -168,14 +168,14 @@ class AssetHandler {
168
168
  const remoteSha1 = stream.headers['x-sanity-sha1']
169
169
  const remoteMd5 = stream.headers['x-sanity-md5']
170
170
  const hasHash = Boolean(remoteSha1 || remoteMd5)
171
- const method = md5 ? 'md5' : 'sha1'
172
-
173
- let differs = false
174
- if (remoteMd5 && md5) {
175
- differs = remoteMd5 !== md5
176
- } else if (remoteSha1 && sha1) {
177
- differs = remoteSha1 !== sha1
178
- }
171
+ const method = sha1 ? 'sha1' : 'md5'
172
+
173
+ // Asset validity is primarily determined by the sha1 hash. However, the sha1 hash is computed
174
+ // before certain processes (i.e. svg sanitization) which can result in a different hash.
175
+ // When the sha1 hashes don't match, fallback to using the md5 hash.
176
+ const sha1Differs = remoteSha1 && sha1 !== remoteSha1
177
+ const md5Differs = remoteMd5 && md5 !== remoteMd5
178
+ const differs = sha1Differs && md5Differs
179
179
 
180
180
  if (differs && attemptNum < 3) {
181
181
  debug('%s does not match downloaded asset, retrying (#%d) [%s]', method, attemptNum + 1, url)
@@ -1,356 +0,0 @@
1
- "use strict";
2
-
3
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
4
-
5
- const path = require('path');
6
-
7
- const crypto = require('crypto');
8
-
9
- const {
10
- parse: parseUrl,
11
- format: formatUrl
12
- } = require('url');
13
-
14
- const {
15
- mkdirSync,
16
- createWriteStream
17
- } = require('fs');
18
-
19
- const miss = require('mississippi');
20
-
21
- const PQueue = require('p-queue');
22
-
23
- const {
24
- omit,
25
- noop
26
- } = require('lodash');
27
-
28
- const pkg = require('../package.json');
29
-
30
- const requestStream = require('./requestStream');
31
-
32
- const debug = require('./debug');
33
-
34
- const rimraf = require('./util/rimraf');
35
-
36
- const EXCLUDE_PROPS = ['_id', '_type', 'assetId', 'extension', 'mimeType', 'path', 'url'];
37
- const ACTION_REMOVE = 'remove';
38
- const ACTION_REWRITE = 'rewrite';
39
- const ASSET_DOWNLOAD_CONCURRENCY = 8;
40
-
41
- class AssetHandler {
42
- constructor(options) {
43
- _defineProperty(this, "rewriteAssets", miss.through.obj(async (doc, enc, callback) => {
44
- if (['sanity.imageAsset', 'sanity.fileAsset'].includes(doc._type)) {
45
- const type = doc._type === 'sanity.imageAsset' ? 'image' : 'file';
46
- const filePath = "".concat(type, "s/").concat(generateFilename(doc._id));
47
- this.assetsSeen.set(doc._id, type);
48
- this.queueAssetDownload(doc, filePath, type);
49
- callback();
50
- return;
51
- }
52
-
53
- callback(null, this.findAndModify(doc, ACTION_REWRITE));
54
- }));
55
-
56
- _defineProperty(this, "stripAssets", miss.through.obj(async (doc, enc, callback) => {
57
- if (['sanity.imageAsset', 'sanity.fileAsset'].includes(doc._type)) {
58
- callback();
59
- return;
60
- }
61
-
62
- callback(null, this.findAndModify(doc, ACTION_REMOVE));
63
- }));
64
-
65
- _defineProperty(this, "skipAssets", miss.through.obj((doc, enc, callback) => {
66
- const isAsset = ['sanity.imageAsset', 'sanity.fileAsset'].includes(doc._type);
67
-
68
- if (isAsset) {
69
- callback();
70
- return;
71
- }
72
-
73
- callback(null, doc);
74
- }));
75
-
76
- _defineProperty(this, "noop", miss.through.obj((doc, enc, callback) => callback(null, doc)));
77
-
78
- _defineProperty(this, "findAndModify", (item, action) => {
79
- if (Array.isArray(item)) {
80
- const children = item.map(child => this.findAndModify(child, action));
81
- return children.filter(Boolean);
82
- }
83
-
84
- if (!item || typeof item !== 'object') {
85
- return item;
86
- }
87
-
88
- const isAsset = isAssetField(item);
89
-
90
- if (isAsset && action === ACTION_REMOVE) {
91
- return undefined;
92
- }
93
-
94
- if (isAsset && action === ACTION_REWRITE) {
95
- const {
96
- asset,
97
- ...other
98
- } = item;
99
- const assetId = asset._ref;
100
- const assetType = getAssetType(item);
101
- const filePath = "".concat(assetType, "s/").concat(generateFilename(assetId));
102
- return {
103
- _sanityAsset: "".concat(assetType, "@file://./").concat(filePath),
104
- ...this.findAndModify(other, action)
105
- };
106
- }
107
-
108
- const newItem = {};
109
- const keys = Object.keys(item);
110
-
111
- for (let i = 0; i < keys.length; i++) {
112
- const key = keys[i];
113
- const value = item[key];
114
- newItem[key] = this.findAndModify(value, action);
115
-
116
- if (typeof newItem[key] === 'undefined') {
117
- delete newItem[key];
118
- }
119
- }
120
-
121
- return newItem;
122
- });
123
-
124
- const concurrency = options.concurrency || ASSET_DOWNLOAD_CONCURRENCY;
125
- debug('Using asset download concurrency of %d', concurrency);
126
- this.client = options.client;
127
- this.tmpDir = options.tmpDir;
128
- this.assetDirsCreated = false;
129
- this.downloading = [];
130
- this.assetsSeen = new Map();
131
- this.assetMap = {};
132
- this.filesWritten = 0;
133
- this.queueSize = 0;
134
- this.queue = options.queue || new PQueue({
135
- concurrency
136
- });
137
- this.rejectedError = null;
138
-
139
- this.reject = err => {
140
- this.rejectedError = err;
141
- };
142
- }
143
-
144
- clear() {
145
- this.assetsSeen.clear();
146
- this.queue.clear();
147
- this.queueSize = 0;
148
- }
149
-
150
- finish() {
151
- return new Promise((resolve, reject) => {
152
- if (this.rejectedError) {
153
- reject(this.rejectedError);
154
- return;
155
- }
156
-
157
- this.reject = reject;
158
- this.queue.onIdle().then(() => resolve(this.assetMap));
159
- });
160
- } // Called when we want to download all assets to local filesystem and rewrite documents to hold
161
- // placeholder asset references (_sanityAsset: 'image@file:///local/path')
162
-
163
-
164
- queueAssetDownload(assetDoc, dstPath, type) {
165
- if (!assetDoc.url) {
166
- debug('Asset document "%s" does not have a URL property, skipping', assetDoc._id);
167
- return;
168
- }
169
-
170
- debug('Adding download task for %s (destination: %s)', assetDoc._id, dstPath);
171
- this.queueSize++;
172
- this.downloading.push(assetDoc.url);
173
- this.queue.add(() => this.downloadAsset(assetDoc, dstPath));
174
- }
175
-
176
- maybeCreateAssetDirs() {
177
- if (this.assetDirsCreated) {
178
- return;
179
- }
180
- /* eslint-disable no-sync */
181
-
182
-
183
- mkdirSync(path.join(this.tmpDir, 'files'), {
184
- recursive: true
185
- });
186
- mkdirSync(path.join(this.tmpDir, 'images'), {
187
- recursive: true
188
- });
189
- /* eslint-enable no-sync */
190
-
191
- this.assetDirsCreated = true;
192
- }
193
-
194
- getAssetRequestOptions(assetDoc) {
195
- const token = this.client.config().token;
196
- const headers = {
197
- 'User-Agent': "".concat(pkg.name, "@").concat(pkg.version)
198
- };
199
- const isImage = assetDoc._type === 'sanity.imageAsset';
200
- const url = parseUrl(assetDoc.url, true);
201
-
202
- if (isImage && ['cdn.sanity.io', 'cdn.sanity.work'].includes(url.hostname)) {
203
- headers.Authorization = "Bearer ".concat(token);
204
- url.query = { ...(url.query || {}),
205
- dlRaw: 'true'
206
- };
207
- }
208
-
209
- return {
210
- url: formatUrl(url),
211
- headers
212
- };
213
- }
214
-
215
- async downloadAsset(assetDoc, dstPath) {
216
- let attemptNum = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
217
- const {
218
- url
219
- } = assetDoc;
220
- const options = this.getAssetRequestOptions(assetDoc);
221
- let stream;
222
-
223
- try {
224
- stream = await requestStream(options);
225
- } catch (err) {
226
- this.reject(err);
227
- return false;
228
- }
229
-
230
- if (stream.statusCode !== 200) {
231
- this.queue.clear();
232
- const err = await tryGetErrorFromStream(stream);
233
- let errMsg = "Referenced asset URL \"".concat(url, "\" returned HTTP ").concat(stream.statusCode);
234
-
235
- if (err) {
236
- errMsg = "".concat(errMsg, ":\n\n").concat(err);
237
- }
238
-
239
- this.reject(new Error(errMsg));
240
- return false;
241
- }
242
-
243
- this.maybeCreateAssetDirs();
244
- debug('Asset stream ready, writing to filesystem at %s', dstPath);
245
- const tmpPath = path.join(this.tmpDir, dstPath);
246
- const {
247
- sha1,
248
- md5,
249
- size
250
- } = await writeHashedStream(tmpPath, stream); // Verify it against our downloaded stream to make sure we have the same copy
251
-
252
- const contentLength = stream.headers['content-length'];
253
- const remoteSha1 = stream.headers['x-sanity-sha1'];
254
- const remoteMd5 = stream.headers['x-sanity-md5'];
255
- const hasHash = Boolean(remoteSha1 || remoteMd5);
256
- const method = md5 ? 'md5' : 'sha1';
257
- let differs = false;
258
-
259
- if (remoteMd5 && md5) {
260
- differs = remoteMd5 !== md5;
261
- } else if (remoteSha1 && sha1) {
262
- differs = remoteSha1 !== sha1;
263
- }
264
-
265
- if (differs && attemptNum < 3) {
266
- debug('%s does not match downloaded asset, retrying (#%d) [%s]', method, attemptNum + 1, url);
267
- return this.downloadAsset(assetDoc, dstPath, attemptNum + 1);
268
- } else if (differs) {
269
- const details = [hasHash && (method === 'md5' ? "md5 should be ".concat(remoteMd5, ", got ").concat(md5) : "sha1 should be ".concat(remoteSha1, ", got ").concat(sha1)), contentLength && parseInt(contentLength, 10) !== size && "Asset should be ".concat(contentLength, " bytes, got ").concat(size), "Did not succeed after ".concat(attemptNum, " attempts.")];
270
- const detailsString = "Details:\n - ".concat(details.filter(Boolean).join('\n - '));
271
- await rimraf(tmpPath);
272
- this.queue.clear();
273
- const error = new Error("Failed to download asset at ".concat(assetDoc.url, ", giving up. ").concat(detailsString));
274
- this.reject(error);
275
- return false;
276
- }
277
-
278
- const isImage = assetDoc._type === 'sanity.imageAsset';
279
- const type = isImage ? 'image' : 'file';
280
- const id = "".concat(type, "-").concat(sha1);
281
- const metaProps = omit(assetDoc, EXCLUDE_PROPS);
282
-
283
- if (Object.keys(metaProps).length > 0) {
284
- this.assetMap[id] = metaProps;
285
- }
286
-
287
- this.downloading.splice(this.downloading.findIndex(datUrl => datUrl === url), 1);
288
- this.filesWritten++;
289
- return true;
290
- }
291
-
292
- }
293
-
294
- function isAssetField(item) {
295
- return item.asset && item.asset._ref && isSanityAsset(item.asset._ref);
296
- }
297
-
298
- function getAssetType(item) {
299
- if (!item.asset || typeof item.asset._ref !== 'string') {
300
- return null;
301
- }
302
-
303
- const [, type] = item.asset._ref.match(/^(image|file)-/) || [];
304
- return type || null;
305
- }
306
-
307
- function isSanityAsset(assetId) {
308
- return /^image-[a-f0-9]{40}-\d+x\d+-[a-z]+$/.test(assetId) || /^file-[a-f0-9]{40}-[a-z0-9]+$/.test(assetId);
309
- }
310
-
311
- function generateFilename(assetId) {
312
- const [,, asset, ext] = assetId.match(/^(image|file)-(.*?)(-[a-z]+)?$/) || [];
313
- const extension = (ext || 'bin').replace(/^-/, '');
314
- return asset ? "".concat(asset, ".").concat(extension) : "".concat(assetId, ".bin");
315
- }
316
-
317
- function writeHashedStream(filePath, stream) {
318
- let size = 0;
319
- const md5 = crypto.createHash('md5');
320
- const sha1 = crypto.createHash('sha1');
321
- const hasher = miss.through((chunk, enc, cb) => {
322
- size += chunk.length;
323
- md5.update(chunk);
324
- sha1.update(chunk);
325
- cb(null, chunk);
326
- });
327
- return new Promise((resolve, reject) => miss.pipe(stream, hasher, createWriteStream(filePath), err => {
328
- if (err) {
329
- reject(err);
330
- return;
331
- }
332
-
333
- resolve({
334
- size,
335
- sha1: sha1.digest('hex'),
336
- md5: md5.digest('hex')
337
- });
338
- }));
339
- }
340
-
341
- function tryGetErrorFromStream(stream) {
342
- return new Promise((resolve, reject) => {
343
- miss.pipe(stream, miss.concat(parse), err => err ? reject(err) : noop);
344
-
345
- function parse(body) {
346
- try {
347
- const parsed = JSON.parse(body.toString('utf8'));
348
- resolve(parsed.message || parsed.error || null);
349
- } catch (err) {
350
- resolve(body.toString('utf8').slice(0, 16000));
351
- }
352
- }
353
- });
354
- }
355
-
356
- module.exports = AssetHandler;
package/lib/debug.js DELETED
@@ -1,3 +0,0 @@
1
- "use strict";
2
-
3
- module.exports = require('debug')('sanity:export');
package/lib/export.js DELETED
@@ -1,222 +0,0 @@
1
- "use strict";
2
-
3
- const os = require('os');
4
-
5
- const path = require('path');
6
-
7
- const zlib = require('zlib');
8
-
9
- const fs = require('fs');
10
-
11
- const miss = require('mississippi');
12
-
13
- const split = require('split2');
14
-
15
- const archiver = require('archiver');
16
-
17
- const rimraf = require('./util/rimraf');
18
-
19
- const debug = require('./debug');
20
-
21
- const AssetHandler = require('./AssetHandler');
22
-
23
- const stringifyStream = require('./stringifyStream');
24
-
25
- const validateOptions = require('./validateOptions');
26
-
27
- const rejectOnApiError = require('./rejectOnApiError');
28
-
29
- const getDocumentsStream = require('./getDocumentsStream');
30
-
31
- const filterSystemDocuments = require('./filterSystemDocuments');
32
-
33
- const filterDocumentTypes = require('./filterDocumentTypes');
34
-
35
- const filterDrafts = require('./filterDrafts');
36
-
37
- const logFirstChunk = require('./logFirstChunk');
38
-
39
- const tryParseJson = require('./tryParseJson');
40
-
41
- const noop = () => null;
42
-
43
- function exportDataset(opts) {
44
- const options = validateOptions(opts);
45
- const onProgress = options.onProgress || noop;
46
- const archive = archiver('tar', {
47
- gzip: true,
48
- gzipOptions: {
49
- level: options.compress ? zlib.Z_DEFAULT_COMPRESSION : zlib.Z_NO_COMPRESSION
50
- }
51
- });
52
- const slugDate = new Date().toISOString().replace(/[^a-z0-9]/gi, '-').toLowerCase();
53
- const prefix = "".concat(opts.dataset, "-export-").concat(slugDate);
54
- const tmpDir = path.join(os.tmpdir(), prefix);
55
-
56
- const cleanup = () => rimraf(tmpDir).catch(err => {
57
- debug("Error while cleaning up temporary files: ".concat(err.message));
58
- });
59
-
60
- const assetHandler = new AssetHandler({
61
- client: options.client,
62
- tmpDir,
63
- prefix,
64
- concurrency: options.assetConcurrency
65
- });
66
- debug('Outputting assets (temporarily) to %s', tmpDir);
67
- debug('Outputting to %s', options.outputPath === '-' ? 'stdout' : options.outputPath);
68
- let outputStream;
69
-
70
- if (isWritableStream(options.outputPath)) {
71
- outputStream = options.outputPath;
72
- } else {
73
- outputStream = options.outputPath === '-' ? process.stdout : fs.createWriteStream(options.outputPath);
74
- }
75
-
76
- let assetStreamHandler = assetHandler.noop;
77
-
78
- if (!options.raw) {
79
- assetStreamHandler = options.assets ? assetHandler.rewriteAssets : assetHandler.stripAssets;
80
- }
81
-
82
- return new Promise(async (resolve, reject) => {
83
- miss.finished(archive, async archiveErr => {
84
- if (archiveErr) {
85
- debug('Archiving errored! %s', archiveErr.stack);
86
- await cleanup();
87
- reject(archiveErr);
88
- return;
89
- }
90
-
91
- debug('Archive finished!');
92
- });
93
- debug('Getting dataset export stream');
94
- onProgress({
95
- step: 'Exporting documents...'
96
- });
97
- let documentCount = 0;
98
- let lastReported = Date.now();
99
-
100
- const reportDocumentCount = (chunk, enc, cb) => {
101
- ++documentCount;
102
- const now = Date.now();
103
-
104
- if (now - lastReported > 50) {
105
- onProgress({
106
- step: 'Exporting documents...',
107
- current: documentCount,
108
- total: '?',
109
- update: true
110
- });
111
- lastReported = now;
112
- }
113
-
114
- cb(null, chunk);
115
- };
116
-
117
- const inputStream = await getDocumentsStream(options.client, options.dataset);
118
- debug('Got HTTP %d', inputStream.statusCode);
119
- debug('Response headers: %o', inputStream.headers);
120
- const jsonStream = miss.pipeline(inputStream, logFirstChunk(), split(tryParseJson), rejectOnApiError(), filterSystemDocuments(), assetStreamHandler, filterDocumentTypes(options.types), options.drafts ? miss.through.obj() : filterDrafts(), stringifyStream(), miss.through(reportDocumentCount));
121
- miss.finished(jsonStream, async err => {
122
- if (err) {
123
- return;
124
- }
125
-
126
- onProgress({
127
- step: 'Exporting documents...',
128
- current: documentCount,
129
- total: documentCount,
130
- update: true
131
- });
132
-
133
- if (!options.raw && options.assets) {
134
- onProgress({
135
- step: 'Downloading assets...'
136
- });
137
- }
138
-
139
- let prevCompleted = 0;
140
- const progressInterval = setInterval(() => {
141
- const completed = assetHandler.queueSize - assetHandler.queue.size - assetHandler.queue.pending;
142
-
143
- if (prevCompleted === completed) {
144
- return;
145
- }
146
-
147
- prevCompleted = completed;
148
- onProgress({
149
- step: 'Downloading assets...',
150
- current: completed,
151
- total: assetHandler.queueSize,
152
- update: true
153
- });
154
- }, 500);
155
- debug('Waiting for asset handler to complete downloads');
156
-
157
- try {
158
- const assetMap = await assetHandler.finish(); // Make sure we mark the progress as done (eg 100/100 instead of 99/100)
159
-
160
- onProgress({
161
- step: 'Downloading assets...',
162
- current: assetHandler.queueSize,
163
- total: assetHandler.queueSize,
164
- update: true
165
- });
166
- archive.append(JSON.stringify(assetMap), {
167
- name: 'assets.json',
168
- prefix
169
- });
170
- clearInterval(progressInterval);
171
- } catch (assetErr) {
172
- clearInterval(progressInterval);
173
- await cleanup();
174
- reject(assetErr);
175
- return;
176
- } // Add all downloaded assets to archive
177
-
178
-
179
- archive.directory(path.join(tmpDir, 'files'), "".concat(prefix, "/files"), {
180
- store: true
181
- });
182
- archive.directory(path.join(tmpDir, 'images'), "".concat(prefix, "/images"), {
183
- store: true
184
- });
185
- debug('Finalizing archive, flushing streams');
186
- onProgress({
187
- step: 'Adding assets to archive...'
188
- });
189
- archive.finalize();
190
- });
191
- archive.on('warning', err => {
192
- debug('Archive warning: %s', err.message);
193
- });
194
- archive.append(jsonStream, {
195
- name: 'data.ndjson',
196
- prefix
197
- });
198
- miss.pipe(archive, outputStream, onComplete);
199
-
200
- async function onComplete(err) {
201
- onProgress({
202
- step: 'Clearing temporary files...'
203
- });
204
- await cleanup();
205
-
206
- if (!err) {
207
- resolve();
208
- return;
209
- }
210
-
211
- debug('Error during streaming: %s', err.stack);
212
- assetHandler.clear();
213
- reject(err);
214
- }
215
- });
216
- }
217
-
218
- function isWritableStream(val) {
219
- return val !== null && typeof val === 'object' && typeof val.pipe === 'function' && typeof val._write === 'function' && typeof val._writableState === 'object';
220
- }
221
-
222
- module.exports = exportDataset;
@@ -1,14 +0,0 @@
1
- "use strict";
2
-
3
- const miss = require('mississippi');
4
-
5
- module.exports = allowedTypes => allowedTypes ? miss.through.obj((doc, enc, callback) => {
6
- const type = doc && doc._type;
7
-
8
- if (allowedTypes.includes(type)) {
9
- callback(null, doc);
10
- return;
11
- }
12
-
13
- callback();
14
- }) : miss.through.obj();
@@ -1,13 +0,0 @@
1
- "use strict";
2
-
3
- const miss = require('mississippi');
4
-
5
- const isDraft = doc => doc && doc._id && doc._id.indexOf('drafts.') === 0;
6
-
7
- module.exports = () => miss.through.obj((doc, enc, callback) => {
8
- if (isDraft(doc)) {
9
- return callback();
10
- }
11
-
12
- return callback(null, doc);
13
- });
@@ -1,16 +0,0 @@
1
- "use strict";
2
-
3
- const miss = require('mississippi');
4
-
5
- const debug = require('./debug');
6
-
7
- const isSystemDocument = doc => doc && doc._id && doc._id.indexOf('_.') === 0;
8
-
9
- module.exports = () => miss.through.obj((doc, enc, callback) => {
10
- if (isSystemDocument(doc)) {
11
- debug('%s is a system document, skipping', doc && doc._id);
12
- return callback();
13
- }
14
-
15
- return callback(null, doc);
16
- });
@@ -1,22 +0,0 @@
1
- "use strict";
2
-
3
- const pkg = require('../package.json');
4
-
5
- const requestStream = require('./requestStream');
6
-
7
- module.exports = (client, dataset) => {
8
- // Sanity client doesn't handle streams natively since we want to support node/browser
9
- // with same API. We're just using it here to get hold of URLs and tokens.
10
- const url = client.getUrl("/data/export/".concat(dataset));
11
- const token = client.config().token;
12
- const headers = {
13
- 'User-Agent': "".concat(pkg.name, "@").concat(pkg.version),
14
- ...(token ? {
15
- Authorization: "Bearer ".concat(token)
16
- } : {})
17
- };
18
- return requestStream({
19
- url,
20
- headers
21
- });
22
- };
@@ -1,18 +0,0 @@
1
- "use strict";
2
-
3
- const miss = require('mississippi');
4
-
5
- const debug = require('./debug');
6
-
7
- module.exports = () => {
8
- let firstChunk = true;
9
- return miss.through((chunk, enc, callback) => {
10
- if (firstChunk) {
11
- const string = chunk.toString('utf8').split('\n')[0];
12
- debug('First chunk received: %s', string.slice(0, 300));
13
- firstChunk = false;
14
- }
15
-
16
- callback(null, chunk);
17
- });
18
- };
@@ -1,17 +0,0 @@
1
- "use strict";
2
-
3
- const miss = require('mississippi');
4
-
5
- module.exports = () => miss.through.obj((doc, enc, callback) => {
6
- if (doc.error && doc.statusCode) {
7
- callback(new Error([doc.statusCode, doc.error].join(': ')));
8
- return;
9
- }
10
-
11
- if (!doc._id && doc.error) {
12
- callback(new Error(doc.error.description || doc.error.message || JSON.stringify(doc)));
13
- return;
14
- }
15
-
16
- callback(null, doc);
17
- });
@@ -1,63 +0,0 @@
1
- "use strict";
2
-
3
- const getIt = require('get-it');
4
-
5
- const {
6
- keepAlive,
7
- promise
8
- } = require('get-it/middleware');
9
-
10
- const debug = require('./debug');
11
-
12
- const request = getIt([keepAlive(), promise({
13
- onlyBody: true
14
- })]);
15
- const socketsWithTimeout = new WeakSet();
16
- const CONNECTION_TIMEOUT = 15 * 1000; // 15 seconds
17
-
18
- const READ_TIMEOUT = 3 * 60 * 1000; // 3 minutes
19
-
20
- const MAX_RETRIES = 5;
21
-
22
- function delay(ms) {
23
- return new Promise(resolve => setTimeout(resolve, ms));
24
- }
25
- /* eslint-disable no-await-in-loop, max-depth */
26
-
27
-
28
- module.exports = async options => {
29
- let error;
30
-
31
- for (let i = 0; i < MAX_RETRIES; i++) {
32
- try {
33
- const response = await request({ ...options,
34
- stream: true,
35
- maxRedirects: 0,
36
- timeout: {
37
- connect: CONNECTION_TIMEOUT,
38
- socket: READ_TIMEOUT
39
- }
40
- });
41
-
42
- if (response.connection && typeof response.connection.setTimeout === 'function' && !socketsWithTimeout.has(response.connection)) {
43
- socketsWithTimeout.add(response.connection);
44
- response.connection.setTimeout(READ_TIMEOUT, () => {
45
- response.destroy(new Error("Read timeout: No data received on socket for ".concat(READ_TIMEOUT, " ms")));
46
- });
47
- }
48
-
49
- return response;
50
- } catch (err) {
51
- error = err;
52
-
53
- if (err.response && err.response.statusCode && err.response.statusCode < 500) {
54
- break;
55
- }
56
-
57
- debug('Error, retrying after 1500ms: %s', err.message);
58
- await delay(1500);
59
- }
60
- }
61
-
62
- throw error;
63
- };
@@ -1,5 +0,0 @@
1
- "use strict";
2
-
3
- const miss = require('mississippi');
4
-
5
- module.exports = () => miss.through.obj((doc, enc, callback) => callback(null, "".concat(JSON.stringify(doc), "\n")));
@@ -1,25 +0,0 @@
1
- "use strict";
2
-
3
- module.exports = line => {
4
- try {
5
- return JSON.parse(line);
6
- } catch (err) {
7
- // Catch half-done lines with an error at the end
8
- const errorPosition = line.lastIndexOf('{"error":');
9
-
10
- if (errorPosition === -1) {
11
- err.message = "".concat(err.message, " (").concat(line, ")");
12
- throw err;
13
- }
14
-
15
- const errorJson = line.slice(errorPosition);
16
- const errorLine = JSON.parse(errorJson);
17
- const error = errorLine && errorLine.error;
18
-
19
- if (error && error.description) {
20
- throw new Error("Error streaming dataset: ".concat(error.description, "\n\n").concat(errorJson, "\n"));
21
- }
22
-
23
- throw err;
24
- }
25
- };
@@ -1,9 +0,0 @@
1
- "use strict";
2
-
3
- const {
4
- promisify
5
- } = require('util');
6
-
7
- const rimrafCb = require('rimraf');
8
-
9
- module.exports = promisify(rimrafCb);
@@ -1,58 +0,0 @@
1
- "use strict";
2
-
3
- const defaults = require('lodash/defaults');
4
-
5
- const clientMethods = ['getUrl', 'config'];
6
- const booleanFlags = ['assets', 'raw', 'compress', 'drafts'];
7
- const exportDefaults = {
8
- compress: true,
9
- drafts: true,
10
- assets: true,
11
- raw: false
12
- };
13
-
14
- function validateOptions(opts) {
15
- const options = defaults({}, opts, exportDefaults);
16
-
17
- if (typeof options.dataset !== 'string' || options.dataset.length < 1) {
18
- throw new Error("options.dataset must be a valid dataset name");
19
- }
20
-
21
- if (options.onProgress && typeof options.onProgress !== 'function') {
22
- throw new Error("options.onProgress must be a function");
23
- }
24
-
25
- if (!options.client) {
26
- throw new Error('`options.client` must be set to an instance of @sanity/client');
27
- }
28
-
29
- const missing = clientMethods.find(key => typeof options.client[key] !== 'function');
30
-
31
- if (missing) {
32
- throw new Error("`options.client` is not a valid @sanity/client instance - no \"".concat(missing, "\" method found"));
33
- }
34
-
35
- const clientConfig = options.client.config();
36
-
37
- if (!clientConfig.token) {
38
- throw new Error('Client is not instantiated with a `token`');
39
- }
40
-
41
- booleanFlags.forEach(flag => {
42
- if (typeof options[flag] !== 'boolean') {
43
- throw new Error("Flag ".concat(flag, " must be a boolean (true/false)"));
44
- }
45
- });
46
-
47
- if (!options.outputPath) {
48
- throw new Error('outputPath must be specified (- for stdout)');
49
- }
50
-
51
- if (options.assetConcurrency && (options.assetConcurrency < 1 || options.assetConcurrency > 24)) {
52
- throw new Error('`assetConcurrency` must be between 1 and 24');
53
- }
54
-
55
- return options;
56
- }
57
-
58
- module.exports = validateOptions;