@krak-stack/registry 0.1.9 → 0.1.11

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.
@@ -0,0 +1,119 @@
1
+ // ../../src/services/file-extraction/index.ts
2
+ import { extractBatch, ExtractInputKind, OutputFormat } from "@xberg-io/xberg";
3
+ import { Context, Effect, Layer, Semaphore } from "effect";
4
+
5
+ // ../../src/services/file-extraction/schema.ts
6
+ import { Schema } from "effect";
7
+ var FileExtractedTextSchema = Schema.Struct({
8
+ content: Schema.String,
9
+ contentByteSize: Schema.Int,
10
+ truncated: Schema.Boolean
11
+ }).annotate({ identifier: "FileExtractedText" });
12
+
13
+ class FileExtractionFailed extends Schema.TaggedErrorClass()("FileExtractionFailed", { message: Schema.String }) {
14
+ }
15
+
16
+ // ../../src/services/file-extraction/index.ts
17
+ import { OutputFormat as OutputFormat2 } from "@xberg-io/xberg";
18
+ var defaultFileExtractionOptions = {
19
+ maxInputBytes: 20 * 1024 * 1024,
20
+ maxOutputBytes: 512 * 1024,
21
+ maxConcurrentExtractions: 2,
22
+ timeoutSeconds: 30
23
+ };
24
+ var truncateUtf8 = (content, maxBytes) => {
25
+ const bytes = new TextEncoder().encode(content);
26
+ if (bytes.byteLength <= maxBytes) {
27
+ return { content, byteSize: bytes.byteLength };
28
+ }
29
+ let end = maxBytes;
30
+ while (end > 0 && (bytes[end] & 192) === 128)
31
+ end -= 1;
32
+ return {
33
+ content: new TextDecoder().decode(bytes.slice(0, end)),
34
+ byteSize: end
35
+ };
36
+ };
37
+ var limitText = (content, maxBytes) => {
38
+ const normalized = content.replace(/\r\n?/g, `
39
+ `).trim();
40
+ const originalByteSize = new TextEncoder().encode(normalized).byteLength;
41
+ const bounded = truncateUtf8(normalized, maxBytes);
42
+ return {
43
+ content: bounded.content,
44
+ contentByteSize: bounded.byteSize,
45
+ truncated: bounded.byteSize !== originalByteSize
46
+ };
47
+ };
48
+ var make = (options) => Effect.gen(function* () {
49
+ const semaphore = yield* Semaphore.make(options.maxConcurrentExtractions);
50
+ const extract = Effect.fn("FileExtractionService.extract")(function* ({
51
+ bytes,
52
+ filename,
53
+ mimeType,
54
+ outputFormat
55
+ }) {
56
+ if (bytes.byteLength > options.maxInputBytes) {
57
+ return yield* new FileExtractionFailed({
58
+ message: "Document exceeds the extraction size limit"
59
+ });
60
+ }
61
+ const output = yield* semaphore.withPermit(Effect.tryPromise({
62
+ try: () => extractBatch([
63
+ {
64
+ kind: ExtractInputKind.Bytes,
65
+ bytes,
66
+ filename,
67
+ mimeType,
68
+ config: { timeoutSecs: options.timeoutSeconds }
69
+ }
70
+ ], {
71
+ outputFormat,
72
+ extractionTimeoutSecs: options.timeoutSeconds,
73
+ maxConcurrentExtractions: 1,
74
+ maxEmbeddedFileBytes: 10 * 1024 * 1024,
75
+ securityLimits: {
76
+ maxArchiveSize: 50 * 1024 * 1024,
77
+ maxCompressionRatio: 100,
78
+ maxFilesInArchive: 1000,
79
+ maxNestingDepth: 50,
80
+ maxEntityLength: 1024 * 1024,
81
+ maxContentSize: 2 * 1024 * 1024,
82
+ maxIterations: 1e6,
83
+ maxXmlDepth: 50,
84
+ maxTableCells: 1e5
85
+ },
86
+ useCache: false
87
+ }),
88
+ catch: (cause) => new FileExtractionFailed({
89
+ message: cause instanceof Error ? cause.message : "Document extraction failed"
90
+ })
91
+ }));
92
+ const result = output.results?.[0];
93
+ if (!result?.content) {
94
+ return yield* new FileExtractionFailed({
95
+ message: output.errors?.[0]?.message ?? "Document extraction returned no readable content"
96
+ });
97
+ }
98
+ return limitText(result.content, options.maxOutputBytes);
99
+ });
100
+ return {
101
+ extract,
102
+ markdown: Effect.fn("FileExtractionService.markdown")((input) => extract({ ...input, outputFormat: OutputFormat.Markdown })),
103
+ text: Effect.fn("FileExtractionService.text")((input) => extract({ ...input, outputFormat: OutputFormat.Plain })),
104
+ html: Effect.fn("FileExtractionService.html")((input) => extract({ ...input, outputFormat: OutputFormat.Html }))
105
+ };
106
+ });
107
+
108
+ class FileExtractionService extends Context.Service()("FileExtractionService", { make: make(defaultFileExtractionOptions) }) {
109
+ static layer = Layer.effect(this, this.make);
110
+ static layerWith = (options) => Layer.effect(this, make({ ...defaultFileExtractionOptions, ...options }));
111
+ static testLayer = (service) => Layer.succeed(this, service);
112
+ }
113
+ export {
114
+ defaultFileExtractionOptions,
115
+ OutputFormat2 as OutputFormat,
116
+ FileExtractionService,
117
+ FileExtractionFailed,
118
+ FileExtractedTextSchema
119
+ };
@@ -0,0 +1,13 @@
1
+ import { Schema } from "effect";
2
+ export declare const FileExtractedTextSchema: Schema.Struct<{
3
+ readonly content: Schema.String;
4
+ readonly contentByteSize: Schema.Int;
5
+ readonly truncated: Schema.Boolean;
6
+ }>;
7
+ export type FileExtractedText = typeof FileExtractedTextSchema.Type;
8
+ declare const FileExtractionFailed_base: Schema.Class<FileExtractionFailed, Schema.TaggedStruct<"FileExtractionFailed", {
9
+ readonly message: Schema.String;
10
+ }>, import("effect/Cause").YieldableError>;
11
+ export declare class FileExtractionFailed extends FileExtractionFailed_base {
12
+ }
13
+ export {};
@@ -0,0 +1,14 @@
1
+ // ../../src/services/file-extraction/schema.ts
2
+ import { Schema } from "effect";
3
+ var FileExtractedTextSchema = Schema.Struct({
4
+ content: Schema.String,
5
+ contentByteSize: Schema.Int,
6
+ truncated: Schema.Boolean
7
+ }).annotate({ identifier: "FileExtractedText" });
8
+
9
+ class FileExtractionFailed extends Schema.TaggedErrorClass()("FileExtractionFailed", { message: Schema.String }) {
10
+ }
11
+ export {
12
+ FileExtractionFailed,
13
+ FileExtractedTextSchema
14
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krak-stack/registry",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Tree-shakable KrakStack components and Effect services.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -172,6 +172,14 @@
172
172
  "types": "./dist/services/s3/schema.d.ts",
173
173
  "import": "./dist/services/s3/schema.js"
174
174
  },
175
+ "./service-file-extraction": {
176
+ "types": "./dist/services/file-extraction/index.d.ts",
177
+ "import": "./dist/services/file-extraction/index.js"
178
+ },
179
+ "./service-file-extraction/schema": {
180
+ "types": "./dist/services/file-extraction/schema.d.ts",
181
+ "import": "./dist/services/file-extraction/schema.js"
182
+ },
175
183
  "./tailwind.css": "./tailwind.css",
176
184
  "./package.json": "./package.json"
177
185
  },
@@ -198,8 +206,9 @@
198
206
  "@streamdown/code": "^1.1.1",
199
207
  "@tanstack/react-form": "^1.33.0",
200
208
  "@tanstack/react-router": "^1.170.15",
201
- "@tanstack/react-table": "^8.21.3",
209
+ "@tanstack/react-table": "^9.1.2",
202
210
  "@tanstack/react-virtual": "^3.14.5",
211
+ "@xberg-io/xberg": "1.0.14",
203
212
  "class-variance-authority": "^0.7.1",
204
213
  "clsx": "^2.1.1",
205
214
  "cmdk": "^1.1.1",
@@ -261,6 +270,9 @@
261
270
  "@tanstack/react-virtual": {
262
271
  "optional": true
263
272
  },
273
+ "@xberg-io/xberg": {
274
+ "optional": true
275
+ },
264
276
  "shiki": {
265
277
  "optional": true
266
278
  },