@e280/mammoth 0.1.0-1 → 0.1.0-10

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 (74) hide show
  1. package/README.md +114 -5
  2. package/package.json +7 -4
  3. package/s/browser/example.ts +10 -11
  4. package/s/browser/index.ts +1 -1
  5. package/s/browser/{iceberg-opfs.ts → opfs-bucket.ts} +2 -8
  6. package/s/core/{hash-stream.ts → analyze.ts} +6 -2
  7. package/s/core/consts.ts +8 -0
  8. package/s/core/index.ts +3 -2
  9. package/s/core/mammoth.ts +55 -45
  10. package/s/core/{iceberg-memory.ts → memory-bucket.ts} +2 -6
  11. package/s/core/streamify.ts +18 -0
  12. package/s/core/types.ts +37 -9
  13. package/s/core/utils/is-expired.ts +10 -0
  14. package/s/core/utils/manifest.ts +113 -0
  15. package/s/core/utils/not-found.ts +7 -0
  16. package/s/core/utils/save.ts +30 -0
  17. package/s/node/disk-bucket.ts +55 -0
  18. package/s/node/index.ts +4 -0
  19. package/s/node/utils/is-not-found.ts +9 -0
  20. package/s/test.ts +37 -12
  21. package/x/browser/example.js +10 -11
  22. package/x/browser/example.js.map +1 -1
  23. package/x/browser/index.d.ts +1 -1
  24. package/x/browser/index.js +1 -1
  25. package/x/browser/index.js.map +1 -1
  26. package/x/browser/{iceberg-opfs.d.ts → opfs-bucket.d.ts} +2 -3
  27. package/x/browser/{iceberg-opfs.js → opfs-bucket.js} +2 -7
  28. package/x/browser/opfs-bucket.js.map +1 -0
  29. package/x/core/analyze.d.ts +2 -0
  30. package/x/core/{hash-stream.js → analyze.js} +6 -3
  31. package/x/core/analyze.js.map +1 -0
  32. package/x/core/consts.d.ts +4 -0
  33. package/x/core/consts.js +6 -0
  34. package/x/core/consts.js.map +1 -0
  35. package/x/core/index.d.ts +3 -2
  36. package/x/core/index.js +3 -2
  37. package/x/core/index.js.map +1 -1
  38. package/x/core/mammoth.d.ts +7 -5
  39. package/x/core/mammoth.js +52 -40
  40. package/x/core/mammoth.js.map +1 -1
  41. package/x/core/{iceberg-memory.d.ts → memory-bucket.d.ts} +2 -3
  42. package/x/core/{iceberg-memory.js → memory-bucket.js} +2 -5
  43. package/x/core/memory-bucket.js.map +1 -0
  44. package/x/core/streamify.d.ts +1 -0
  45. package/x/core/streamify.js +15 -0
  46. package/x/core/streamify.js.map +1 -0
  47. package/x/core/types.d.ts +27 -9
  48. package/x/core/utils/is-expired.d.ts +2 -0
  49. package/x/core/utils/is-expired.js +7 -0
  50. package/x/core/utils/is-expired.js.map +1 -0
  51. package/x/core/utils/manifest.d.ts +19 -0
  52. package/x/core/utils/manifest.js +91 -0
  53. package/x/core/utils/manifest.js.map +1 -0
  54. package/x/core/utils/not-found.d.ts +2 -0
  55. package/x/core/utils/not-found.js +4 -0
  56. package/x/core/utils/not-found.js.map +1 -0
  57. package/x/core/utils/save.d.ts +2 -0
  58. package/x/core/utils/save.js +19 -0
  59. package/x/core/utils/save.js.map +1 -0
  60. package/x/node/disk-bucket.d.ts +9 -0
  61. package/x/node/disk-bucket.js +43 -0
  62. package/x/node/disk-bucket.js.map +1 -0
  63. package/x/node/index.d.ts +2 -0
  64. package/x/node/index.js +3 -0
  65. package/x/node/index.js.map +1 -0
  66. package/x/node/utils/is-not-found.d.ts +1 -0
  67. package/x/node/utils/is-not-found.js +6 -0
  68. package/x/node/utils/is-not-found.js.map +1 -0
  69. package/x/test.js +35 -12
  70. package/x/test.js.map +1 -1
  71. package/x/browser/iceberg-opfs.js.map +0 -1
  72. package/x/core/hash-stream.d.ts +0 -1
  73. package/x/core/hash-stream.js.map +0 -1
  74. package/x/core/iceberg-memory.js.map +0 -1
@@ -0,0 +1,55 @@
1
+
2
+ import {join} from "node:path"
3
+ import {Readable} from "node:stream"
4
+ import {pipeline} from "node:stream/promises"
5
+ import {mkdir, stat, unlink} from "node:fs/promises"
6
+ import {createWriteStream, openAsBlob} from "node:fs"
7
+
8
+ import {Bucket, Id} from "../core/types.js"
9
+ import {isNotFound} from "./utils/is-not-found.js"
10
+
11
+ export class DiskBucket implements Bucket {
12
+ #directory
13
+
14
+ constructor(directory: string) {
15
+ this.#directory = directory
16
+ }
17
+
18
+ async has(id: Id) {
19
+ try {
20
+ await stat(this.#path(id))
21
+ return true
22
+ }
23
+ catch (error) {
24
+ if (isNotFound(error)) return false
25
+ throw error
26
+ }
27
+ }
28
+
29
+ async delete(id: Id) {
30
+ try {
31
+ await unlink(this.#path(id))
32
+ }
33
+ catch (error) {
34
+ if (!isNotFound(error))
35
+ throw error
36
+ }
37
+ }
38
+
39
+ async read(id: Id) {
40
+ return openAsBlob(this.#path(id))
41
+ }
42
+
43
+ async write(id: Id, readable: ReadableStream<Uint8Array>) {
44
+ await mkdir(this.#directory, {recursive: true})
45
+ await pipeline(
46
+ Readable.fromWeb(readable as any),
47
+ createWriteStream(this.#path(id)),
48
+ )
49
+ }
50
+
51
+ #path(id: Id) {
52
+ return join(this.#directory, id)
53
+ }
54
+ }
55
+
@@ -0,0 +1,4 @@
1
+
2
+ export * from "../core/index.js"
3
+ export * from "./disk-bucket.js"
4
+
@@ -0,0 +1,9 @@
1
+
2
+ export function isNotFound(error: unknown): error is NodeJS.ErrnoException {
3
+ return (
4
+ error instanceof Error
5
+ && "code" in error
6
+ && error.code === "ENOENT"
7
+ )
8
+ }
9
+
package/s/test.ts CHANGED
@@ -1,24 +1,35 @@
1
1
 
2
2
  import {Kv} from "@e280/kv"
3
+ import {rm} from "fs/promises"
3
4
  import {bytes, collect} from "@e280/stz"
4
5
  import {science, test, expect} from "@e280/science"
5
6
 
6
7
  import {Mammoth} from "./core/mammoth.js"
8
+ import {DiskBucket} from "./node/disk-bucket.js"
7
9
  import {randomId} from "./core/utils/random-id.js"
8
- import {IcebergMemory} from "./core/iceberg-memory.js"
10
+ import {MemoryBucket} from "./core/memory-bucket.js"
9
11
 
10
12
  const blob = () => new Blob([new Uint8Array([0xDE, 0xAD, 0xBE, 0xEF])])
11
13
  const quickstream = (b: number[]) => new Blob([new Uint8Array(b)]).stream()
12
14
 
13
15
  function setup() {
14
- const index = new Kv<string>()
15
- const iceberg = new IcebergMemory()
16
- const mammoth = new Mammoth(index, iceberg)
16
+ const kv = new Kv()
17
+ const bucket = new MemoryBucket()
18
+ const mammoth = new Mammoth(bucket, kv)
17
19
  return {mammoth}
18
20
  }
19
21
 
20
22
  await science.run({
21
- "mammoth": {
23
+ "mammoth node": test(async() => {
24
+ const dataDir = "data"
25
+ await rm(dataDir, {recursive: true, force: true})
26
+ const mammoth = new Mammoth(new DiskBucket(dataDir), new Kv())
27
+ const hash = await mammoth.write(blob().stream())
28
+ const second = await mammoth.read(hash)
29
+ expect(bytes.eq(await second.bytes(), await blob().bytes()))
30
+ }),
31
+
32
+ "mammoth memory": {
22
33
  ".write and .read": test(async() => {
23
34
  const {mammoth} = setup()
24
35
  const hash = await mammoth.write(blob().stream())
@@ -30,7 +41,7 @@ await science.run({
30
41
  const {mammoth} = setup()
31
42
  const hashA = await mammoth.write(blob().stream())
32
43
  const hashB = await mammoth.write(blob().stream())
33
- const keys = await collect(mammoth.keys())
44
+ const keys = await collect(mammoth.hashes())
34
45
  expect(hashA).is(hashB)
35
46
  expect(keys.length).is(1)
36
47
  expect(keys[0]).is(hashA)
@@ -39,7 +50,7 @@ await science.run({
39
50
  ".write empty file": test(async() => {
40
51
  const {mammoth} = setup()
41
52
  const hash = await mammoth.write(new Blob().stream())
42
- expect(await mammoth.size(hash)).is(0)
53
+ expect((await mammoth.info(hash)).size).is(0)
43
54
  expect((await mammoth.read(hash)).size).is(0)
44
55
  }),
45
56
 
@@ -48,7 +59,20 @@ await science.run({
48
59
  const hashA = await mammoth.write(quickstream([0xC0, 0xFF, 0xEE]))
49
60
  const hashB = await mammoth.write(quickstream([0xB0, 0x0B, 0x1E, 0x5]))
50
61
  expect(hashA).not.is(hashB)
51
- expect((await collect(mammoth.keys())).length).is(2)
62
+ expect((await collect(mammoth.hashes())).length).is(2)
63
+ }),
64
+
65
+ ".stats": test(async() => {
66
+ const {mammoth} = setup()
67
+ expect(await mammoth.stats()).deep({count: 0, size: 0})
68
+ const hashA = await mammoth.write(quickstream([0xC0, 0xFF, 0xEE]))
69
+ expect(await mammoth.stats()).deep({count: 1, size: 3})
70
+ const hashB = await mammoth.write(quickstream([0xB0, 0x0B, 0x1E, 0x5]))
71
+ expect(await mammoth.stats()).deep({count: 2, size: 7})
72
+ await mammoth.delete(hashA)
73
+ expect(await mammoth.stats()).deep({count: 1, size: 4})
74
+ await mammoth.delete(hashB)
75
+ expect(await mammoth.stats()).deep({count: 0, size: 0})
52
76
  }),
53
77
 
54
78
  ".has": test(async() => {
@@ -60,8 +84,9 @@ await science.run({
60
84
 
61
85
  ".size": test(async() => {
62
86
  const {mammoth} = setup()
63
- const hash = await mammoth.write(blob().stream())
64
- expect(await mammoth.size(hash)).is(4)
87
+ const b = blob()
88
+ const hash = await mammoth.write(b.stream())
89
+ expect((await mammoth.info(hash)).size).is(b.size)
65
90
  }),
66
91
 
67
92
  ".delete": test(async() => {
@@ -69,7 +94,7 @@ await science.run({
69
94
  const hash = await mammoth.write(blob().stream())
70
95
  await mammoth.delete(hash)
71
96
  expect(await mammoth.has(hash)).is(false)
72
- expect(await collect(mammoth.keys())).deep([])
97
+ expect(await collect(mammoth.hashes())).deep([])
73
98
  }),
74
99
 
75
100
  ".delete idempotent": test(async() => {
@@ -80,7 +105,7 @@ await science.run({
80
105
  ".keys": test(async() => {
81
106
  const {mammoth} = setup()
82
107
  const hash = await mammoth.write(blob().stream())
83
- const keys = await collect(mammoth.keys())
108
+ const keys = await collect(mammoth.hashes())
84
109
  expect(keys.length).is(1)
85
110
  expect(keys[0]).is(hash)
86
111
  }),
@@ -1,20 +1,19 @@
1
1
  import { Kv, StorageDriver } from "@e280/kv";
2
2
  import { Mammoth } from "../core/mammoth.js";
3
- import { IcebergOpfs } from "./iceberg-opfs.js";
3
+ import { OpfsBucket } from "./opfs-bucket.js";
4
4
  export async function example() {
5
- // setup the localstorage kv index
5
+ // setup the localstorage kv
6
6
  const driver = new StorageDriver(window.localStorage);
7
- const kv = new Kv(driver);
8
- const index = kv.scope("glacier_index");
9
- // setup the opfs iceberg
7
+ const kv = new Kv(driver).scope("mammoth");
8
+ // setup the opfs file bucket
10
9
  const root = await navigator.storage.getDirectory();
11
- const directory = await root.getDirectoryHandle("glacier", { create: true });
12
- const iceberg = new IcebergOpfs(directory);
10
+ const directory = await root.getDirectoryHandle("mammoth", { create: true });
11
+ const bucket = new OpfsBucket(directory);
13
12
  // setup the mammoth
14
- const mammoth = new Mammoth(index, iceberg);
15
- const bigFile = new Blob([new Uint8Array([0xDE, 0xAD, 0xBE, 0xEF])]);
13
+ const mammoth = new Mammoth(bucket, kv);
14
+ const myFile = new Blob([new Uint8Array([0xDE, 0xAD, 0xBE, 0xEF])]);
16
15
  // write a file as an example
17
- const hash = await mammoth.write(bigFile.stream());
18
- console.log(`mammoth stored file by hash "${hash}"`);
16
+ const hash = await mammoth.write(myFile.stream());
17
+ console.log(`mammoth stored file "${hash}"`);
19
18
  }
20
19
  //# sourceMappingURL=example.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"example.js","sourceRoot":"","sources":["../../s/browser/example.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,EAAE,EAAE,aAAa,EAAC,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAA;AAE7C,MAAM,CAAC,KAAK,UAAU,OAAO;IAE5B,kCAAkC;IAClC,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACrD,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,CAAA;IACzB,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;IAEvC,yBAAyB;IACzB,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,CAAA;IACnD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAC,MAAM,EAAE,IAAI,EAAC,CAAC,CAAA;IAC1E,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,SAAS,CAAC,CAAA;IAE1C,oBAAoB;IACpB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAC3C,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAEpE,6BAA6B;IAC7B,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAClD,OAAO,CAAC,GAAG,CAAC,gCAAgC,IAAI,GAAG,CAAC,CAAA;AACrD,CAAC"}
1
+ {"version":3,"file":"example.js","sourceRoot":"","sources":["../../s/browser/example.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,EAAE,EAAE,aAAa,EAAC,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAA;AAE3C,MAAM,CAAC,KAAK,UAAU,OAAO;IAE5B,4BAA4B;IAC5B,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACrD,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IAE1C,6BAA6B;IAC7B,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,CAAA;IACnD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAC,MAAM,EAAE,IAAI,EAAC,CAAC,CAAA;IAC1E,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAA;IAExC,oBAAoB;IACpB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACvC,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAEnE,6BAA6B;IAC7B,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;IACjD,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,GAAG,CAAC,CAAA;AAC7C,CAAC"}
@@ -1,2 +1,2 @@
1
1
  export * from "../core/index.js";
2
- export * from "./iceberg-opfs.js";
2
+ export * from "./opfs-bucket.js";
@@ -1,3 +1,3 @@
1
1
  export * from "../core/index.js";
2
- export * from "./iceberg-opfs.js";
2
+ export * from "./opfs-bucket.js";
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../s/browser/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../s/browser/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA"}
@@ -1,9 +1,8 @@
1
- import { Iceberg, Id } from "../core/types.js";
2
- export declare class IcebergOpfs implements Iceberg {
1
+ import { Bucket, Id } from "../core/types.js";
2
+ export declare class OpfsBucket implements Bucket {
3
3
  #private;
4
4
  constructor(directory: FileSystemDirectoryHandle);
5
5
  has(id: Id): Promise<boolean>;
6
- size(id: Id): Promise<number>;
7
6
  delete(id: Id): Promise<void>;
8
7
  read(id: Id): Promise<File>;
9
8
  write(id: Id, readable: ReadableStream<Uint8Array>): Promise<void>;
@@ -1,5 +1,5 @@
1
1
  import { isNotFound } from "./utils/is-not-found.js";
2
- export class IcebergOpfs {
2
+ export class OpfsBucket {
3
3
  #directory;
4
4
  constructor(directory) {
5
5
  this.#directory = directory;
@@ -15,11 +15,6 @@ export class IcebergOpfs {
15
15
  throw error;
16
16
  }
17
17
  }
18
- async size(id) {
19
- const handle = await this.#directory.getFileHandle(id);
20
- const file = await handle.getFile();
21
- return file.size;
22
- }
23
18
  async delete(id) {
24
19
  try {
25
20
  await this.#directory.removeEntry(id);
@@ -39,4 +34,4 @@ export class IcebergOpfs {
39
34
  await readable.pipeTo(writable);
40
35
  }
41
36
  }
42
- //# sourceMappingURL=iceberg-opfs.js.map
37
+ //# sourceMappingURL=opfs-bucket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opfs-bucket.js","sourceRoot":"","sources":["../../s/browser/opfs-bucket.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,UAAU,EAAC,MAAM,yBAAyB,CAAA;AAElD,MAAM,OAAO,UAAU;IACtB,UAAU,CAAA;IAEV,YAAY,SAAoC;QAC/C,IAAI,CAAC,UAAU,GAAG,SAAS,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAM;QACf,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;YACvC,OAAO,IAAI,CAAA;QACZ,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACd,IAAI,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAA;YACnC,MAAM,KAAK,CAAA;QACZ,CAAC;IACF,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAM;QAClB,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;QACtC,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;gBACrB,MAAM,KAAK,CAAA;QACb,CAAC;IACF,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAM;QAChB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;QACtD,OAAO,MAAM,CAAC,OAAO,EAAE,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,EAAM,EAAE,QAAoC;QACvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,EAAE,EAAC,MAAM,EAAE,IAAI,EAAC,CAAC,CAAA;QACtE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAA;QAC9C,MAAM,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAChC,CAAC;CACD"}
@@ -0,0 +1,2 @@
1
+ import { Analysis } from "./types.js";
2
+ export declare function analyze(readable: ReadableStream<Uint8Array>): Promise<Analysis>;
@@ -1,14 +1,17 @@
1
1
  import { hex, nap } from "@e280/stz";
2
2
  import { blake3 } from "@noble/hashes/blake3.js";
3
3
  import { relaxer } from "./utils/relaxer.js";
4
- export async function hashStream(readable) {
4
+ export async function analyze(readable) {
5
+ let size = 0;
5
6
  const hasher = blake3.create();
6
7
  const relax = relaxer();
7
8
  for await (const chunk of readable) {
8
9
  hasher.update(chunk);
10
+ size += chunk.byteLength;
9
11
  if (relax())
10
12
  await nap();
11
13
  }
12
- return hex.fromBytes(hasher.digest());
14
+ const hash = hex.fromBytes(hasher.digest());
15
+ return { hash, size };
13
16
  }
14
- //# sourceMappingURL=hash-stream.js.map
17
+ //# sourceMappingURL=analyze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../s/core/analyze.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,GAAG,EAAE,GAAG,EAAC,MAAM,WAAW,CAAA;AAClC,OAAO,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAA;AAE9C,OAAO,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAA;AAE1C,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAoC;IACjE,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;IAC9B,MAAM,KAAK,GAAG,OAAO,EAAE,CAAA;IAEvB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACpB,IAAI,IAAI,KAAK,CAAC,UAAU,CAAA;QAExB,IAAI,KAAK,EAAE;YACV,MAAM,GAAG,EAAE,CAAA;IACb,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;IAC3C,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;AACpB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const consts: {
2
+ max_jobs: number;
3
+ expiry_time: number;
4
+ };
@@ -0,0 +1,6 @@
1
+ import { time } from "@e280/stz";
2
+ export const consts = {
3
+ max_jobs: 64,
4
+ expiry_time: time.days(7),
5
+ };
6
+ //# sourceMappingURL=consts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../../s/core/consts.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAE9B,MAAM,CAAC,MAAM,MAAM,GAAG;IACrB,QAAQ,EAAE,EAAE;IACZ,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;CACzB,CAAA"}
package/x/core/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export * from "./hash-stream.js";
2
- export * from "./iceberg-memory.js";
1
+ export * from "./analyze.js";
3
2
  export * from "./mammoth.js";
3
+ export * from "./memory-bucket.js";
4
+ export * from "./streamify.js";
4
5
  export * from "./types.js";
package/x/core/index.js CHANGED
@@ -1,5 +1,6 @@
1
- export * from "./hash-stream.js";
2
- export * from "./iceberg-memory.js";
1
+ export * from "./analyze.js";
3
2
  export * from "./mammoth.js";
3
+ export * from "./memory-bucket.js";
4
+ export * from "./streamify.js";
4
5
  export * from "./types.js";
5
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../s/core/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../s/core/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,oBAAoB,CAAA;AAClC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA"}
@@ -1,12 +1,14 @@
1
1
  import { Kv } from "@e280/kv";
2
- import { Glacier, Hash, Iceberg } from "./types.js";
3
- export declare class Mammoth implements Glacier {
2
+ import { Hash, Bucket } from "./types.js";
3
+ /** file storage datalake, content-addressed with blake3 hashes. */
4
+ export declare class Mammoth {
4
5
  #private;
5
- constructor(index: Kv<string>, iceberg: Iceberg);
6
+ constructor(bucket?: Bucket, kv?: Kv<any>);
7
+ hashes(): AsyncGenerator<string, void, unknown>;
6
8
  has(hash: Hash): Promise<boolean>;
7
- size(hash: Hash): Promise<number>;
9
+ info(hash: Hash): Promise<import("./types.js").Info>;
10
+ stats(): Promise<import("./types.js").Stats>;
8
11
  read(hash: Hash): Promise<Blob>;
9
12
  delete(hash: Hash): Promise<void>;
10
13
  write(readable: ReadableStream<Uint8Array>): Promise<Hash>;
11
- keys(): AsyncGenerator<string, void, unknown>;
12
14
  }
package/x/core/mammoth.js CHANGED
@@ -1,56 +1,68 @@
1
- import { got, hex } from "@e280/stz";
2
- import { blake3 } from "@noble/hashes/blake3.js";
1
+ import { Kv } from "@e280/kv";
2
+ import { lane, queue } from "@e280/stz";
3
+ import { consts } from "./consts.js";
4
+ import { save } from "./utils/save.js";
5
+ import { Manifest } from "./utils/manifest.js";
3
6
  import { randomId } from "./utils/random-id.js";
7
+ import { MemoryBucket } from "./memory-bucket.js";
8
+ /** file storage datalake, content-addressed with blake3 hashes. */
4
9
  export class Mammoth {
5
- #index;
6
- #iceberg;
7
- constructor(index, iceberg) {
8
- this.#index = index;
9
- this.#iceberg = iceberg;
10
+ #bucket;
11
+ #manifest;
12
+ #wholesome = lane(consts.max_jobs);
13
+ constructor(bucket = new MemoryBucket(), kv = new Kv()) {
14
+ this.#bucket = bucket;
15
+ this.#manifest = new Manifest(kv);
16
+ }
17
+ async *hashes() {
18
+ yield* this.#manifest.hashes();
10
19
  }
11
20
  async has(hash) {
12
- return this.#index.has(hash);
21
+ return this.#manifest.hasHash(hash);
22
+ }
23
+ async info(hash) {
24
+ return this.#manifest.needInfo(hash);
13
25
  }
14
- async size(hash) {
15
- const id = await this.#needFileId(hash);
16
- return this.#iceberg.size(id);
26
+ async stats() {
27
+ return this.#manifest.getStats();
17
28
  }
18
29
  async read(hash) {
19
- const id = await this.#needFileId(hash);
20
- return this.#iceberg.read(id);
30
+ const { id } = await this.#manifest.needInfo(hash);
31
+ return this.#bucket.read(id);
21
32
  }
22
33
  async delete(hash) {
23
- const id = await this.#getFileId(hash);
24
- if (id) {
25
- await this.#index.del(hash);
26
- await this.#iceberg.delete(id);
27
- }
34
+ await this.#wholesome(async () => {
35
+ const info = await this.#manifest.getInfo(hash);
36
+ if (info)
37
+ await this.#manifest.scheduleDeletion(hash, info);
38
+ });
39
+ await this.#cleanup();
28
40
  }
29
41
  async write(readable) {
30
42
  const id = randomId();
31
- const pipe = new TransformStream();
32
- const done = this.#iceberg.write(id, pipe.readable);
33
- const writer = pipe.writable.getWriter();
34
- const hasher = blake3.create();
35
- for await (const chunk of readable) {
36
- await writer.write(chunk);
37
- hasher.update(chunk);
43
+ await this.#manifest.addWip(id);
44
+ try {
45
+ const analysis = await save(this.#bucket, id, readable);
46
+ const { hash, size } = analysis;
47
+ const info = { id, size, added: Date.now() };
48
+ await this.#wholesome(() => this.#manifest.commit(hash, info));
49
+ return analysis.hash;
50
+ }
51
+ catch (error) {
52
+ await this.#manifest.moveWipToTrash(id);
53
+ throw error;
54
+ }
55
+ finally {
56
+ void this.#cleanup().catch(e => console.error("cleanup failed", e));
38
57
  }
39
- await writer.close();
40
- await done;
41
- const hash = hex.fromBytes(hasher.digest());
42
- await this.delete(hash);
43
- await this.#index.set(hash, id);
44
- return hash;
45
- }
46
- async #getFileId(hash) {
47
- return this.#index.get(hash);
48
- }
49
- async #needFileId(hash) {
50
- return got(await this.#getFileId(hash), `file not found by hash "${hash}"`);
51
- }
52
- async *keys() {
53
- yield* this.#index.keys();
54
58
  }
59
+ #cleanup = queue(async () => {
60
+ for await (const id of this.#manifest.getExpiredWipIds())
61
+ await this.#manifest.moveWipToTrash(id);
62
+ for await (const id of this.#manifest.listTrashIds()) {
63
+ await this.#bucket.delete(id);
64
+ await this.#manifest.dropTrashRecord(id);
65
+ }
66
+ }, consts.max_jobs);
55
67
  }
56
68
  //# sourceMappingURL=mammoth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mammoth.js","sourceRoot":"","sources":["../../s/core/mammoth.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,GAAG,EAAE,GAAG,EAAC,MAAM,WAAW,CAAA;AAClC,OAAO,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAA;AAE9C,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAA;AAG7C,MAAM,OAAO,OAAO;IACnB,MAAM,CAAA;IACN,QAAQ,CAAA;IAER,YAAY,KAAiB,EAAE,OAAgB;QAC9C,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAU;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC7B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAU;QACpB,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QACvC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAU;QACpB,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QACvC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAU;QACtB,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QACtC,IAAI,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YAC3B,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAC/B,CAAC;IACF,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAoC;QAC/C,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;QACrB,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAA;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAA;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAE9B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YACpC,MAAM,MAAM,CAAC,KAAK,CAAC,KAAgC,CAAC,CAAA;YACpD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC;QAED,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;QACpB,MAAM,IAAI,CAAA;QACV,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;QAC3C,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACvB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QAC/B,OAAO,IAAI,CAAA;IACZ,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAAU;QAC1B,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAS,IAAI,CAAC,CAAA;IACrC,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAU;QAC3B,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,2BAA2B,IAAI,GAAG,CAAC,CAAA;IAC5E,CAAC;IAED,KAAK,CAAA,CAAE,IAAI;QACV,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAA;IAC1B,CAAC;CACD"}
1
+ {"version":3,"file":"mammoth.js","sourceRoot":"","sources":["../../s/core/mammoth.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,EAAE,EAAC,MAAM,UAAU,CAAA;AAC3B,OAAO,EAAC,IAAI,EAAE,KAAK,EAAC,MAAM,WAAW,CAAA;AAErC,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAA;AAClC,OAAO,EAAC,IAAI,EAAC,MAAM,iBAAiB,CAAA;AAEpC,OAAO,EAAC,QAAQ,EAAC,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAA;AAE/C,mEAAmE;AACnE,MAAM,OAAO,OAAO;IACnB,OAAO,CAAA;IACP,SAAS,CAAA;IACT,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAElC,YAAY,MAAM,GAAW,IAAI,YAAY,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE;QAC7D,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,IAAI,CAAC,SAAS,GAAG,IAAI,QAAQ,CAAC,EAAE,CAAC,CAAA;IAClC,CAAC;IAED,KAAK,CAAA,CAAE,MAAM;QACZ,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAA;IAC/B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAU;QACnB,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAU;QACpB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IACrC,CAAC;IAED,KAAK,CAAC,KAAK;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAA;IACjC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAU;QACpB,MAAM,EAAC,EAAE,EAAC,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QAChD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC7B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAU;QACtB,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,IAAG,EAAE;YAC/B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YAC/C,IAAI,IAAI;gBACP,MAAM,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QACnD,CAAC,CAAC,CAAA;QACF,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAA;IACtB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAoC;QAC/C,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;QACrB,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAC/B,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAA;YACvD,MAAM,EAAC,IAAI,EAAE,IAAI,EAAC,GAAG,QAAQ,CAAA;YAC7B,MAAM,IAAI,GAAG,EAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,EAAC,CAAA;YAC1C,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;YAC9D,OAAO,QAAQ,CAAC,IAAI,CAAA;QACrB,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACd,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC,CAAA;YACvC,MAAM,KAAK,CAAA;QACZ,CAAC;gBACO,CAAC;YACR,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAA;QACpE,CAAC;IACF,CAAC;IAED,QAAQ,GAAG,KAAK,CAAC,KAAK,IAAG,EAAE;QAC1B,IAAI,KAAK,EAAE,MAAM,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE;YACvD,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC,CAAA;QAExC,IAAI,KAAK,EAAE,MAAM,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,CAAC;YACtD,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YAC7B,MAAM,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC,CAAA;QACzC,CAAC;IACF,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;CACnB"}
@@ -1,8 +1,7 @@
1
- import { Iceberg, Id } from "./types.js";
2
- export declare class IcebergMemory implements Iceberg {
1
+ import { Bucket, Id } from "./types.js";
2
+ export declare class MemoryBucket implements Bucket {
3
3
  #private;
4
4
  has(id: Id): Promise<boolean>;
5
- size(id: Id): Promise<number>;
6
5
  delete(id: Id): Promise<void>;
7
6
  read(id: Id): Promise<Blob>;
8
7
  write(id: Id, readable: ReadableStream<Uint8Array>): Promise<void>;
@@ -1,13 +1,10 @@
1
1
  import { bytes, got, nap } from "@e280/stz";
2
2
  import { relaxer } from "./utils/relaxer.js";
3
- export class IcebergMemory {
3
+ export class MemoryBucket {
4
4
  #map = new Map();
5
5
  async has(id) {
6
6
  return this.#map.has(id);
7
7
  }
8
- async size(id) {
9
- return got(this.#map.get(id)).byteLength;
10
- }
11
8
  async delete(id) {
12
9
  this.#map.delete(id);
13
10
  }
@@ -26,4 +23,4 @@ export class IcebergMemory {
26
23
  this.#map.set(id, payload);
27
24
  }
28
25
  }
29
- //# sourceMappingURL=iceberg-memory.js.map
26
+ //# sourceMappingURL=memory-bucket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-bucket.js","sourceRoot":"","sources":["../../s/core/memory-bucket.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAC,MAAM,WAAW,CAAA;AAEzC,OAAO,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAA;AAE1C,MAAM,OAAO,YAAY;IACxB,IAAI,GAAG,IAAI,GAAG,EAAsB,CAAA;IAEpC,KAAK,CAAC,GAAG,CAAC,EAAM;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACzB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAM;QAClB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACrB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAM;QAChB,OAAO,IAAI,IAAI,CACd,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAA4B,CAAC,EACnD,EAAC,IAAI,EAAE,0BAA0B,EAAC,CAClC,CAAA;IACF,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,EAAM,EAAE,QAAoC;QACvD,MAAM,KAAK,GAAG,OAAO,EAAE,CAAA;QACvB,MAAM,KAAK,GAAiB,EAAE,CAAA;QAE9B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YACpC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACjB,IAAI,KAAK,EAAE;gBAAE,MAAM,GAAG,EAAE,CAAA;QACzB,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACnC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IAC3B,CAAC;CACD"}
@@ -0,0 +1 @@
1
+ export declare function streamify(bytes: Uint8Array, chunkSize?: number): ReadableStream<Uint8Array<ArrayBufferLike>>;
@@ -0,0 +1,15 @@
1
+ export function streamify(bytes, chunkSize = 64 * 1024) {
2
+ let offset = 0;
3
+ return new ReadableStream({
4
+ pull(controller) {
5
+ if (offset >= bytes.length) {
6
+ controller.close();
7
+ return;
8
+ }
9
+ const end = Math.min(offset + chunkSize, bytes.length);
10
+ controller.enqueue(bytes.subarray(offset, end));
11
+ offset = end;
12
+ },
13
+ });
14
+ }
15
+ //# sourceMappingURL=streamify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamify.js","sourceRoot":"","sources":["../../s/core/streamify.ts"],"names":[],"mappings":"AACA,MAAM,UAAU,SAAS,CAAC,KAAiB,EAAE,SAAS,GAAG,EAAE,GAAG,IAAI;IACjE,IAAI,MAAM,GAAG,CAAC,CAAA;IAEd,OAAO,IAAI,cAAc,CAAa;QACrC,IAAI,CAAC,UAAU;YACd,IAAI,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBAC5B,UAAU,CAAC,KAAK,EAAE,CAAA;gBAClB,OAAM;YACP,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;YACtD,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;YAC/C,MAAM,GAAG,GAAG,CAAA;QACb,CAAC;KACD,CAAC,CAAA;AACH,CAAC"}
package/x/core/types.d.ts CHANGED
@@ -1,17 +1,35 @@
1
1
  export type Hash = string;
2
2
  export type Id = string;
3
- export type Iceberg = {
3
+ /** file blob store. */
4
+ export type Bucket = {
4
5
  has(id: Id): Promise<boolean>;
5
- size(id: Id): Promise<number>;
6
6
  delete(id: Id): Promise<void>;
7
7
  read(id: Id): Promise<Blob>;
8
8
  write(id: Id, readable: ReadableStream<Uint8Array>): Promise<void>;
9
9
  };
10
- export type Glacier = {
11
- has(hash: Hash): Promise<boolean>;
12
- size(hash: Hash): Promise<number>;
13
- read(hash: Hash): Promise<Blob>;
14
- delete(hash: Hash): Promise<void>;
15
- write(readable: ReadableStream<Uint8Array>): Promise<Hash>;
16
- keys(): AsyncIterable<Hash>;
10
+ /** report about a file */
11
+ export type Analysis = {
12
+ /** blake3 hash of the file's contents */
13
+ hash: Hash;
14
+ /** filesize in bytes */
15
+ size: number;
16
+ };
17
+ /** metadata for a single file. */
18
+ export type Info = {
19
+ /** bucket id for this file's data. */
20
+ id: Id;
21
+ /** filesize in bytes. */
22
+ size: number;
23
+ /** when this file was added to the datalake. */
24
+ added: number;
25
+ };
26
+ /** statistics for the whole datalake. */
27
+ export type Stats = {
28
+ /** total number of bytes in the whole datalake. */
29
+ size: number;
30
+ /** total number of files in the datalake. */
31
+ count: number;
32
+ };
33
+ export type Wip = {
34
+ created: number;
17
35
  };
@@ -0,0 +1,2 @@
1
+ import { Wip } from "../types.js";
2
+ export declare function isExpired({ created }: Wip): boolean;
@@ -0,0 +1,7 @@
1
+ import { time } from "@e280/stz";
2
+ import { consts } from "../consts.js";
3
+ export function isExpired({ created }) {
4
+ const since = Date.now() - created;
5
+ return since > time.days(consts.expiry_time);
6
+ }
7
+ //# sourceMappingURL=is-expired.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-expired.js","sourceRoot":"","sources":["../../../s/core/utils/is-expired.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAE9B,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAA;AAEnC,MAAM,UAAU,SAAS,CAAC,EAAC,OAAO,EAAM;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAA;IAClC,OAAO,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;AAC7C,CAAC"}