@sanity/export 5.0.1 → 6.0.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.
Files changed (115) hide show
  1. package/dist/AssetHandler.d.ts +47 -0
  2. package/dist/AssetHandler.d.ts.map +1 -0
  3. package/dist/AssetHandler.js +384 -0
  4. package/dist/AssetHandler.js.map +1 -0
  5. package/dist/constants.d.ts +45 -0
  6. package/dist/constants.d.ts.map +1 -0
  7. package/{src → dist}/constants.js +13 -18
  8. package/dist/constants.js.map +1 -0
  9. package/dist/debug.d.ts +3 -0
  10. package/dist/debug.d.ts.map +1 -0
  11. package/dist/debug.js +3 -0
  12. package/dist/debug.js.map +1 -0
  13. package/dist/export.d.ts +43 -0
  14. package/dist/export.d.ts.map +1 -0
  15. package/dist/export.js +269 -0
  16. package/dist/export.js.map +1 -0
  17. package/dist/filterDocumentTypes.d.ts +3 -0
  18. package/dist/filterDocumentTypes.d.ts.map +1 -0
  19. package/dist/filterDocumentTypes.js +16 -0
  20. package/dist/filterDocumentTypes.js.map +1 -0
  21. package/dist/filterDocuments.d.ts +3 -0
  22. package/dist/filterDocuments.d.ts.map +1 -0
  23. package/dist/filterDocuments.js +36 -0
  24. package/dist/filterDocuments.js.map +1 -0
  25. package/dist/getDocumentCursorStream.d.ts +4 -0
  26. package/dist/getDocumentCursorStream.d.ts.map +1 -0
  27. package/dist/getDocumentCursorStream.js +85 -0
  28. package/dist/getDocumentCursorStream.js.map +1 -0
  29. package/dist/getDocumentsStream.d.ts +5 -0
  30. package/dist/getDocumentsStream.d.ts.map +1 -0
  31. package/dist/getDocumentsStream.js +28 -0
  32. package/dist/getDocumentsStream.js.map +1 -0
  33. package/dist/getUserAgent.d.ts +2 -0
  34. package/dist/getUserAgent.d.ts.map +1 -0
  35. package/dist/getUserAgent.js +12 -0
  36. package/dist/getUserAgent.js.map +1 -0
  37. package/dist/index.d.ts +3 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +3 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/logFirstChunk.d.ts +3 -0
  42. package/dist/logFirstChunk.d.ts.map +1 -0
  43. package/dist/logFirstChunk.js +14 -0
  44. package/dist/logFirstChunk.js.map +1 -0
  45. package/dist/options.d.ts +14 -0
  46. package/dist/options.d.ts.map +1 -0
  47. package/dist/options.js +97 -0
  48. package/dist/options.js.map +1 -0
  49. package/dist/rejectOnApiError.d.ts +3 -0
  50. package/dist/rejectOnApiError.d.ts.map +1 -0
  51. package/dist/rejectOnApiError.js +35 -0
  52. package/dist/rejectOnApiError.js.map +1 -0
  53. package/dist/requestStream.d.ts +3 -0
  54. package/dist/requestStream.d.ts.map +1 -0
  55. package/dist/requestStream.js +48 -0
  56. package/dist/requestStream.js.map +1 -0
  57. package/dist/stringifyStream.d.ts +3 -0
  58. package/dist/stringifyStream.d.ts.map +1 -0
  59. package/dist/stringifyStream.js +5 -0
  60. package/dist/stringifyStream.js.map +1 -0
  61. package/dist/tryParseJson.d.ts +10 -0
  62. package/dist/tryParseJson.d.ts.map +1 -0
  63. package/dist/tryParseJson.js +36 -0
  64. package/dist/tryParseJson.js.map +1 -0
  65. package/dist/types.d.ts +241 -0
  66. package/dist/types.d.ts.map +1 -0
  67. package/dist/types.js +2 -0
  68. package/dist/types.js.map +1 -0
  69. package/dist/util/delay.d.ts +2 -0
  70. package/dist/util/delay.d.ts.map +1 -0
  71. package/dist/util/delay.js +4 -0
  72. package/dist/util/delay.js.map +1 -0
  73. package/dist/util/extractFirstError.d.ts +2 -0
  74. package/dist/util/extractFirstError.d.ts.map +1 -0
  75. package/dist/util/extractFirstError.js +22 -0
  76. package/dist/util/extractFirstError.js.map +1 -0
  77. package/dist/util/friendlyError.d.ts +2 -0
  78. package/dist/util/friendlyError.d.ts.map +1 -0
  79. package/dist/util/friendlyError.js +49 -0
  80. package/dist/util/friendlyError.js.map +1 -0
  81. package/dist/util/streamHelpers.d.ts +10 -0
  82. package/dist/util/streamHelpers.d.ts.map +1 -0
  83. package/dist/util/streamHelpers.js +99 -0
  84. package/dist/util/streamHelpers.js.map +1 -0
  85. package/package.json +22 -7
  86. package/src/{AssetHandler.js → AssetHandler.ts} +174 -99
  87. package/src/constants.ts +50 -0
  88. package/src/debug.ts +3 -0
  89. package/src/{export.js → export.ts} +110 -70
  90. package/src/filterDocumentTypes.ts +21 -0
  91. package/src/filterDocuments.ts +55 -0
  92. package/src/{getDocumentCursorStream.js → getDocumentCursorStream.ts} +37 -18
  93. package/src/{getDocumentsStream.js → getDocumentsStream.ts} +16 -6
  94. package/src/{getUserAgent.js → getUserAgent.ts} +8 -3
  95. package/src/index.ts +11 -0
  96. package/src/{logFirstChunk.js → logFirstChunk.ts} +6 -4
  97. package/src/options.ts +138 -0
  98. package/src/rejectOnApiError.ts +62 -0
  99. package/src/requestStream.ts +81 -0
  100. package/src/stringifyStream.ts +7 -0
  101. package/src/{tryParseJson.js → tryParseJson.ts} +29 -17
  102. package/src/types.ts +274 -0
  103. package/src/util/{delay.js → delay.ts} +1 -1
  104. package/src/util/extractFirstError.ts +31 -0
  105. package/src/util/friendlyError.ts +75 -0
  106. package/src/util/{streamHelpers.js → streamHelpers.ts} +35 -18
  107. package/src/debug.js +0 -3
  108. package/src/filterDocumentTypes.js +0 -18
  109. package/src/filterDocuments.js +0 -33
  110. package/src/rejectOnApiError.js +0 -31
  111. package/src/requestStream.js +0 -64
  112. package/src/stringifyStream.js +0 -5
  113. package/src/util/extractFirstError.js +0 -14
  114. package/src/util/friendlyError.js +0 -58
  115. package/src/validateOptions.js +0 -113
@@ -0,0 +1,75 @@
1
+ interface ErrorWithResponse {
2
+ response: {
3
+ body: NodeJS.ReadableStream
4
+ headers: Record<string, string>
5
+ statusCode?: number
6
+ }
7
+ }
8
+
9
+ interface ErrorBody {
10
+ error?: string
11
+ message?: string
12
+ }
13
+
14
+ function isRecord(thing: unknown): thing is Record<string, unknown> {
15
+ return typeof thing === 'object' && thing !== null && !Array.isArray(thing)
16
+ }
17
+
18
+ function isErrorWithResponse(err: unknown): err is ErrorWithResponse {
19
+ if (!isRecord(err)) {
20
+ return false
21
+ }
22
+
23
+ if (!('response' in err) || !isRecord(err.response)) {
24
+ return false
25
+ }
26
+
27
+ const response = err.response
28
+ return (
29
+ 'body' in response &&
30
+ isRecord(response.body) &&
31
+ 'pipe' in response.body &&
32
+ 'headers' in response &&
33
+ isRecord(response.headers)
34
+ )
35
+ }
36
+
37
+ async function readBody(req: NodeJS.ReadableStream): Promise<Buffer> {
38
+ const chunks: Buffer[] = []
39
+ for await (const chunk of req) {
40
+ chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : Buffer.from(chunk as Uint8Array))
41
+ }
42
+ return Buffer.concat(chunks)
43
+ }
44
+
45
+ async function readBodyJson(req: NodeJS.ReadableStream): Promise<unknown> {
46
+ return JSON.parse((await readBody(req)).toString('utf8'))
47
+ }
48
+
49
+ export async function tryThrowFriendlyError(err: unknown): Promise<null> {
50
+ if (!isErrorWithResponse(err)) {
51
+ return null
52
+ }
53
+
54
+ const contentType = err.response.headers['content-type']
55
+ if (typeof contentType !== 'string' || !contentType.includes('application/json')) {
56
+ return null
57
+ }
58
+
59
+ const body = await readBodyJson(err.response.body)
60
+
61
+ if (!isRecord(body)) {
62
+ return null
63
+ }
64
+
65
+ const typedBody = body as ErrorBody
66
+ const status =
67
+ typeof err.response.statusCode === 'number' ? `HTTP ${err.response.statusCode}` : undefined
68
+ const error = typeof typedBody.error === 'string' ? typedBody.error : undefined
69
+ const message = typeof typedBody.message === 'string' ? typedBody.message : undefined
70
+ if (!error && !message) {
71
+ return null
72
+ }
73
+
74
+ throw new Error(['Export', status, error, message].filter(Boolean).join(': '))
75
+ }
@@ -1,63 +1,80 @@
1
- import {Transform} from 'node:stream'
1
+ import {Transform, type TransformCallback, type Writable} from 'node:stream'
2
2
 
3
- export function through(transformFn) {
3
+ type TransformFunction = (
4
+ chunk: Buffer,
5
+ encoding: BufferEncoding,
6
+ callback: TransformCallback,
7
+ ) => void
8
+
9
+ type TransformObjFunction<T, R> = (
10
+ chunk: T,
11
+ encoding: BufferEncoding,
12
+ callback: TransformCallback,
13
+ ) => R
14
+
15
+ export function through(transformFn: TransformFunction): Transform {
4
16
  return new Transform({
5
- transform(chunk, encoding, callback) {
17
+ transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback) {
6
18
  transformFn(chunk, encoding, callback)
7
19
  },
8
20
  })
9
21
  }
10
22
 
11
- export function throughObj(transformFn) {
23
+ export function throughObj<T = unknown, R = void>(
24
+ transformFn: TransformObjFunction<T, R>,
25
+ ): Transform {
12
26
  return new Transform({
13
27
  objectMode: true,
14
- transform(chunk, encoding, callback) {
28
+ transform(chunk: T, encoding: BufferEncoding, callback: TransformCallback) {
15
29
  transformFn(chunk, encoding, callback)
16
30
  },
17
31
  })
18
32
  }
19
33
 
20
- export function isWritableStream(val) {
34
+ export function isWritableStream(val: unknown): val is Writable {
21
35
  return (
22
36
  val !== null &&
23
37
  typeof val === 'object' &&
38
+ 'pipe' in val &&
24
39
  typeof val.pipe === 'function' &&
40
+ '_write' in val &&
25
41
  typeof val._write === 'function' &&
42
+ '_writableState' in val &&
26
43
  typeof val._writableState === 'object'
27
44
  )
28
45
  }
29
46
 
30
- export function concat(onData) {
31
- const chunks = []
47
+ export function concat(onData: (chunks: unknown[]) => void): Transform {
48
+ const chunks: unknown[] = []
32
49
  return new Transform({
33
50
  objectMode: true,
34
- transform(chunk, encoding, callback) {
51
+ transform(chunk: unknown, _encoding: BufferEncoding, callback: TransformCallback) {
35
52
  chunks.push(chunk)
36
53
  callback()
37
54
  },
38
- flush(callback) {
55
+ flush(callback: TransformCallback) {
39
56
  try {
40
57
  onData(chunks)
41
58
  callback()
42
59
  } catch (err) {
43
- callback(err)
60
+ callback(err as Error)
44
61
  }
45
62
  },
46
63
  })
47
64
  }
48
65
 
49
- export const split = (transformFn) => {
66
+ export function split(transformFn?: (line: string) => unknown): Transform {
50
67
  let buffer = ''
51
68
  const splitRegex = /\r?\n/
52
69
 
53
70
  return new Transform({
54
- objectMode: !!transformFn,
55
- transform(chunk, encoding, callback) {
71
+ objectMode: Boolean(transformFn),
72
+ transform(chunk: Buffer, _encoding: BufferEncoding, callback: TransformCallback) {
56
73
  buffer += chunk.toString()
57
74
  const lines = buffer.split(splitRegex)
58
75
 
59
76
  // Keep the last line in buffer as it might be incomplete
60
- buffer = lines.pop() || ''
77
+ buffer = lines.pop() ?? ''
61
78
 
62
79
  for (const line of lines) {
63
80
  if (line.length === 0) continue
@@ -69,7 +86,7 @@ export const split = (transformFn) => {
69
86
  this.push(result)
70
87
  }
71
88
  } catch (err) {
72
- callback(err)
89
+ callback(err as Error)
73
90
  return
74
91
  }
75
92
  } else {
@@ -78,7 +95,7 @@ export const split = (transformFn) => {
78
95
  }
79
96
  callback()
80
97
  },
81
- flush(callback) {
98
+ flush(callback: TransformCallback) {
82
99
  if (buffer.length === 0) {
83
100
  callback()
84
101
  return
@@ -96,7 +113,7 @@ export const split = (transformFn) => {
96
113
  }
97
114
  callback()
98
115
  } catch (err) {
99
- callback(err)
116
+ callback(err as Error)
100
117
  }
101
118
  },
102
119
  })
package/src/debug.js DELETED
@@ -1,3 +0,0 @@
1
- import debugIt from 'debug'
2
-
3
- export const debug = debugIt('sanity:export')
@@ -1,18 +0,0 @@
1
- import {throughObj} from './util/streamHelpers.js'
2
-
3
- export function filterDocumentTypes(allowedTypes) {
4
- if (!allowedTypes || allowedTypes.length === 0) {
5
- // Pass-through
6
- return throughObj((doc, enc, callback) => callback(null, doc))
7
- }
8
-
9
- return throughObj(function docTypesFilter(doc, enc, callback) {
10
- const type = doc && doc._type
11
- if (allowedTypes.includes(type)) {
12
- callback(null, doc)
13
- return
14
- }
15
-
16
- callback()
17
- })
18
- }
@@ -1,33 +0,0 @@
1
- import {debug} from './debug.js'
2
- import {throughObj} from './util/streamHelpers.js'
3
-
4
- const isDraftOrVersion = (doc) =>
5
- doc && doc._id && (doc._id.indexOf('drafts.') === 0 || doc._id.indexOf('versions.') === 0)
6
-
7
- const isSystemDocument = (doc) => doc && doc._id && doc._id.indexOf('_.') === 0
8
- const isReleaseDocument = (doc) => doc && doc._id && doc._id.indexOf('_.releases.') === 0
9
- const isCursor = (doc) => doc && !doc._id && doc.nextCursor !== undefined
10
-
11
- export function filterDocuments(drafts) {
12
- return throughObj(function filterDocs(doc, enc, callback) {
13
- if (isCursor(doc)) {
14
- debug('%o is a cursor, skipping', doc)
15
- return callback()
16
- }
17
-
18
- if (!drafts && isDraftOrVersion(doc)) {
19
- debug('%s is a draft or version, skipping', doc && doc._id)
20
- return callback()
21
- }
22
-
23
- if (isSystemDocument(doc)) {
24
- if (drafts && isReleaseDocument(doc)) {
25
- return callback(null, doc)
26
- }
27
- debug('%s is a system document, skipping', doc && doc._id)
28
- return callback()
29
- }
30
-
31
- return callback(null, doc)
32
- })
33
- }
@@ -1,31 +0,0 @@
1
- import {throughObj} from './util/streamHelpers.js'
2
-
3
- export function rejectOnApiError() {
4
- return throughObj((doc, enc, callback) => {
5
- // check if the document passed contains a document attribtue first, and return early.
6
- if (doc._id) {
7
- callback(null, doc)
8
- return
9
- }
10
-
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
25
- callback(new Error(doc.error.description || doc.error.message || JSON.stringify(doc)))
26
- return
27
- }
28
-
29
- callback(null, doc)
30
- })
31
- }
@@ -1,64 +0,0 @@
1
- import {getIt} from 'get-it'
2
- import {keepAlive, promise} from 'get-it/middleware'
3
-
4
- import {
5
- DEFAULT_RETRY_DELAY,
6
- DOCUMENT_STREAM_MAX_RETRIES,
7
- REQUEST_READ_TIMEOUT,
8
- } from './constants.js'
9
- import {debug} from './debug.js'
10
- import {delay} from './util/delay.js'
11
- import {extractFirstError} from './util/extractFirstError.js'
12
- import {tryThrowFriendlyError} from './util/friendlyError.js'
13
-
14
- const request = getIt([keepAlive(), promise({onlyBody: true})])
15
-
16
- const CONNECTION_TIMEOUT = 15 * 1000 // 15 seconds
17
-
18
- /* eslint-disable no-await-in-loop, max-depth */
19
- export async function requestStream(options) {
20
- const maxRetries =
21
- typeof options.maxRetries === 'number' ? options.maxRetries : DOCUMENT_STREAM_MAX_RETRIES
22
-
23
- const readTimeout =
24
- typeof options.readTimeout === 'number' ? options.readTimeout : REQUEST_READ_TIMEOUT
25
-
26
- const retryDelayMs =
27
- typeof options.retryDelayMs === 'number' ? options.retryDelayMs : DEFAULT_RETRY_DELAY
28
-
29
- let error
30
-
31
- let i = 0
32
- do {
33
- i++
34
-
35
- try {
36
- return await request({
37
- ...options,
38
- stream: true,
39
- maxRedirects: 0,
40
- timeout: {connect: CONNECTION_TIMEOUT, socket: readTimeout},
41
- })
42
- } catch (err) {
43
- error = extractFirstError(err) || err
44
-
45
- if (maxRetries === 0) {
46
- throw error
47
- }
48
-
49
- if (err.response && err.response.statusCode && err.response.statusCode < 500) {
50
- break
51
- }
52
-
53
- if (i < maxRetries) {
54
- debug('Error, retrying after %d ms: %s', retryDelayMs, error.message)
55
- await delay(retryDelayMs)
56
- }
57
- }
58
- } while (i < maxRetries)
59
-
60
- await tryThrowFriendlyError(error)
61
-
62
- error.message = `Export: Failed to fetch ${options.url}: ${error.message}`
63
- throw error
64
- }
@@ -1,5 +0,0 @@
1
- import {throughObj} from './util/streamHelpers.js'
2
-
3
- export function stringifyStream() {
4
- return throughObj((doc, enc, callback) => callback(null, `${JSON.stringify(doc)}\n`))
5
- }
@@ -1,14 +0,0 @@
1
- export function extractFirstError(err) {
2
- if (
3
- // eslint-disable-next-line no-undef
4
- ((typeof AggregateError !== 'undefined' && err instanceof AggregateError) ||
5
- ('name' in err && err.name === 'AggregateError')) &&
6
- Array.isArray(err.errors) &&
7
- err.errors.length > 0 &&
8
- 'message' in err.errors[0]
9
- ) {
10
- return err.errors[0]
11
- }
12
-
13
- return err
14
- }
@@ -1,58 +0,0 @@
1
- export async function tryThrowFriendlyError(err) {
2
- if (!isRecord(err)) {
3
- return null
4
- }
5
-
6
- if (!('response' in err) || !isRecord(err.response)) {
7
- return null
8
- }
9
-
10
- if (
11
- !('body' in err.response) ||
12
- !('pipe' in err.response.body) ||
13
- !('headers' in err.response) ||
14
- !isRecord(err.response.headers)
15
- ) {
16
- return null
17
- }
18
-
19
- if (
20
- typeof err.response.headers['content-type'] !== 'string' ||
21
- !err.response.headers['content-type'].includes('application/json')
22
- ) {
23
- return null
24
- }
25
-
26
- const body = await readBodyJson(err.response.body)
27
-
28
- if (!isRecord(body)) {
29
- return null
30
- }
31
-
32
- // Look for Sanity API(ish) standard error shape
33
- const status =
34
- typeof err.response.statusCode === 'number' ? `HTTP ${err.response.statusCode}` : undefined
35
- const error = typeof body.error === 'string' ? body.error : undefined
36
- const message = typeof body.message === 'string' ? body.message : undefined
37
- if (!error && !message) {
38
- return null
39
- }
40
-
41
- throw new Error(['Export', status, error, message].filter(Boolean).join(': '))
42
- }
43
-
44
- function isRecord(thing) {
45
- return typeof thing === 'object' && thing !== null && !Array.isArray(thing)
46
- }
47
-
48
- async function readBody(req) {
49
- const chunks = []
50
- for await (const chunk of req) {
51
- chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk)
52
- }
53
- return Buffer.concat(chunks)
54
- }
55
-
56
- async function readBodyJson(req) {
57
- return JSON.parse((await readBody(req)).toString('utf8'))
58
- }
@@ -1,113 +0,0 @@
1
- import {
2
- ASSET_DOWNLOAD_MAX_RETRIES,
3
- DOCUMENT_STREAM_MAX_RETRIES,
4
- MODE_CURSOR,
5
- MODE_STREAM,
6
- REQUEST_READ_TIMEOUT,
7
- } from './constants.js'
8
-
9
- const clientMethods = ['getUrl', 'config']
10
- const booleanFlags = ['assets', 'raw', 'compress', 'drafts']
11
- const numberFlags = ['maxAssetRetries', 'maxRetries', 'assetConcurrency', 'readTimeout']
12
- const exportDefaults = {
13
- compress: true,
14
- drafts: true,
15
- assets: true,
16
- assetsMap: true,
17
- raw: false,
18
- mode: MODE_STREAM,
19
- maxRetries: DOCUMENT_STREAM_MAX_RETRIES,
20
- maxAssetRetries: ASSET_DOWNLOAD_MAX_RETRIES,
21
- readTimeout: REQUEST_READ_TIMEOUT,
22
- filterDocument: () => true,
23
- transformDocument: (doc) => doc,
24
- }
25
-
26
- export function validateOptions(opts) {
27
- const options = {...exportDefaults, ...opts}
28
-
29
- const resources = [options.dataset, options.mediaLibraryId].filter(
30
- (resource) => typeof resource === 'string' && resource.length !== 0,
31
- )
32
-
33
- if (resources.length === 0) {
34
- throw new Error(
35
- 'either `options.dataset` or `options.mediaLibraryId` must be specified, got neither',
36
- )
37
- }
38
-
39
- if (resources.length === 2) {
40
- throw new Error(
41
- 'either `options.dataset` or `options.mediaLibraryId` must be specified, got both',
42
- )
43
- }
44
-
45
- if (
46
- typeof options.mode !== 'string' ||
47
- (options.mode !== MODE_STREAM && options.mode !== MODE_CURSOR)
48
- ) {
49
- throw new Error(
50
- `options.mode must be either "${MODE_STREAM}" or "${MODE_CURSOR}", got "${options.mode}"`,
51
- )
52
- }
53
-
54
- if (options.onProgress && typeof options.onProgress !== 'function') {
55
- throw new Error(`options.onProgress must be a function`)
56
- }
57
-
58
- if (!options.client) {
59
- throw new Error('`options.client` must be set to an instance of @sanity/client')
60
- }
61
-
62
- const missing = clientMethods.find((key) => typeof options.client[key] !== 'function')
63
- if (missing) {
64
- throw new Error(
65
- `\`options.client\` is not a valid @sanity/client instance - no "${missing}" method found`,
66
- )
67
- }
68
-
69
- const clientConfig = options.client.config()
70
- if (!clientConfig.token) {
71
- throw new Error('Client is not instantiated with a `token`')
72
- }
73
-
74
- booleanFlags.forEach((flag) => {
75
- if (typeof options[flag] !== 'boolean') {
76
- throw new Error(`Flag ${flag} must be a boolean (true/false)`)
77
- }
78
- })
79
-
80
- numberFlags.forEach((flag) => {
81
- if (typeof options[flag] !== 'undefined' && typeof options[flag] !== 'number') {
82
- throw new Error(`Flag ${flag} must be a number if specified`)
83
- }
84
- })
85
-
86
- if (!options.outputPath) {
87
- throw new Error('outputPath must be specified (- for stdout)')
88
- }
89
-
90
- if (options.assetConcurrency && (options.assetConcurrency < 1 || options.assetConcurrency > 24)) {
91
- throw new Error('`assetConcurrency` must be between 1 and 24')
92
- }
93
-
94
- if (
95
- typeof options.filterDocument !== 'undefined' &&
96
- typeof options.filterDocument !== 'function'
97
- ) {
98
- throw new Error('`filterDocument` must be a function')
99
- }
100
-
101
- if (
102
- typeof options.transformDocument !== 'undefined' &&
103
- typeof options.transformDocument !== 'function'
104
- ) {
105
- throw new Error('`transformDocument` must be a function')
106
- }
107
-
108
- if (typeof assetsMap !== 'undefined' && typeof assetsMap !== 'boolean') {
109
- throw new Error('`assetsMap` must be a boolean')
110
- }
111
-
112
- return options
113
- }