@luzzle/core 0.0.63 → 0.0.64
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.
|
@@ -11,6 +11,9 @@ declare function detectStreamFileType(stream: Readable, maxBytes?: number): Prom
|
|
|
11
11
|
stream: Readable;
|
|
12
12
|
}>;
|
|
13
13
|
declare function savePieceAsset(file: string, filename: string, stream: Readable, storage: LuzzleStorage): Promise<string>;
|
|
14
|
+
declare function savePieceAsset(file: string, source: string, storage: LuzzleStorage, options?: {
|
|
15
|
+
name?: string;
|
|
16
|
+
}): Promise<string>;
|
|
14
17
|
declare function savePieceFieldAsset(file: string, field: PieceFrontmatterSchemaField, stream: AttachableStream, storage: LuzzleStorage): Promise<string>;
|
|
15
18
|
declare function isAttachableStream(value: unknown): value is AttachableStream;
|
|
16
19
|
declare function makePieceValue(field: PieceFrontmatterSchemaField, value: PieceFrontMatterValue | AttachableStream): Promise<PieceFrontMatterValue | AttachableStream>;
|
|
@@ -100,21 +100,47 @@ async function detectStreamFileType(stream, maxBytes = 4100) {
|
|
|
100
100
|
stream: Readable.from(gen()),
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
|
-
async function savePieceAsset(file,
|
|
103
|
+
async function savePieceAsset(file, filenameOrSource, streamOrStorage, storageOrOptions) {
|
|
104
|
+
let finalStream;
|
|
105
|
+
let targetFilename;
|
|
106
|
+
let storage;
|
|
107
|
+
if (streamOrStorage &&
|
|
108
|
+
typeof streamOrStorage === 'object' &&
|
|
109
|
+
'pipe' in streamOrStorage &&
|
|
110
|
+
typeof streamOrStorage.pipe === 'function') {
|
|
111
|
+
targetFilename = filenameOrSource;
|
|
112
|
+
finalStream = streamOrStorage;
|
|
113
|
+
storage = storageOrOptions;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
storage = streamOrStorage;
|
|
117
|
+
const options = storageOrOptions;
|
|
118
|
+
const res = await downloadToStream(filenameOrSource);
|
|
119
|
+
finalStream = res.stream;
|
|
120
|
+
const originalFilename = res.filename || 'attachment';
|
|
121
|
+
if (options?.name) {
|
|
122
|
+
const ext = path.extname(originalFilename);
|
|
123
|
+
const hasExt = path.extname(options.name) !== '';
|
|
124
|
+
targetFilename = hasExt ? options.name : options.name + ext;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
targetFilename = originalFilename;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
104
130
|
const pieceDir = file.replace(/\.[^.]+$/, '');
|
|
105
131
|
const attachDir = path.join(ASSETS_DIRECTORY, pieceDir);
|
|
106
132
|
const exists = await storage.exists(attachDir);
|
|
107
133
|
if (!exists) {
|
|
108
134
|
await storage.makeDirectory(attachDir);
|
|
109
135
|
}
|
|
110
|
-
const { type: detectedType, stream:
|
|
111
|
-
const sourceBasename =
|
|
112
|
-
? path.basename(
|
|
136
|
+
const { type: detectedType, stream: detectedStream } = await detectStreamFileType(finalStream);
|
|
137
|
+
const sourceBasename = targetFilename
|
|
138
|
+
? path.basename(targetFilename, path.extname(targetFilename))
|
|
113
139
|
: 'attachment';
|
|
114
140
|
const sourceExt = detectedType
|
|
115
141
|
? '.' + detectedType.ext
|
|
116
|
-
:
|
|
117
|
-
? path.extname(
|
|
142
|
+
: targetFilename
|
|
143
|
+
? path.extname(targetFilename)
|
|
118
144
|
: '';
|
|
119
145
|
let relPath = path.join(attachDir, sourceBasename + sourceExt);
|
|
120
146
|
let counter = 2;
|
|
@@ -122,7 +148,7 @@ async function savePieceAsset(file, filename, stream, storage) {
|
|
|
122
148
|
relPath = path.join(attachDir, sourceBasename + '-' + counter + sourceExt);
|
|
123
149
|
counter++;
|
|
124
150
|
}
|
|
125
|
-
await pipeline(
|
|
151
|
+
await pipeline(detectedStream, storage.createWriteStream(relPath));
|
|
126
152
|
return relPath;
|
|
127
153
|
}
|
|
128
154
|
async function savePieceFieldAsset(file, field, stream, storage) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"piece.js","sourceRoot":"","sources":["../../../../src/pieces/utils/piece.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat } from 'fs/promises'\nimport { createHash } from 'crypto'\nimport { Readable } from 'stream'\nimport { createReadStream } from 'fs'\nimport { pipeline } from 'stream/promises'\nimport path from 'path'\nimport { fileTypeFromBuffer } from 'file-type'\nimport got from 'got'\nimport { PieceFrontmatterSchemaField, PieceFrontMatterValue } from './frontmatter.js'\nimport LuzzleStorage from '../../storage/abstract.js'\nimport { ASSETS_DIRECTORY } from '../assets.js'\n\ntype AttachableStream = { stream: Readable; filename?: string }\n\nasync function downloadToStream(fileOrUrl: string): Promise<AttachableStream> {\n\tif (/https?:\\/\\//i.test(fileOrUrl)) {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst download = got.stream(fileOrUrl, {\n\t\t\t\tthrowHttpErrors: false,\n\t\t\t\theaders: {\n\t\t\t\t\t'user-agent': 'luzzle/core (https://github.com/eleith/luzzle)',\n\t\t\t\t},\n\t\t\t\tretry: {\n\t\t\t\t\tlimit: 3,\n\t\t\t\t\tmethods: ['GET'],\n\t\t\t\t},\n\t\t\t\ttimeout: {\n\t\t\t\t\trequest: 10000,\n\t\t\t\t},\n\t\t\t})\n\t\t\tdownload.on('error', (err) => {\n\t\t\t\tconsole.error(`Error downloading file from ${fileOrUrl}: ${err.message}`)\n\t\t\t\treject(err)\n\t\t\t})\n\t\t\tdownload.on('response', (response) => {\n\t\t\t\tif (response.statusCode >= 400) {\n\t\t\t\t\tconsole.error(`Error downloading file from ${fileOrUrl}: http ${response.statusCode}`)\n\t\t\t\t\treject(new Error(`HTTP Error: ${response.statusCode}`))\n\t\t\t\t} else {\n\t\t\t\t\tconst filename = path.basename(new URL(fileOrUrl).pathname)\n\t\t\t\t\tresolve({ stream: download, filename })\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n\n\tconst file = fileOrUrl\n\tconst fileStat = await stat(file).catch(() => null)\n\n\tif (fileStat && fileStat.isFile()) {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst stream = createReadStream(file)\n\t\t\tstream.on('error', (err) => {\n\t\t\t\tconsole.error(`Error reading file from path: ${err.message}`)\n\t\t\t\treject(err)\n\t\t\t})\n\t\t\tstream.on('open', () => {\n\t\t\t\tconst filename = path.basename(file)\n\t\t\t\tresolve({ stream, filename })\n\t\t\t})\n\t\t})\n\t}\n\n\tthrow new Error(`${fileOrUrl} is not a valid file`)\n}\n\nfunction calculateHashFromFile(stream: Readable): Promise<string> {\n\tconst hash = createHash('md5')\n\n\treturn new Promise((resolve, reject) => {\n\t\tstream.on('error', (err) => {\n\t\t\tconsole.error(`Error calculating hash from stream: ${err.message}`)\n\t\t\treject(err)\n\t\t})\n\t\tstream.on('data', (data) => hash.update(data))\n\t\tstream.on('end', () => resolve(hash.digest('hex')))\n\t})\n}\n\nasync function detectStreamFileType(stream: Readable, maxBytes = 4100) {\n\tconst iterator = stream[Symbol.asyncIterator]()\n\tconst chunks: Buffer[] = []\n\tlet length = 0\n\tlet done = false\n\n\twhile (length < maxBytes) {\n\t\tconst next = await iterator.next()\n\t\tif (next.done) {\n\t\t\tdone = true\n\t\t\tbreak\n\t\t}\n\t\tconst chunk = Buffer.isBuffer(next.value) ? next.value : Buffer.from(next.value)\n\t\tchunks.push(chunk)\n\t\tlength += chunk.length\n\t}\n\n\tconst buffer = Buffer.concat(chunks)\n\tconst type = await fileTypeFromBuffer(buffer)\n\n\tasync function* gen() {\n\t\tif (length > 0) yield buffer\n\t\tif (done) return\n\n\t\tlet next = await iterator.next()\n\t\twhile (!next.done) {\n\t\t\tyield next.value\n\t\t\tnext = await iterator.next()\n\t\t}\n\t}\n\n\treturn {\n\t\ttype,\n\t\tstream: Readable.from(gen()),\n\t}\n}\n\nasync function savePieceAsset(\n\tfile: string,\n\tfilename: string,\n\tstream: Readable,\n\tstorage: LuzzleStorage\n): Promise<string> {\n\tconst pieceDir = file.replace(/\\.[^.]+$/, '')\n\tconst attachDir = path.join(ASSETS_DIRECTORY, pieceDir)\n\tconst exists = await storage.exists(attachDir)\n\n\tif (!exists) {\n\t\tawait storage.makeDirectory(attachDir)\n\t}\n\n\tconst { type: detectedType, stream: finalStream } = await detectStreamFileType(stream)\n\n\tconst sourceBasename = filename\n\t\t? path.basename(filename, path.extname(filename))\n\t\t: 'attachment'\n\n\tconst sourceExt = detectedType\n\t\t? '.' + detectedType.ext\n\t\t: filename\n\t\t\t? path.extname(filename)\n\t\t\t: ''\n\n\tlet relPath = path.join(attachDir, sourceBasename + sourceExt)\n\tlet counter = 2\n\n\twhile (await storage.exists(relPath)) {\n\t\trelPath = path.join(attachDir, sourceBasename + '-' + counter + sourceExt)\n\t\tcounter++\n\t}\n\n\tawait pipeline(finalStream, storage.createWriteStream(relPath))\n\n\treturn relPath\n}\n\nasync function savePieceFieldAsset(\n\tfile: string,\n\tfield: PieceFrontmatterSchemaField,\n\tstream: AttachableStream,\n\tstorage: LuzzleStorage\n): Promise<string> {\n\tconst format = field.type === 'array' ? field.items.format : field.format\n\n\t/* c8 ignore next 3 */\n\tif (format !== 'asset') {\n\t\tthrow new Error(`${field} is not an attachable field for ${file}`)\n\t}\n\n\tconst filename = stream.filename || field.name\n\treturn savePieceAsset(file, filename, stream.stream, storage)\n}\n\nfunction isAttachableStream(value: unknown): value is AttachableStream {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'stream' in value &&\n\t\ttypeof (value as AttachableStream).stream?.pipe === 'function'\n\t)\n}\n\nasync function makePieceValue(\n\tfield: PieceFrontmatterSchemaField,\n\tvalue: PieceFrontMatterValue | AttachableStream\n): Promise<PieceFrontMatterValue | AttachableStream> {\n\tconst isArray = field.type === 'array'\n\tconst format = isArray ? field.items.format : field.format\n\tconst type = isArray ? field.items.type : field.type\n\n\tif (format === 'asset') {\n\t\tif (typeof value === 'string') {\n\t\t\tif (value.startsWith(ASSETS_DIRECTORY)) {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn downloadToStream(value)\n\t\t} else if (typeof value === 'number' || typeof value === 'boolean' || Array.isArray(value)) {\n\t\t\tthrow new Error(`${field} must be a string or stream`)\n\t\t} else {\n\t\t\treturn value\n\t\t}\n\t} else if (type === 'boolean') {\n\t\treturn /1|true|yes/.test(value as string)\n\t} else if (type === 'integer') {\n\t\treturn parseInt(value as string)\n\t}\n\n\treturn value\n}\n\nexport {\n\tcalculateHashFromFile,\n\tisAttachableStream,\n\tsavePieceFieldAsset,\n\tmakePieceValue,\n\tdetectStreamFileType,\n\tsavePieceAsset,\n\ttype AttachableStream,\n}\n"]}
|
|
1
|
+
{"version":3,"file":"piece.js","sourceRoot":"","sources":["../../../../src/pieces/utils/piece.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat } from 'fs/promises'\nimport { createHash } from 'crypto'\nimport { Readable } from 'stream'\nimport { createReadStream } from 'fs'\nimport { pipeline } from 'stream/promises'\nimport path from 'path'\nimport { fileTypeFromBuffer } from 'file-type'\nimport got from 'got'\nimport { PieceFrontmatterSchemaField, PieceFrontMatterValue } from './frontmatter.js'\nimport LuzzleStorage from '../../storage/abstract.js'\nimport { ASSETS_DIRECTORY } from '../assets.js'\n\ntype AttachableStream = { stream: Readable; filename?: string }\n\nasync function downloadToStream(fileOrUrl: string): Promise<AttachableStream> {\n\tif (/https?:\\/\\//i.test(fileOrUrl)) {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst download = got.stream(fileOrUrl, {\n\t\t\t\tthrowHttpErrors: false,\n\t\t\t\theaders: {\n\t\t\t\t\t'user-agent': 'luzzle/core (https://github.com/eleith/luzzle)',\n\t\t\t\t},\n\t\t\t\tretry: {\n\t\t\t\t\tlimit: 3,\n\t\t\t\t\tmethods: ['GET'],\n\t\t\t\t},\n\t\t\t\ttimeout: {\n\t\t\t\t\trequest: 10000,\n\t\t\t\t},\n\t\t\t})\n\t\t\tdownload.on('error', (err) => {\n\t\t\t\tconsole.error(`Error downloading file from ${fileOrUrl}: ${err.message}`)\n\t\t\t\treject(err)\n\t\t\t})\n\t\t\tdownload.on('response', (response) => {\n\t\t\t\tif (response.statusCode >= 400) {\n\t\t\t\t\tconsole.error(`Error downloading file from ${fileOrUrl}: http ${response.statusCode}`)\n\t\t\t\t\treject(new Error(`HTTP Error: ${response.statusCode}`))\n\t\t\t\t} else {\n\t\t\t\t\tconst filename = path.basename(new URL(fileOrUrl).pathname)\n\t\t\t\t\tresolve({ stream: download, filename })\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n\n\tconst file = fileOrUrl\n\tconst fileStat = await stat(file).catch(() => null)\n\n\tif (fileStat && fileStat.isFile()) {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst stream = createReadStream(file)\n\t\t\tstream.on('error', (err) => {\n\t\t\t\tconsole.error(`Error reading file from path: ${err.message}`)\n\t\t\t\treject(err)\n\t\t\t})\n\t\t\tstream.on('open', () => {\n\t\t\t\tconst filename = path.basename(file)\n\t\t\t\tresolve({ stream, filename })\n\t\t\t})\n\t\t})\n\t}\n\n\tthrow new Error(`${fileOrUrl} is not a valid file`)\n}\n\nfunction calculateHashFromFile(stream: Readable): Promise<string> {\n\tconst hash = createHash('md5')\n\n\treturn new Promise((resolve, reject) => {\n\t\tstream.on('error', (err) => {\n\t\t\tconsole.error(`Error calculating hash from stream: ${err.message}`)\n\t\t\treject(err)\n\t\t})\n\t\tstream.on('data', (data) => hash.update(data))\n\t\tstream.on('end', () => resolve(hash.digest('hex')))\n\t})\n}\n\nasync function detectStreamFileType(stream: Readable, maxBytes = 4100) {\n\tconst iterator = stream[Symbol.asyncIterator]()\n\tconst chunks: Buffer[] = []\n\tlet length = 0\n\tlet done = false\n\n\twhile (length < maxBytes) {\n\t\tconst next = await iterator.next()\n\t\tif (next.done) {\n\t\t\tdone = true\n\t\t\tbreak\n\t\t}\n\t\tconst chunk = Buffer.isBuffer(next.value) ? next.value : Buffer.from(next.value)\n\t\tchunks.push(chunk)\n\t\tlength += chunk.length\n\t}\n\n\tconst buffer = Buffer.concat(chunks)\n\tconst type = await fileTypeFromBuffer(buffer)\n\n\tasync function* gen() {\n\t\tif (length > 0) yield buffer\n\t\tif (done) return\n\n\t\tlet next = await iterator.next()\n\t\twhile (!next.done) {\n\t\t\tyield next.value\n\t\t\tnext = await iterator.next()\n\t\t}\n\t}\n\n\treturn {\n\t\ttype,\n\t\tstream: Readable.from(gen()),\n\t}\n}\n\nasync function savePieceAsset(\n\tfile: string,\n\tfilename: string,\n\tstream: Readable,\n\tstorage: LuzzleStorage\n): Promise<string>\nasync function savePieceAsset(\n\tfile: string,\n\tsource: string,\n\tstorage: LuzzleStorage,\n\toptions?: { name?: string }\n): Promise<string>\nasync function savePieceAsset(\n\tfile: string,\n\tfilenameOrSource: string,\n\tstreamOrStorage: Readable | LuzzleStorage,\n\tstorageOrOptions?: LuzzleStorage | { name?: string }\n): Promise<string> {\n\tlet finalStream: Readable\n\tlet targetFilename: string\n\tlet storage: LuzzleStorage\n\n\tif (\n\t\tstreamOrStorage &&\n\t\ttypeof streamOrStorage === 'object' &&\n\t\t'pipe' in streamOrStorage &&\n\t\ttypeof (streamOrStorage as unknown as Readable).pipe === 'function'\n\t) {\n\t\ttargetFilename = filenameOrSource\n\t\tfinalStream = streamOrStorage as Readable\n\t\tstorage = storageOrOptions as LuzzleStorage\n\t} else {\n\t\tstorage = streamOrStorage as LuzzleStorage\n\t\tconst options = storageOrOptions as { name?: string } | undefined\n\t\tconst res = await downloadToStream(filenameOrSource)\n\t\tfinalStream = res.stream\n\t\tconst originalFilename = res.filename || 'attachment'\n\t\tif (options?.name) {\n\t\t\tconst ext = path.extname(originalFilename)\n\t\t\tconst hasExt = path.extname(options.name) !== ''\n\t\t\ttargetFilename = hasExt ? options.name : options.name + ext\n\t\t} else {\n\t\t\ttargetFilename = originalFilename\n\t\t}\n\t}\n\n\tconst pieceDir = file.replace(/\\.[^.]+$/, '')\n\tconst attachDir = path.join(ASSETS_DIRECTORY, pieceDir)\n\tconst exists = await storage.exists(attachDir)\n\n\tif (!exists) {\n\t\tawait storage.makeDirectory(attachDir)\n\t}\n\n\tconst { type: detectedType, stream: detectedStream } = await detectStreamFileType(finalStream)\n\n\tconst sourceBasename = targetFilename\n\t\t? path.basename(targetFilename, path.extname(targetFilename))\n\t\t: 'attachment'\n\n\tconst sourceExt = detectedType\n\t\t? '.' + detectedType.ext\n\t\t: targetFilename\n\t\t\t? path.extname(targetFilename)\n\t\t\t: ''\n\n\tlet relPath = path.join(attachDir, sourceBasename + sourceExt)\n\tlet counter = 2\n\n\twhile (await storage.exists(relPath)) {\n\t\trelPath = path.join(attachDir, sourceBasename + '-' + counter + sourceExt)\n\t\tcounter++\n\t}\n\n\tawait pipeline(detectedStream, storage.createWriteStream(relPath))\n\n\treturn relPath\n}\n\nasync function savePieceFieldAsset(\n\tfile: string,\n\tfield: PieceFrontmatterSchemaField,\n\tstream: AttachableStream,\n\tstorage: LuzzleStorage\n): Promise<string> {\n\tconst format = field.type === 'array' ? field.items.format : field.format\n\n\t/* c8 ignore next 3 */\n\tif (format !== 'asset') {\n\t\tthrow new Error(`${field} is not an attachable field for ${file}`)\n\t}\n\n\tconst filename = stream.filename || field.name\n\treturn savePieceAsset(file, filename, stream.stream, storage)\n}\n\nfunction isAttachableStream(value: unknown): value is AttachableStream {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'stream' in value &&\n\t\ttypeof (value as AttachableStream).stream?.pipe === 'function'\n\t)\n}\n\nasync function makePieceValue(\n\tfield: PieceFrontmatterSchemaField,\n\tvalue: PieceFrontMatterValue | AttachableStream\n): Promise<PieceFrontMatterValue | AttachableStream> {\n\tconst isArray = field.type === 'array'\n\tconst format = isArray ? field.items.format : field.format\n\tconst type = isArray ? field.items.type : field.type\n\n\tif (format === 'asset') {\n\t\tif (typeof value === 'string') {\n\t\t\tif (value.startsWith(ASSETS_DIRECTORY)) {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn downloadToStream(value)\n\t\t} else if (typeof value === 'number' || typeof value === 'boolean' || Array.isArray(value)) {\n\t\t\tthrow new Error(`${field} must be a string or stream`)\n\t\t} else {\n\t\t\treturn value\n\t\t}\n\t} else if (type === 'boolean') {\n\t\treturn /1|true|yes/.test(value as string)\n\t} else if (type === 'integer') {\n\t\treturn parseInt(value as string)\n\t}\n\n\treturn value\n}\n\nexport {\n\tcalculateHashFromFile,\n\tisAttachableStream,\n\tsavePieceFieldAsset,\n\tmakePieceValue,\n\tdetectStreamFileType,\n\tsavePieceAsset,\n\ttype AttachableStream,\n}\n"]}
|