tar-vern 0.1.0 → 0.2.0

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/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * name: tar-vern
3
- * version: 0.1.0
3
+ * version: 0.2.0
4
4
  * description: Tape archiver library for Typescript
5
5
  * author: Kouji Matsui (@kekyo@mi.kekyo.net)
6
6
  * license: MIT
@@ -10,6 +10,196 @@ import { Readable } from "stream";
10
10
  import { createGzip } from "zlib";
11
11
  import { createReadStream, createWriteStream } from "fs";
12
12
  import { stat } from "fs/promises";
13
+ const getUName = (candidateName, candidateId, reflectStat) => {
14
+ return candidateName ?? (reflectStat === "all" ? candidateId.toString() : "root");
15
+ };
16
+ const getBuffer = (data) => {
17
+ return Buffer.isBuffer(data) ? data : Buffer.from(data, "utf8");
18
+ };
19
+ const createDirectoryItem = async (path, reflectStat, options) => {
20
+ const rs = reflectStat ?? "none";
21
+ if (rs !== "none" && options?.directoryPath) {
22
+ const stats = await stat(options.directoryPath);
23
+ const mode = options?.mode ?? stats.mode;
24
+ const uid = options?.uid ?? stats.uid;
25
+ const gid = options?.gid ?? stats.gid;
26
+ const date = options?.date ?? stats.mtime;
27
+ const uname = getUName(options?.uname, stats.uid, rs);
28
+ const gname = getUName(options?.gname, stats.gid, rs);
29
+ return {
30
+ kind: "directory",
31
+ path,
32
+ mode,
33
+ uname,
34
+ gname,
35
+ uid,
36
+ gid,
37
+ date
38
+ };
39
+ } else {
40
+ const mode = options?.mode ?? 493;
41
+ const uid = options?.uid ?? 0;
42
+ const gid = options?.gid ?? 0;
43
+ const date = options?.date ?? /* @__PURE__ */ new Date();
44
+ const uname = getUName(options?.uname, void 0, rs);
45
+ const gname = getUName(options?.gname, void 0, rs);
46
+ return {
47
+ kind: "directory",
48
+ path,
49
+ mode,
50
+ uname,
51
+ gname,
52
+ uid,
53
+ gid,
54
+ date
55
+ };
56
+ }
57
+ };
58
+ const createFileItem = async (path, content, options) => {
59
+ const mode = options?.mode ?? 420;
60
+ const uid = options?.uid ?? 0;
61
+ const gid = options?.gid ?? 0;
62
+ const date = options?.date ?? /* @__PURE__ */ new Date();
63
+ const uname = options?.uname ?? "root";
64
+ const gname = options?.gname ?? "root";
65
+ return {
66
+ kind: "file",
67
+ path,
68
+ mode,
69
+ uname,
70
+ gname,
71
+ uid,
72
+ gid,
73
+ date,
74
+ content
75
+ };
76
+ };
77
+ const createReadableFileItem = async (path, readable, options) => {
78
+ const mode = options?.mode ?? 420;
79
+ const uid = options?.uid ?? 0;
80
+ const gid = options?.gid ?? 0;
81
+ const date = options?.date ?? /* @__PURE__ */ new Date();
82
+ const uname = options?.uname ?? "root";
83
+ const gname = options?.gname ?? "root";
84
+ let length = options?.length;
85
+ if (!length) {
86
+ const chunks = [];
87
+ length = 0;
88
+ for await (const chunk of readable) {
89
+ const buffer = getBuffer(chunk);
90
+ chunks.push(buffer);
91
+ length += buffer.length;
92
+ }
93
+ return {
94
+ kind: "file",
95
+ path,
96
+ mode,
97
+ uname,
98
+ gname,
99
+ uid,
100
+ gid,
101
+ date,
102
+ content: {
103
+ kind: "readable",
104
+ length,
105
+ readable: Readable.from(chunks)
106
+ }
107
+ };
108
+ } else {
109
+ return {
110
+ kind: "file",
111
+ path,
112
+ mode,
113
+ uname,
114
+ gname,
115
+ uid,
116
+ gid,
117
+ date,
118
+ content: {
119
+ kind: "readable",
120
+ length,
121
+ readable
122
+ }
123
+ };
124
+ }
125
+ };
126
+ const createGeneratorFileItem = async (path, generator, options) => {
127
+ const mode = options?.mode ?? 420;
128
+ const uid = options?.uid ?? 0;
129
+ const gid = options?.gid ?? 0;
130
+ const date = options?.date ?? /* @__PURE__ */ new Date();
131
+ const uname = options?.uname ?? "root";
132
+ const gname = options?.gname ?? "root";
133
+ let length = options?.length;
134
+ if (!length) {
135
+ const chunks = [];
136
+ length = 0;
137
+ for await (const chunk of generator) {
138
+ const buffer = getBuffer(chunk);
139
+ chunks.push(buffer);
140
+ length += buffer.length;
141
+ }
142
+ return {
143
+ kind: "file",
144
+ path,
145
+ mode,
146
+ uname,
147
+ gname,
148
+ uid,
149
+ gid,
150
+ date,
151
+ content: {
152
+ kind: "readable",
153
+ length,
154
+ readable: Readable.from(chunks)
155
+ }
156
+ };
157
+ } else {
158
+ return {
159
+ kind: "file",
160
+ path,
161
+ mode,
162
+ uname,
163
+ gname,
164
+ uid,
165
+ gid,
166
+ date,
167
+ content: {
168
+ kind: "generator",
169
+ length,
170
+ generator
171
+ }
172
+ };
173
+ }
174
+ };
175
+ const createReadFileItem = async (path, filePath, reflectStat, options) => {
176
+ const rs = reflectStat ?? "exceptName";
177
+ const stats = await stat(filePath);
178
+ const reader = createReadStream(filePath);
179
+ const mode = options?.mode ?? (rs !== "none" ? stats.mode : void 0);
180
+ const uid = options?.uid ?? (rs !== "none" ? stats.uid : void 0);
181
+ const gid = options?.gid ?? (rs !== "none" ? stats.gid : void 0);
182
+ const date = options?.date ?? (rs !== "none" ? stats.mtime : void 0);
183
+ const uname = getUName(options?.uname, stats.uid, rs);
184
+ const gname = getUName(options?.gname, stats.gid, rs);
185
+ return await createReadableFileItem(path, reader, {
186
+ length: stats.size,
187
+ mode,
188
+ uname,
189
+ gname,
190
+ uid,
191
+ gid,
192
+ date
193
+ });
194
+ };
195
+ const storeReaderToFile = (reader, path) => {
196
+ const writer = createWriteStream(path);
197
+ reader.pipe(writer);
198
+ return new Promise((res, rej) => {
199
+ writer.on("finish", res);
200
+ writer.on("error", rej);
201
+ });
202
+ };
13
203
  const utf8ByteLength = (str) => {
14
204
  return Buffer.byteLength(str, "utf8");
15
205
  };
@@ -91,8 +281,8 @@ const createTarPacker = (entryItemGenerator, compressionType, signal) => {
91
281
  // Entry is a file
92
282
  case "file": {
93
283
  const entryItemContent = entryItem.content;
94
- if (typeof entryItemContent === "string") {
95
- const contentBytes = Buffer.from(entryItemContent, "utf8");
284
+ if (typeof entryItemContent === "string" || Buffer.isBuffer(entryItemContent)) {
285
+ const contentBytes = getBuffer(entryItemContent);
96
286
  const tarHeaderBytes = createTarHeader(
97
287
  "file",
98
288
  entryItem.path,
@@ -105,23 +295,8 @@ const createTarPacker = (entryItemGenerator, compressionType, signal) => {
105
295
  entryItem.date
106
296
  );
107
297
  yield tarHeaderBytes;
108
- const paddedContentBytes = getPaddedBytes(contentBytes);
109
- yield paddedContentBytes;
110
- } else if (Buffer.isBuffer(entryItemContent)) {
111
- const tarHeaderBytes = createTarHeader(
112
- "file",
113
- entryItem.path,
114
- entryItemContent.length,
115
- entryItem.mode,
116
- entryItem.uname,
117
- entryItem.gname,
118
- entryItem.uid,
119
- entryItem.gid,
120
- entryItem.date
121
- );
122
- yield tarHeaderBytes;
123
- const paddedContentBytes = getPaddedBytes(entryItemContent);
124
- yield paddedContentBytes;
298
+ const totalPaddedContentBytes = getPaddedBytes(contentBytes);
299
+ yield totalPaddedContentBytes;
125
300
  } else {
126
301
  const tarHeaderBytes = createTarHeader(
127
302
  "file",
@@ -135,42 +310,32 @@ const createTarPacker = (entryItemGenerator, compressionType, signal) => {
135
310
  entryItem.date
136
311
  );
137
312
  yield tarHeaderBytes;
313
+ let position = 0;
138
314
  switch (entryItemContent.kind) {
139
315
  // Content is a generator
140
316
  case "generator": {
141
- let position = 0;
142
- for await (const contentFragmentBytes of entryItemContent.generator) {
317
+ for await (const contentBytes of entryItemContent.generator) {
143
318
  signal?.throwIfAborted();
144
- yield contentFragmentBytes;
145
- position += contentFragmentBytes.length;
146
- }
147
- if (position % 512 !== 0) {
148
- signal?.throwIfAborted();
149
- yield Buffer.alloc(512 - position % 512, 0);
319
+ yield contentBytes;
320
+ position += contentBytes.length;
150
321
  }
151
322
  break;
152
323
  }
153
324
  // Content is a readable stream
154
325
  case "readable": {
155
- let position = 0;
156
326
  for await (const content of entryItemContent.readable) {
157
327
  signal?.throwIfAborted();
158
- if (typeof content === "string") {
159
- const stringBytes = Buffer.from(content, "utf8");
160
- yield stringBytes;
161
- position += stringBytes.length;
162
- } else if (Buffer.isBuffer(content)) {
163
- yield content;
164
- position += content.length;
165
- }
166
- }
167
- if (position % 512 !== 0) {
168
- signal?.throwIfAborted();
169
- yield Buffer.alloc(512 - position % 512, 0);
328
+ const contentBytes = getBuffer(content);
329
+ yield contentBytes;
330
+ position += contentBytes.length;
170
331
  }
171
332
  break;
172
333
  }
173
334
  }
335
+ if (position % 512 !== 0) {
336
+ signal?.throwIfAborted();
337
+ yield Buffer.alloc(512 - position % 512, 0);
338
+ }
174
339
  }
175
340
  break;
176
341
  }
@@ -209,116 +374,14 @@ const createTarPacker = (entryItemGenerator, compressionType, signal) => {
209
374
  }
210
375
  }
211
376
  };
212
- const getUName = (candidateName, candidateId, reflectStat) => {
213
- return candidateName ?? (reflectStat === "all" ? candidateId.toString() : "root");
214
- };
215
- const createDirectoryItem = async (path, reflectStat, options) => {
216
- const rs = reflectStat ?? "none";
217
- if (rs !== "none" && options?.directoryPath) {
218
- const stats = await stat(options.directoryPath);
219
- const mode = options?.mode ?? stats.mode;
220
- const uid = options?.uid ?? stats.uid;
221
- const gid = options?.gid ?? stats.gid;
222
- const date = options?.date ?? stats.mtime;
223
- const uname = getUName(options?.uname, stats.uid, rs);
224
- const gname = getUName(options?.gname, stats.gid, rs);
225
- return {
226
- kind: "directory",
227
- path,
228
- mode,
229
- uname,
230
- gname,
231
- uid,
232
- gid,
233
- date
234
- };
235
- } else {
236
- const mode = options?.mode ?? 493;
237
- const uid = options?.uid ?? 0;
238
- const gid = options?.gid ?? 0;
239
- const date = options?.date ?? /* @__PURE__ */ new Date();
240
- const uname = getUName(options?.uname, void 0, rs);
241
- const gname = getUName(options?.gname, void 0, rs);
242
- return {
243
- kind: "directory",
244
- path,
245
- mode,
246
- uname,
247
- gname,
248
- uid,
249
- gid,
250
- date
251
- };
252
- }
253
- };
254
- const createReadableItem = async (path, reader, options) => {
255
- let readable = reader;
256
- let length = options?.length;
257
- if (!length) {
258
- const chunks = [];
259
- length = 0;
260
- for await (const chunk of reader) {
261
- const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
262
- chunks.push(buffer);
263
- length += buffer.length;
264
- }
265
- readable = Readable.from(chunks);
266
- }
267
- const mode = options?.mode ?? 420;
268
- const uid = options?.uid ?? 0;
269
- const gid = options?.gid ?? 0;
270
- const date = options?.date ?? /* @__PURE__ */ new Date();
271
- const uname = options?.uname ?? "root";
272
- const gname = options?.gname ?? "root";
273
- return {
274
- kind: "file",
275
- path,
276
- mode,
277
- uname,
278
- gname,
279
- uid,
280
- gid,
281
- date,
282
- content: {
283
- kind: "readable",
284
- length,
285
- readable
286
- }
287
- };
288
- };
289
- const createReadFileItem = async (path, filePath, reflectStat, options) => {
290
- const rs = reflectStat ?? "exceptName";
291
- const stats = await stat(filePath);
292
- const reader = createReadStream(filePath);
293
- const mode = options?.mode ?? (rs !== "none" ? stats.mode : void 0);
294
- const uid = options?.uid ?? (rs !== "none" ? stats.uid : void 0);
295
- const gid = options?.gid ?? (rs !== "none" ? stats.gid : void 0);
296
- const date = options?.date ?? (rs !== "none" ? stats.mtime : void 0);
297
- const uname = getUName(options?.uname, stats.uid, rs);
298
- const gname = getUName(options?.gname, stats.gid, rs);
299
- return await createReadableItem(path, reader, {
300
- length: stats.size,
301
- mode,
302
- uname,
303
- gname,
304
- uid,
305
- gid,
306
- date
307
- });
308
- };
309
- const storeReaderToFile = (reader, path) => {
310
- const writer = createWriteStream(path);
311
- reader.pipe(writer);
312
- return new Promise((res, rej) => {
313
- writer.on("finish", res);
314
- writer.on("error", rej);
315
- });
316
- };
317
377
  export {
318
378
  createDirectoryItem,
379
+ createFileItem,
380
+ createGeneratorFileItem,
319
381
  createReadFileItem,
320
- createReadableItem,
382
+ createReadableFileItem,
321
383
  createTarPacker,
384
+ getBuffer,
322
385
  storeReaderToFile
323
386
  };
324
387
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/packer.ts","../src/utils.ts"],"sourcesContent":["// tar-vern - Tape archiver library for Typescript\n// Copyright (c) Kouji Matsui (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/tar-vern/\n\nimport { Readable } from \"stream\";\nimport { CompressionTypes, EntryItem } from \"./types\";\nimport { createGzip } from \"zlib\";\n\n/**\n * Get the byte length of a string in UTF-8\n * @param str - The string to get the byte length of\n * @returns The byte length of the string\n */\nconst utf8ByteLength = (str: string) => {\n return Buffer.byteLength(str, \"utf8\");\n}\n\n/**\n * Truncate a string to a maximum byte length in UTF-8\n * @param str - The string to truncate\n * @param maxBytes - The maximum byte length\n * @returns The truncated string\n */\nconst truncateUtf8Safe = (str: string, maxBytes: number) => {\n let total = 0;\n let i = 0;\n while (i < str.length) {\n const codePoint = str.codePointAt(i)!;\n const char = String.fromCodePoint(codePoint);\n const charBytes = Buffer.byteLength(char, \"utf8\");\n if (total + charBytes > maxBytes) break;\n total += charBytes;\n i += char.length;\n }\n return str.slice(0, i);\n}\n\n// Tar specification: name max 100 bytes, prefix max 155 bytes\nconst MAX_NAME = 100;\nconst MAX_PREFIX = 155;\n\n/**\n * Split a path into a name and a prefix\n * @param path - The path to split\n * @returns The name and prefix\n */\nconst splitPath = (path: string) => {\n if (utf8ByteLength(path) <= MAX_NAME) {\n return { prefix: \"\", name: path };\n }\n\n // Split by '/' and find the part that fits in name from the end\n const parts = path.split(\"/\");\n let name = parts.pop() ?? \"\";\n let prefix = parts.join(\"/\");\n\n // Truncate if name exceeds 100 bytes\n if (utf8ByteLength(name) > MAX_NAME) {\n name = truncateUtf8Safe(name, MAX_NAME);\n }\n\n // Truncate if prefix exceeds 155 bytes\n while (utf8ByteLength(prefix) > MAX_PREFIX) {\n prefix = truncateUtf8Safe(prefix, MAX_PREFIX);\n }\n\n return { prefix, name };\n}\n\n///////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Get octal bytes from a number\n * @param value - The number to get octal bytes from\n * @param length - The length of the octal bytes\n * @returns The octal bytes\n */\nconst getOctalBytes = (value: number, length: number) => {\n const str = value.toString(8).padStart(length - 1, \"0\") + \"\\0\";\n return Buffer.from(str, \"ascii\");\n};\n\n/**\n * Get padded bytes from a buffer\n * @param buffer - The buffer to get padded bytes from\n * @returns The padded bytes\n */\nconst getPaddedBytes = (buffer: Buffer) => {\n const extra = buffer.length % 512;\n if (extra === 0) {\n return buffer;\n } else {\n return Buffer.concat([buffer, Buffer.alloc(512 - extra, 0)]);\n }\n}\n\n/**\n * The terminator bytes\n */\nconst terminatorBytes = Buffer.alloc(1024, 0);\n\n/**\n * Create a tar header\n * @param type - The type of the entry\n * @param path - The path of the entry\n * @param size - The size of the entry\n * @param mode - The mode of the entry\n * @param uname - The user name of the entry\n * @param gname - The group name of the entry\n */\nconst createTarHeader = (\n type: 'file' | 'directory',\n path: string,\n size: number,\n mode: number,\n uname: string,\n gname: string,\n uid: number,\n gid: number,\n date: Date\n) => {\n // Allocate header bytes\n const buffer = Buffer.alloc(512, 0);\n\n // Split path into name and prefix\n const { name, prefix } = splitPath(path);\n\n // Write name, mode, uid, gid, size, mtime, typeflag, prefix, checksum\n buffer.write(name, 0, 100, \"utf8\");\n getOctalBytes(mode & 0o7777, 8).copy(buffer, 100);\n getOctalBytes(uid, 8).copy(buffer, 108);\n getOctalBytes(gid, 8).copy(buffer, 116);\n getOctalBytes(size, 12).copy(buffer, 124);\n getOctalBytes(Math.floor(date.getTime() / 1000), 12).copy(buffer, 136);\n\n // Check sum space\n Buffer.from(\" \", \"ascii\").copy(buffer, 148);\n\n if (type === 'file') {\n buffer.write(\"0\", 156, 1, \"ascii\"); // typeflag (file)\n } else {\n buffer.write(\"5\", 156, 1, \"ascii\"); // typeflag (directory)\n }\n buffer.write(\"ustar\\0\", 257, 6, \"ascii\");\n buffer.write(\"00\", 263, 2, \"ascii\"); // version\n buffer.write(uname, 265, 32, \"utf8\");\n buffer.write(gname, 297, 32, \"utf8\");\n buffer.write(prefix, 345, 155, \"utf8\"); // Path prefix\n\n // Calculate check sum\n let sum = 0;\n for (let i = 0; i < 512; i++) {\n sum += buffer[i];\n }\n getOctalBytes(sum, 8).copy(buffer, 148);\n\n return buffer;\n}\n\n///////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Create a tar packer\n * @param entryItemGenerator - The async generator of the entry items\n * @param compressionType - The compression type to use (Default: 'none')\n * @param signal - The abort signal to cancel the tar packer\n * @returns Readable stream of the tar packer\n */\nexport const createTarPacker = (\n entryItemGenerator: AsyncGenerator<EntryItem, void, unknown>,\n compressionType?: CompressionTypes,\n signal?: AbortSignal) => {\n\n // Create async generator function from entry item iterator\n const entryItemIterator = async function*() {\n // Iterate over the entry items\n for await (const entryItem of entryItemGenerator) {\n signal?.throwIfAborted();\n\n switch (entryItem.kind) {\n // Entry is a file\n case 'file': {\n const entryItemContent = entryItem.content;\n // Content is a string\n if (typeof entryItemContent === 'string') {\n // Get content bytes from string\n const contentBytes = Buffer.from(entryItemContent, \"utf8\");\n\n // Create and produce tar header bytes\n const tarHeaderBytes = createTarHeader(\n 'file',\n entryItem.path,\n contentBytes.length,\n entryItem.mode,\n entryItem.uname,\n entryItem.gname,\n entryItem.uid,\n entryItem.gid,\n entryItem.date);\n yield tarHeaderBytes;\n\n // Content bytes to adjust padding space and produce\n const paddedContentBytes = getPaddedBytes(contentBytes);\n yield paddedContentBytes;\n\n // Content is a buffer\n } else if (Buffer.isBuffer(entryItemContent)) {\n // Create and produce tar header bytes\n const tarHeaderBytes = createTarHeader(\n 'file',\n entryItem.path,\n entryItemContent.length,\n entryItem.mode,\n entryItem.uname,\n entryItem.gname,\n entryItem.uid,\n entryItem.gid,\n entryItem.date);\n yield tarHeaderBytes;\n\n // Content bytes to adjust padding space and produce\n const paddedContentBytes = getPaddedBytes(entryItemContent);\n yield paddedContentBytes;\n\n } else {\n // Create and produce tar header bytes\n const tarHeaderBytes = createTarHeader(\n 'file',\n entryItem.path,\n entryItemContent.length,\n entryItem.mode,\n entryItem.uname,\n entryItem.gname,\n entryItem.uid,\n entryItem.gid,\n entryItem.date);\n yield tarHeaderBytes;\n\n switch (entryItemContent.kind) {\n // Content is a generator\n case 'generator': {\n let position = 0;\n for await (const contentFragmentBytes of entryItemContent.generator) {\n signal?.throwIfAborted();\n yield contentFragmentBytes;\n position += contentFragmentBytes.length;\n }\n\n // Padding space\n if (position % 512 !== 0) {\n signal?.throwIfAborted();\n yield Buffer.alloc(512 - (position % 512), 0);\n }\n break;\n }\n // Content is a readable stream\n case 'readable': {\n let position = 0;\n for await (const content of entryItemContent.readable) {\n signal?.throwIfAborted();\n if (typeof content === 'string') {\n const stringBytes = Buffer.from(content, \"utf8\");\n yield stringBytes;\n position += stringBytes.length;\n } else if (Buffer.isBuffer(content)) {\n yield content;\n position += content.length;\n }\n }\n\n // Padding space\n if (position % 512 !== 0) {\n signal?.throwIfAborted();\n yield Buffer.alloc(512 - (position % 512), 0);\n }\n break;\n }\n }\n }\n break;\n }\n // Entry is a directory\n case 'directory': {\n // Create and produce tar header bytes\n const tarHeaderBytes = createTarHeader(\n 'directory',\n entryItem.path,\n 0,\n entryItem.mode,\n entryItem.uname,\n entryItem.gname,\n entryItem.uid,\n entryItem.gid,\n entryItem.date\n );\n yield tarHeaderBytes;\n break;\n }\n }\n }\n\n // Terminates for tar stream\n yield terminatorBytes;\n };\n\n const ct = compressionType ?? 'none';\n\n switch (ct) {\n // No compression\n case 'none': {\n // Create readable stream from entry item iterator\n return Readable.from(entryItemIterator());\n }\n // Gzip compression\n case 'gzip': {\n // Create gzip stream\n const gzipStream = createGzip({ level: 9 });\n // Create readable stream from entry item iterator\n const entryItemStream = Readable.from(entryItemIterator());\n // Pipe the entry item stream to the gzip stream\n entryItemStream.pipe(gzipStream);\n // Return the gzip stream\n return gzipStream;\n }\n }\n};\n","// tar-vern - Tape archiver library for Typescript\n// Copyright (c) Kouji Matsui (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/tar-vern/\n\nimport { createReadStream, createWriteStream } from \"fs\";\nimport { stat } from \"fs/promises\";\nimport { Readable } from \"stream\";\nimport { CreateItemOptions, CreateReadableItemOptions, FileItem, DirectoryItem, ReflectStats, CreateDirectoryItemOptions } from \"./types\";\n\n/**\n * Get the user/group name from the candidate name or ID\n * @param candidateName - The candidate user/group name\n * @param candidateId - The candidate user/group ID\n * @param reflectStat - Whether to reflect the stat (all, exceptName, none)\n * @returns The user/group name\n */\nconst getUName = (candidateName: string | undefined, candidateId: number, reflectStat: ReflectStats | undefined) => {\n return candidateName ?? (reflectStat === 'all' ? candidateId.toString() : 'root');\n}\n\n/**\n * Create a DirectoryItem\n * @param path - The path to the directory in the tar archive\n * @param reflectStat - Whether to reflect optional stat of the file (mode, uid, gid, mtime. Default: 'none')\n * @param options - Metadata for the directory including path in tar archive\n * @returns A DirectoryItem\n * @remarks When reflectStat is 'all' or 'exceptName', `options.directoryPath` must be provided.\n */\nexport const createDirectoryItem = async (\n path: string,\n reflectStat?: ReflectStats,\n options?: CreateDirectoryItemOptions\n): Promise<DirectoryItem> => {\n const rs = reflectStat ?? 'none';\n\n if (rs !== 'none' && options?.directoryPath) {\n const stats = await stat(options.directoryPath);\n const mode = options?.mode ?? stats.mode;\n const uid = options?.uid ?? stats.uid;\n const gid = options?.gid ?? stats.gid;\n const date = options?.date ?? stats.mtime;\n const uname = getUName(options?.uname, stats.uid, rs);\n const gname = getUName(options?.gname, stats.gid, rs);\n return {\n kind: 'directory',\n path, mode, uname, gname, uid, gid, date,\n };\n } else {\n const mode = options?.mode ?? 0o755;\n const uid = options?.uid ?? 0;\n const gid = options?.gid ?? 0;\n const date = options?.date ?? new Date();\n const uname = getUName(options?.uname, undefined, rs);\n const gname = getUName(options?.gname, undefined, rs);\n return {\n kind: 'directory',\n path, mode, uname, gname, uid, gid, date,\n };\n }\n};\n\n/**\n * Create a FileItem from a Readable stream\n * @param path - The path to the file in the tar archive\n * @param reader - The readable stream\n * @param options - Metadata for the file including path in tar archive\n * @returns A FileItem\n */\nexport const createReadableItem = async (\n path: string,\n reader: Readable,\n options?: CreateReadableItemOptions\n): Promise<FileItem> => {\n let readable = reader;\n\n // When length is not provided, calculate the total size by reading all chunks\n let length = options?.length;\n if (!length) {\n // Calculate the total size by reading all chunks\n const chunks: Buffer[] = [];\n length = 0;\n\n // Collect all chunks to calculate size\n for await (const chunk of reader) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, 'utf8');\n chunks.push(buffer);\n length += buffer.length;\n }\n\n // Create a new readable stream from the collected chunks\n readable = Readable.from(chunks);\n }\n\n const mode = options?.mode ?? 0o644;\n const uid = options?.uid ?? 0;\n const gid = options?.gid ?? 0;\n const date = options?.date ?? new Date();\n\n const uname = options?.uname ?? 'root';\n const gname = options?.gname ?? 'root';\n\n // Create a FileItem\n return {\n kind: 'file',\n path, mode, uname, gname, uid, gid, date,\n content: {\n kind: 'readable',\n length: length,\n readable: readable\n }\n };\n};\n\n/**\n * Create a FileItem from a local file path\n * @param path - The path to the file in the tar archive\n * @param filePath - The path to the file to read from real filesystem\n * @param reflectStat - Whether to reflect optional stat of the file (mode, uid, gid, mtime. Default: 'exceptName')\n * @param options - Metadata for the file including path in tar archive\n * @returns A FileItem\n */\nexport const createReadFileItem = async (\n path: string,\n filePath: string,\n reflectStat?: ReflectStats,\n options?: CreateItemOptions\n): Promise<FileItem> => {\n const rs = reflectStat ?? 'exceptName';\n\n // Get file stats to extract metadata\n const stats = await stat(filePath);\n // Create readable stream from file\n const reader = createReadStream(filePath);\n\n const mode = options?.mode ?? (rs !== 'none' ? stats.mode : undefined);\n const uid = options?.uid ?? (rs !== 'none' ? stats.uid : undefined);\n const gid = options?.gid ?? (rs !== 'none' ? stats.gid : undefined);\n const date = options?.date ?? (rs !== 'none' ? stats.mtime : undefined);\n\n const uname = getUName(options?.uname, stats.uid, rs);\n const gname = getUName(options?.gname, stats.gid, rs);\n\n // Create a FileItem\n return await createReadableItem(path, reader, {\n length: stats.size, mode, uname, gname, uid, gid, date,\n });\n};\n\n/**\n * Store a readable stream to a file\n * @param reader - The readable stream\n * @param path - The path to the file to store the readable stream to\n * @returns A promise that resolves when the stream is finished\n */\nexport const storeReaderToFile = (reader: Readable, path: string) => {\n const writer = createWriteStream(path);\n reader.pipe(writer);\n return new Promise<void>((res, rej) => {\n writer.on('finish', res);\n writer.on('error', rej);\n });\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/utils.ts","../src/packer.ts"],"sourcesContent":["// tar-vern - Tape archiver library for Typescript\n// Copyright (c) Kouji Matsui (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/tar-vern/\n\nimport { createReadStream, createWriteStream } from \"fs\";\nimport { stat } from \"fs/promises\";\nimport { Readable } from \"stream\";\nimport { CreateItemOptions, CreateReadableFileItemOptions, FileItem, DirectoryItem, ReflectStats, CreateDirectoryItemOptions } from \"./types\";\n\n/**\n * Get the user/group name from the candidate name or ID\n * @param candidateName - The candidate user/group name\n * @param candidateId - The candidate user/group ID\n * @param reflectStat - Whether to reflect the stat (all, exceptName, none)\n * @returns The user/group name\n */\nconst getUName = (candidateName: string | undefined, candidateId: number, reflectStat: ReflectStats | undefined) => {\n return candidateName ?? (reflectStat === 'all' ? candidateId.toString() : 'root');\n}\n\n/**\n * Get a buffer from the string or Buffer\n * @param data - The data to get a buffer from\n * @returns A buffer\n */\nexport const getBuffer = (data: Buffer | string) => {\n return Buffer.isBuffer(data) ? data : Buffer.from(data, 'utf8');\n}\n\n/**\n * Create a DirectoryItem\n * @param path - The path to the directory in the tar archive\n * @param reflectStat - Whether to reflect optional stat of the file (mode, uid, gid, mtime. Default: 'none')\n * @param options - Metadata for the directory including path in tar archive\n * @returns A DirectoryItem\n * @remarks When reflectStat is 'all' or 'exceptName', `options.directoryPath` must be provided.\n */\nexport const createDirectoryItem = async (\n path: string,\n reflectStat?: ReflectStats,\n options?: CreateDirectoryItemOptions\n): Promise<DirectoryItem> => {\n const rs = reflectStat ?? 'none';\n\n if (rs !== 'none' && options?.directoryPath) {\n const stats = await stat(options.directoryPath);\n const mode = options?.mode ?? stats.mode;\n const uid = options?.uid ?? stats.uid;\n const gid = options?.gid ?? stats.gid;\n const date = options?.date ?? stats.mtime;\n const uname = getUName(options?.uname, stats.uid, rs);\n const gname = getUName(options?.gname, stats.gid, rs);\n return {\n kind: 'directory',\n path, mode, uname, gname, uid, gid, date,\n };\n } else {\n const mode = options?.mode ?? 0o755;\n const uid = options?.uid ?? 0;\n const gid = options?.gid ?? 0;\n const date = options?.date ?? new Date();\n const uname = getUName(options?.uname, undefined, rs);\n const gname = getUName(options?.gname, undefined, rs);\n return {\n kind: 'directory',\n path, mode, uname, gname, uid, gid, date,\n };\n }\n};\n\n/**\n * Create a FileItem from content data directly\n * @param path - The path to the file in the tar archive\n * @param content - Content data\n * @param options - Metadata for the file including path in tar archive\n * @returns A FileItem\n */\nexport const createFileItem = async (\n path: string,\n content: string | Buffer,\n options?: CreateItemOptions\n): Promise<FileItem> => {\n const mode = options?.mode ?? 0o644;\n const uid = options?.uid ?? 0;\n const gid = options?.gid ?? 0;\n const date = options?.date ?? new Date();\n\n const uname = options?.uname ?? 'root';\n const gname = options?.gname ?? 'root';\n\n // Create a FileItem\n return {\n kind: 'file',\n path, mode, uname, gname, uid, gid, date,\n content\n };\n};\n\n/**\n * Create a FileItem from a Readable stream\n * @param path - The path to the file in the tar archive\n * @param readable - The readable stream\n * @param options - Metadata for the file including path in tar archive\n * @returns A FileItem\n */\nexport const createReadableFileItem = async (\n path: string,\n readable: Readable,\n options?: CreateReadableFileItemOptions\n): Promise<FileItem> => {\n const mode = options?.mode ?? 0o644;\n const uid = options?.uid ?? 0;\n const gid = options?.gid ?? 0;\n const date = options?.date ?? new Date();\n\n const uname = options?.uname ?? 'root';\n const gname = options?.gname ?? 'root';\n\n // When length is not provided, calculate the total size by reading all chunks\n let length = options?.length;\n if (!length) {\n // Calculate the total size by reading all chunks\n const chunks: Buffer[] = [];\n length = 0;\n\n // Collect all chunks to calculate size\n for await (const chunk of readable) {\n const buffer = getBuffer(chunk);\n chunks.push(buffer);\n length += buffer.length;\n }\n\n // Create a FileItem\n return {\n kind: 'file',\n path, mode, uname, gname, uid, gid, date,\n content: {\n kind: 'readable',\n length,\n readable: Readable.from(chunks)\n }\n };\n } else {\n // Create a FileItem\n return {\n kind: 'file',\n path, mode, uname, gname, uid, gid, date,\n content: {\n kind: 'readable',\n length,\n readable\n }\n };\n }\n};\n\n/**\n * Create a FileItem from a generator\n * @param path - The path to the file in the tar archive\n * @param generator - The generator to read the file from\n * @param options - Metadata for the file including path in tar archive\n * @returns A FileItem\n */\nexport const createGeneratorFileItem = async (\n path: string,\n generator: AsyncGenerator<Buffer, void, unknown>,\n options?: CreateReadableFileItemOptions\n): Promise<FileItem> => {\n const mode = options?.mode ?? 0o644;\n const uid = options?.uid ?? 0;\n const gid = options?.gid ?? 0;\n const date = options?.date ?? new Date();\n\n const uname = options?.uname ?? 'root';\n const gname = options?.gname ?? 'root';\n\n // When length is not provided, calculate the total size by reading all chunks\n let length = options?.length;\n if (!length) {\n // Calculate the total size by reading all chunks\n const chunks: Buffer[] = [];\n length = 0;\n\n // Collect all chunks to calculate size\n for await (const chunk of generator) {\n const buffer = getBuffer(chunk);\n chunks.push(buffer);\n length += buffer.length;\n }\n\n // Create a FileItem\n return {\n kind: 'file',\n path, mode, uname, gname, uid, gid, date,\n content: {\n kind: 'readable',\n length,\n readable: Readable.from(chunks)\n }\n };\n } else {\n // Create a FileItem\n return {\n kind: 'file',\n path, mode, uname, gname, uid, gid, date,\n content: {\n kind: 'generator',\n length,\n generator\n }\n };\n }\n};\n\n/**\n * Create a FileItem from a local file path\n * @param path - The path to the file in the tar archive\n * @param filePath - The path to the file to read from real filesystem\n * @param reflectStat - Whether to reflect optional stat of the file (mode, uid, gid, mtime. Default: 'exceptName')\n * @param options - Metadata for the file including path in tar archive\n * @returns A FileItem\n */\nexport const createReadFileItem = async (\n path: string,\n filePath: string,\n reflectStat?: ReflectStats,\n options?: CreateItemOptions\n): Promise<FileItem> => {\n const rs = reflectStat ?? 'exceptName';\n\n // Get file stats to extract metadata\n const stats = await stat(filePath);\n // Create readable stream from file\n const reader = createReadStream(filePath);\n\n const mode = options?.mode ?? (rs !== 'none' ? stats.mode : undefined);\n const uid = options?.uid ?? (rs !== 'none' ? stats.uid : undefined);\n const gid = options?.gid ?? (rs !== 'none' ? stats.gid : undefined);\n const date = options?.date ?? (rs !== 'none' ? stats.mtime : undefined);\n\n const uname = getUName(options?.uname, stats.uid, rs);\n const gname = getUName(options?.gname, stats.gid, rs);\n\n // Create a FileItem\n return await createReadableFileItem(path, reader, {\n length: stats.size, mode, uname, gname, uid, gid, date,\n });\n};\n\n/**\n * Store a readable stream to a file\n * @param reader - The readable stream\n * @param path - The path to the file to store the readable stream to\n * @returns A promise that resolves when the stream is finished\n */\nexport const storeReaderToFile = (reader: Readable, path: string) => {\n const writer = createWriteStream(path);\n reader.pipe(writer);\n return new Promise<void>((res, rej) => {\n writer.on('finish', res);\n writer.on('error', rej);\n });\n};\n","// tar-vern - Tape archiver library for Typescript\n// Copyright (c) Kouji Matsui (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/tar-vern/\n\nimport { Readable } from \"stream\";\nimport { createGzip } from \"zlib\";\nimport { getBuffer } from \"./utils\";\nimport { CompressionTypes, EntryItem } from \"./types\";\n\n/**\n * Get the byte length of a string in UTF-8\n * @param str - The string to get the byte length of\n * @returns The byte length of the string\n */\nconst utf8ByteLength = (str: string) => {\n return Buffer.byteLength(str, \"utf8\");\n}\n\n/**\n * Truncate a string to a maximum byte length in UTF-8\n * @param str - The string to truncate\n * @param maxBytes - The maximum byte length\n * @returns The truncated string\n */\nconst truncateUtf8Safe = (str: string, maxBytes: number) => {\n let total = 0;\n let i = 0;\n while (i < str.length) {\n const codePoint = str.codePointAt(i)!;\n const char = String.fromCodePoint(codePoint);\n const charBytes = Buffer.byteLength(char, \"utf8\");\n if (total + charBytes > maxBytes) break;\n total += charBytes;\n i += char.length;\n }\n return str.slice(0, i);\n}\n\n// Tar specification: name max 100 bytes, prefix max 155 bytes\nconst MAX_NAME = 100;\nconst MAX_PREFIX = 155;\n\n/**\n * Split a path into a name and a prefix\n * @param path - The path to split\n * @returns The name and prefix\n */\nconst splitPath = (path: string) => {\n if (utf8ByteLength(path) <= MAX_NAME) {\n return { prefix: \"\", name: path };\n }\n\n // Split by '/' and find the part that fits in name from the end\n const parts = path.split(\"/\");\n let name = parts.pop() ?? \"\";\n let prefix = parts.join(\"/\");\n\n // Truncate if name exceeds 100 bytes\n if (utf8ByteLength(name) > MAX_NAME) {\n name = truncateUtf8Safe(name, MAX_NAME);\n }\n\n // Truncate if prefix exceeds 155 bytes\n while (utf8ByteLength(prefix) > MAX_PREFIX) {\n prefix = truncateUtf8Safe(prefix, MAX_PREFIX);\n }\n\n return { prefix, name };\n}\n\n///////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Get octal bytes from a number\n * @param value - The number to get octal bytes from\n * @param length - The length of the octal bytes\n * @returns The octal bytes\n */\nconst getOctalBytes = (value: number, length: number) => {\n const str = value.toString(8).padStart(length - 1, \"0\") + \"\\0\";\n return Buffer.from(str, \"ascii\");\n};\n\n/**\n * Get padded bytes from a buffer\n * @param buffer - The buffer to get padded bytes from\n * @returns The padded bytes\n */\nconst getPaddedBytes = (buffer: Buffer) => {\n const extra = buffer.length % 512;\n if (extra === 0) {\n return buffer;\n } else {\n return Buffer.concat([buffer, Buffer.alloc(512 - extra, 0)]);\n }\n}\n\n/**\n * The terminator bytes\n */\nconst terminatorBytes = Buffer.alloc(1024, 0);\n\n/**\n * Create a tar header\n * @param type - The type of the entry\n * @param path - The path of the entry\n * @param size - The size of the entry\n * @param mode - The mode of the entry\n * @param uname - The user name of the entry\n * @param gname - The group name of the entry\n */\nconst createTarHeader = (\n type: 'file' | 'directory',\n path: string,\n size: number,\n mode: number,\n uname: string,\n gname: string,\n uid: number,\n gid: number,\n date: Date\n) => {\n // Allocate header bytes\n const buffer = Buffer.alloc(512, 0);\n\n // Split path into name and prefix\n const { name, prefix } = splitPath(path);\n\n // Write name, mode, uid, gid, size, mtime, typeflag, prefix, checksum\n buffer.write(name, 0, 100, \"utf8\");\n getOctalBytes(mode & 0o7777, 8).copy(buffer, 100);\n getOctalBytes(uid, 8).copy(buffer, 108);\n getOctalBytes(gid, 8).copy(buffer, 116);\n getOctalBytes(size, 12).copy(buffer, 124);\n getOctalBytes(Math.floor(date.getTime() / 1000), 12).copy(buffer, 136);\n\n // Check sum space\n Buffer.from(\" \", \"ascii\").copy(buffer, 148);\n\n if (type === 'file') {\n buffer.write(\"0\", 156, 1, \"ascii\"); // typeflag (file)\n } else {\n buffer.write(\"5\", 156, 1, \"ascii\"); // typeflag (directory)\n }\n buffer.write(\"ustar\\0\", 257, 6, \"ascii\");\n buffer.write(\"00\", 263, 2, \"ascii\"); // version\n buffer.write(uname, 265, 32, \"utf8\");\n buffer.write(gname, 297, 32, \"utf8\");\n buffer.write(prefix, 345, 155, \"utf8\"); // Path prefix\n\n // Calculate check sum\n let sum = 0;\n for (let i = 0; i < 512; i++) {\n sum += buffer[i];\n }\n getOctalBytes(sum, 8).copy(buffer, 148);\n\n return buffer;\n}\n\n///////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Create a tar packer\n * @param entryItemGenerator - The async generator of the entry items\n * @param compressionType - The compression type to use (Default: 'none')\n * @param signal - The abort signal to cancel the tar packer\n * @returns Readable stream of the tar packer\n */\nexport const createTarPacker = (\n entryItemGenerator: AsyncGenerator<EntryItem, void, unknown>,\n compressionType?: CompressionTypes,\n signal?: AbortSignal) => {\n\n // Create async generator function from entry item iterator\n const entryItemIterator = async function*() {\n // Iterate over the entry items\n for await (const entryItem of entryItemGenerator) {\n signal?.throwIfAborted();\n\n switch (entryItem.kind) {\n // Entry is a file\n case 'file': {\n const entryItemContent = entryItem.content;\n // Content is a string or buffer\n if (typeof entryItemContent === 'string' || Buffer.isBuffer(entryItemContent)) {\n // Get content bytes from string or buffer\n const contentBytes = getBuffer(entryItemContent);\n\n // Create and produce tar header bytes\n const tarHeaderBytes = createTarHeader(\n 'file',\n entryItem.path,\n contentBytes.length,\n entryItem.mode,\n entryItem.uname,\n entryItem.gname,\n entryItem.uid,\n entryItem.gid,\n entryItem.date);\n yield tarHeaderBytes;\n\n // Content bytes to adjust padding space and produce\n const totalPaddedContentBytes = getPaddedBytes(contentBytes);\n yield totalPaddedContentBytes;\n } else {\n // Create and produce tar header bytes\n const tarHeaderBytes = createTarHeader(\n 'file',\n entryItem.path,\n entryItemContent.length,\n entryItem.mode,\n entryItem.uname,\n entryItem.gname,\n entryItem.uid,\n entryItem.gid,\n entryItem.date);\n yield tarHeaderBytes;\n\n let position = 0;\n switch (entryItemContent.kind) {\n // Content is a generator\n case 'generator': {\n for await (const contentBytes of entryItemContent.generator) {\n signal?.throwIfAborted();\n yield contentBytes;\n position += contentBytes.length;\n }\n break;\n }\n // Content is a readable stream\n case 'readable': {\n for await (const content of entryItemContent.readable) {\n signal?.throwIfAborted();\n const contentBytes = getBuffer(content);\n yield contentBytes;\n position += contentBytes.length;\n }\n break;\n }\n }\n\n // Padding space\n if (position % 512 !== 0) {\n signal?.throwIfAborted();\n yield Buffer.alloc(512 - (position % 512), 0);\n }\n }\n break;\n }\n // Entry is a directory\n case 'directory': {\n // Create and produce tar header bytes\n const tarHeaderBytes = createTarHeader(\n 'directory',\n entryItem.path,\n 0,\n entryItem.mode,\n entryItem.uname,\n entryItem.gname,\n entryItem.uid,\n entryItem.gid,\n entryItem.date\n );\n yield tarHeaderBytes;\n break;\n }\n }\n }\n\n // Terminates for tar stream\n yield terminatorBytes;\n };\n\n const ct = compressionType ?? 'none';\n\n switch (ct) {\n // No compression\n case 'none': {\n // Create readable stream from entry item iterator\n return Readable.from(entryItemIterator());\n }\n // Gzip compression\n case 'gzip': {\n // Create gzip stream\n const gzipStream = createGzip({ level: 9 });\n // Create readable stream from entry item iterator\n const entryItemStream = Readable.from(entryItemIterator());\n // Pipe the entry item stream to the gzip stream\n entryItemStream.pipe(gzipStream);\n // Return the gzip stream\n return gzipStream;\n }\n }\n};\n"],"names":[],"mappings":"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"}
package/dist/packer.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * name: tar-vern
3
- * version: 0.1.0
3
+ * version: 0.2.0
4
4
  * description: Tape archiver library for Typescript
5
5
  * author: Kouji Matsui (@kekyo@mi.kekyo.net)
6
6
  * license: MIT
@@ -1 +1 @@
1
- {"version":3,"file":"packer.d.ts","sourceRoot":"","sources":["../src/packer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AA4JtD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAC1B,oBAAoB,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,EAC5D,kBAAkB,gBAAgB,EAClC,SAAS,WAAW,aA0JrB,CAAC"}
1
+ {"version":3,"file":"packer.d.ts","sourceRoot":"","sources":["../src/packer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGlC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AA2JtD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAC1B,oBAAoB,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,EAC5D,kBAAkB,gBAAgB,EAClC,SAAS,WAAW,aA0HrB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * name: tar-vern
3
- * version: 0.1.0
3
+ * version: 0.2.0
4
4
  * description: Tape archiver library for Typescript
5
5
  * author: Kouji Matsui (@kekyo@mi.kekyo.net)
6
6
  * license: MIT
@@ -111,6 +111,7 @@ export type ReflectStats = 'all' | 'exceptName' | 'none';
111
111
  export type CompressionTypes = 'none' | 'gzip';
112
112
  /**
113
113
  * Options for creating an item
114
+ * @remarks If these option values are provided, will set values to the item exactly
114
115
  */
115
116
  export interface CreateItemOptions {
116
117
  /**
@@ -144,15 +145,17 @@ export interface CreateItemOptions {
144
145
  export interface CreateDirectoryItemOptions extends CreateItemOptions {
145
146
  /**
146
147
  * The real directory path
148
+ * @remarks If provided, will get the stats from the directory path
147
149
  */
148
150
  readonly directoryPath?: string;
149
151
  }
150
152
  /**
151
- * Options for creating a readable item
153
+ * Options for creating a readable/generator item
152
154
  */
153
- export interface CreateReadableItemOptions extends CreateItemOptions {
155
+ export interface CreateReadableFileItemOptions extends CreateItemOptions {
154
156
  /**
155
157
  * The length of the item
158
+ * @remarks If not provided, the length will be calculated by reading all chunks
156
159
  */
157
160
  readonly length?: number;
158
161
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC;IACxC;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,oBAAoB;IACrE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,wBAAyB,SAAQ,oBAAoB;IACpE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,yBAAyB,GAAG,wBAAwB,CAAC;AAIpF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IACpC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,QAAS,SAAQ,aAAa;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,gBAAgB,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,aAAa;IAClD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,aAAa,CAAC;AAIjD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,YAAY,GAAG,MAAM,CAAC;AAEzD;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA2B,SAAQ,iBAAiB;IACnE;;OAEG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,iBAAiB;IAClE;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC;IACxC;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,oBAAoB;IACrE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,wBAAyB,SAAQ,oBAAoB;IACpE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,yBAAyB,GAAG,wBAAwB,CAAC;AAIpF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IACpC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,QAAS,SAAQ,aAAa;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,gBAAgB,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,aAAa;IAClD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,aAAa,CAAC;AAIjD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,YAAY,GAAG,MAAM,CAAC;AAEzD;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/C;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA2B,SAAQ,iBAAiB;IACnE;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,6BAA8B,SAAQ,iBAAiB;IACtE;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B"}
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * name: tar-vern
3
- * version: 0.1.0
3
+ * version: 0.2.0
4
4
  * description: Tape archiver library for Typescript
5
5
  * author: Kouji Matsui (@kekyo@mi.kekyo.net)
6
6
  * license: MIT
@@ -8,7 +8,13 @@
8
8
  */
9
9
 
10
10
  import { Readable } from 'stream';
11
- import { CreateItemOptions, CreateReadableItemOptions, FileItem, DirectoryItem, ReflectStats, CreateDirectoryItemOptions } from './types';
11
+ import { CreateItemOptions, CreateReadableFileItemOptions, FileItem, DirectoryItem, ReflectStats, CreateDirectoryItemOptions } from './types';
12
+ /**
13
+ * Get a buffer from the string or Buffer
14
+ * @param data - The data to get a buffer from
15
+ * @returns A buffer
16
+ */
17
+ export declare const getBuffer: (data: Buffer | string) => Buffer<ArrayBufferLike>;
12
18
  /**
13
19
  * Create a DirectoryItem
14
20
  * @param path - The path to the directory in the tar archive
@@ -18,14 +24,30 @@ import { CreateItemOptions, CreateReadableItemOptions, FileItem, DirectoryItem,
18
24
  * @remarks When reflectStat is 'all' or 'exceptName', `options.directoryPath` must be provided.
19
25
  */
20
26
  export declare const createDirectoryItem: (path: string, reflectStat?: ReflectStats, options?: CreateDirectoryItemOptions) => Promise<DirectoryItem>;
27
+ /**
28
+ * Create a FileItem from content data directly
29
+ * @param path - The path to the file in the tar archive
30
+ * @param content - Content data
31
+ * @param options - Metadata for the file including path in tar archive
32
+ * @returns A FileItem
33
+ */
34
+ export declare const createFileItem: (path: string, content: string | Buffer, options?: CreateItemOptions) => Promise<FileItem>;
21
35
  /**
22
36
  * Create a FileItem from a Readable stream
23
37
  * @param path - The path to the file in the tar archive
24
- * @param reader - The readable stream
38
+ * @param readable - The readable stream
39
+ * @param options - Metadata for the file including path in tar archive
40
+ * @returns A FileItem
41
+ */
42
+ export declare const createReadableFileItem: (path: string, readable: Readable, options?: CreateReadableFileItemOptions) => Promise<FileItem>;
43
+ /**
44
+ * Create a FileItem from a generator
45
+ * @param path - The path to the file in the tar archive
46
+ * @param generator - The generator to read the file from
25
47
  * @param options - Metadata for the file including path in tar archive
26
48
  * @returns A FileItem
27
49
  */
28
- export declare const createReadableItem: (path: string, reader: Readable, options?: CreateReadableItemOptions) => Promise<FileItem>;
50
+ export declare const createGeneratorFileItem: (path: string, generator: AsyncGenerator<Buffer, void, unknown>, options?: CreateReadableFileItemOptions) => Promise<FileItem>;
29
51
  /**
30
52
  * Create a FileItem from a local file path
31
53
  * @param path - The path to the file in the tar archive
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAa1I;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAC9B,MAAM,MAAM,EACZ,cAAc,YAAY,EAC1B,UAAU,0BAA0B,KACnC,OAAO,CAAC,aAAa,CA2BvB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAC7B,MAAM,MAAM,EACZ,QAAQ,QAAQ,EAChB,UAAU,yBAAyB,KAClC,OAAO,CAAC,QAAQ,CAuClB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAC7B,MAAM,MAAM,EACZ,UAAU,MAAM,EAChB,cAAc,YAAY,EAC1B,UAAU,iBAAiB,KAC1B,OAAO,CAAC,QAAQ,CAoBlB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,QAAQ,EAAE,MAAM,MAAM,kBAO/D,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,6BAA6B,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAa9I;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,GAAG,MAAM,4BAE9C,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAC9B,MAAM,MAAM,EACZ,cAAc,YAAY,EAC1B,UAAU,0BAA0B,KACnC,OAAO,CAAC,aAAa,CA2BvB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,SAAS,MAAM,GAAG,MAAM,EACxB,UAAU,iBAAiB,KAC1B,OAAO,CAAC,QAAQ,CAelB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,GACjC,MAAM,MAAM,EACZ,UAAU,QAAQ,EAClB,UAAU,6BAA6B,KACtC,OAAO,CAAC,QAAQ,CA6ClB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,MAAM,EACZ,WAAW,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,EAChD,UAAU,6BAA6B,KACtC,OAAO,CAAC,QAAQ,CA6ClB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAC7B,MAAM,MAAM,EACZ,UAAU,MAAM,EAChB,cAAc,YAAY,EAC1B,UAAU,iBAAiB,KAC1B,OAAO,CAAC,QAAQ,CAoBlB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,QAAQ,EAAE,MAAM,MAAM,kBAO/D,CAAC"}