@tstdl/base 0.92.150 → 0.92.152

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 (43) hide show
  1. package/ai/ai-file.service.d.ts +3 -1
  2. package/ai/ai-file.service.js +63 -17
  3. package/ai/types.d.ts +13 -0
  4. package/ai/types.js +7 -0
  5. package/api/client/client.js +11 -0
  6. package/api/server/gateway.js +4 -2
  7. package/api/types.d.ts +4 -2
  8. package/data-structures/array-dictionary.d.ts +1 -0
  9. package/data-structures/array-dictionary.js +13 -18
  10. package/data-structures/array-list.js +1 -1
  11. package/data-structures/cache.js +7 -3
  12. package/data-structures/dictionary.js +1 -1
  13. package/data-structures/distinct-collection.d.ts +4 -0
  14. package/data-structures/distinct-collection.js +1 -1
  15. package/data-structures/iterable-weak-map.d.ts +2 -2
  16. package/data-structures/iterable-weak-map.js +3 -3
  17. package/data-structures/set-collection.js +1 -0
  18. package/data-structures/sorted-array-list.js +1 -1
  19. package/data-structures/weak-ref-map.d.ts +2 -2
  20. package/data-structures/weak-ref-map.js +3 -3
  21. package/document-management/api/document-management.api.d.ts +19 -13
  22. package/document-management/api/document-management.api.js +3 -3
  23. package/document-management/server/api/document-management.api.d.ts +2 -2
  24. package/document-management/server/api/document-management.api.js +2 -47
  25. package/document-management/server/services/document-management.service.d.ts +1 -1
  26. package/document-management/service-models/document.service-model.d.ts +6 -6
  27. package/dom/observation/resize-observer.d.ts +1 -1
  28. package/dom/observation/resize-observer.js +1 -1
  29. package/image-service/imgproxy/imgproxy-image-service.d.ts +1 -2
  30. package/image-service/imgproxy/imgproxy-image-service.js +11 -11
  31. package/orm/decorators.d.ts +1 -1
  32. package/package.json +4 -3
  33. package/sse/data-stream-source.d.ts +18 -0
  34. package/sse/data-stream-source.js +66 -0
  35. package/sse/data-stream.d.ts +8 -0
  36. package/sse/data-stream.js +15 -0
  37. package/sse/index.d.ts +2 -0
  38. package/sse/index.js +2 -0
  39. package/utils/binary.d.ts +3 -4
  40. package/utils/binary.js +5 -9
  41. package/utils/math.js +2 -3
  42. package/utils/stream/stream-reader.d.ts +1 -1
  43. package/utils/stream/stream-reader.js +1 -1
@@ -1,6 +1,6 @@
1
1
  import type { Resolvable, resolveArgumentType } from '../injector/interfaces.js';
2
2
  import type { AiServiceOptions } from './ai.service.js';
3
- import type { FileContentPart, FileInput } from './types.js';
3
+ import { type FileContentPart, type FileInput } from './types.js';
4
4
  /**
5
5
  * Options for {@link AiFileService}.
6
6
  */
@@ -48,6 +48,8 @@ export declare class AiFileService implements Resolvable<AiFileServiceArgument>
48
48
  private getFile;
49
49
  private getFiles;
50
50
  private uploadFile;
51
+ private uploadFileVertex;
52
+ private uploadFileGenAi;
51
53
  private getBucket;
52
54
  private waitForFileActive;
53
55
  private waitForFilesActive;
@@ -4,7 +4,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { openAsBlob } from 'node:fs';
7
+ import { createReadStream } from 'node:fs';
8
+ import { stat } from 'node:fs/promises';
8
9
  import { Readable } from 'node:stream';
9
10
  import { ReadableStream as NodeReadableStream } from 'node:stream/web';
10
11
  import { Storage } from '@google-cloud/storage';
@@ -18,7 +19,9 @@ import { Logger } from '../logger/logger.js';
18
19
  import { createArray } from '../utils/array/array.js';
19
20
  import { backoffGenerator } from '../utils/backoff.js';
20
21
  import { formatBytes } from '../utils/format.js';
22
+ import { readBinaryStream } from '../utils/stream/stream-reader.js';
21
23
  import { assertDefinedPass, isBlob, isDefined, isUndefined } from '../utils/type-guards.js';
24
+ import { isPathFileInput } from './types.js';
22
25
  /**
23
26
  * Manages file uploads and state for use with AI models.
24
27
  * Handles both Google Generative AI File API and Google Cloud Storage for Vertex AI.
@@ -103,24 +106,67 @@ let AiFileService = class AiFileService {
103
106
  return files;
104
107
  }
105
108
  async uploadFile(fileInput, id) {
106
- const inputIsBlob = isBlob(fileInput);
107
- const blob = inputIsBlob
108
- ? fileInput
109
- : await openAsBlob(fileInput.path, { type: fileInput.mimeType });
110
- this.#logger.verbose(`Uploading file "${id}" (${formatBytes(blob.size)})...`);
111
109
  if (isDefined(this.#storage)) {
112
- const bucket = await this.getBucket();
113
- const file = bucket.file(id);
114
- const blobStream = Readable.fromWeb(blob.stream());
115
- await file.save(blobStream, { contentType: blob.type, resumable: false });
116
- return {
117
- id,
118
- name: id, // For Vertex, name is the GCS object id
119
- uri: `gs://${bucket.name}/${file.name}`,
120
- mimeType: blob.type,
121
- };
110
+ return await this.uploadFileVertex(fileInput, id);
122
111
  }
123
- const response = await this.#genAI.files.upload({ file: blob, config: { mimeType: blob.type } });
112
+ return await this.uploadFileGenAi(fileInput, id);
113
+ }
114
+ async uploadFileVertex(fileInput, id) {
115
+ const bucket = await this.getBucket();
116
+ const file = bucket.file(id);
117
+ let stream;
118
+ let contentType;
119
+ let size;
120
+ if (isBlob(fileInput)) {
121
+ stream = Readable.fromWeb(fileInput.stream());
122
+ contentType = fileInput.type;
123
+ size = fileInput.size;
124
+ }
125
+ else if (isPathFileInput(fileInput)) {
126
+ const stats = await stat(fileInput.path);
127
+ stream = createReadStream(fileInput.path);
128
+ contentType = fileInput.mimeType;
129
+ size = stats.size;
130
+ }
131
+ else {
132
+ stream = Readable.fromWeb(fileInput.stream);
133
+ contentType = fileInput.mimeType;
134
+ size = fileInput.size;
135
+ }
136
+ this.#logger.verbose(`Uploading file "${id}"${isDefined(size) ? ` (${formatBytes(size)})` : ''}...`);
137
+ await file.save(stream, { contentType, resumable: false });
138
+ return {
139
+ id,
140
+ name: id,
141
+ uri: `gs://${bucket.name}/${file.name}`,
142
+ mimeType: contentType,
143
+ };
144
+ }
145
+ async uploadFileGenAi(fileInput, id) {
146
+ let uploadData;
147
+ let contentType;
148
+ let size;
149
+ if (isBlob(fileInput)) {
150
+ uploadData = fileInput;
151
+ contentType = fileInput.type;
152
+ size = fileInput.size;
153
+ }
154
+ else if (isPathFileInput(fileInput)) {
155
+ const fileState = await stat(fileInput.path);
156
+ uploadData = fileInput.path;
157
+ contentType = fileInput.mimeType;
158
+ size = fileState.size;
159
+ }
160
+ else {
161
+ const fileBytes = await readBinaryStream(fileInput.stream);
162
+ const blob = new Blob([fileBytes], { type: fileInput.mimeType });
163
+ uploadData = blob;
164
+ contentType = blob.type;
165
+ size = blob.size;
166
+ }
167
+ this.#logger.verbose(`Uploading file "${id}" (${formatBytes(size)}) via GenAI API...`);
168
+ // upload supports paths and blobs, but not streams (yet)
169
+ const response = await this.#genAI.files.upload({ file: uploadData, config: { mimeType: contentType } });
124
170
  return {
125
171
  id,
126
172
  name: assertDefinedPass(response.name, 'Missing file name'),
package/ai/types.d.ts CHANGED
@@ -8,6 +8,10 @@ import type { ResolvedValueOrProvider, ValueOrAsyncProvider } from '../utils/val
8
8
  export type FileInput = {
9
9
  path: string;
10
10
  mimeType: string;
11
+ } | {
12
+ stream: ReadableStream<Uint8Array>;
13
+ mimeType: string;
14
+ size?: number;
11
15
  } | Blob;
12
16
  /**
13
17
  * A record of named function declarations, where each key is the function name.
@@ -202,3 +206,12 @@ export declare function defineFunction<P extends Record, T extends SchemaFunctio
202
206
  * @returns `true` if the declaration has a `handler` property, `false` otherwise.
203
207
  */
204
208
  export declare function isSchemaFunctionDeclarationWithHandler(declaration: SchemaFunctionDeclaration): declaration is SchemaFunctionDeclarationWithHandler;
209
+ export declare function isPathFileInput(input: FileInput): input is {
210
+ path: string;
211
+ mimeType: string;
212
+ };
213
+ export declare function isStreamFileInput(input: FileInput): input is {
214
+ stream: ReadableStream<Uint8Array>;
215
+ mimeType: string;
216
+ size?: number;
217
+ };
package/ai/types.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { hasOwnProperty } from '../utils/object/object.js';
2
+ import { isBlob } from '../utils/type-guards.js';
2
3
  /**
3
4
  * A helper function to define a set of function declarations with strong type inference.
4
5
  * @param declarations A record of function declarations.
@@ -24,3 +25,9 @@ export function defineFunction(declaration) {
24
25
  export function isSchemaFunctionDeclarationWithHandler(declaration) {
25
26
  return hasOwnProperty(declaration, 'handler');
26
27
  }
28
+ export function isPathFileInput(input) {
29
+ return !isBlob(input) && hasOwnProperty(input, 'path');
30
+ }
31
+ export function isStreamFileInput(input) {
32
+ return !isBlob(input) && hasOwnProperty(input, 'stream');
33
+ }
@@ -4,6 +4,7 @@ import { inject } from '../../injector/inject.js';
4
4
  import { Injector } from '../../injector/injector.js';
5
5
  import { resolveArgumentType } from '../../injector/interfaces.js';
6
6
  import { Schema } from '../../schema/index.js';
7
+ import { DataStream } from '../../sse/data-stream.js';
7
8
  import { ServerSentEvents } from '../../sse/server-sent-events.js';
8
9
  import { toArray } from '../../utils/array/array.js';
9
10
  import { copyObjectProperties, objectEntries } from '../../utils/object/object.js';
@@ -74,6 +75,12 @@ export function compileClient(definition, options = defaultOptions) {
74
75
  }
75
76
  return getServerSentEvents(this[httpClientSymbol].options.baseUrl, resource, endpoint, parameters);
76
77
  }
78
+ if (endpoint.result == DataStream) {
79
+ if (isDefined(requestBody)) {
80
+ throw new Error('Body not supported for DataStream.');
81
+ }
82
+ return getDataStream(this[httpClientSymbol].options.baseUrl, resource, endpoint, parameters);
83
+ }
77
84
  if (context.endpoint.data?.[bustCacheToken] == true) {
78
85
  context[bustCacheToken] = true;
79
86
  }
@@ -126,6 +133,10 @@ async function getResponseBody(response, schema) {
126
133
  : undefined;
127
134
  return Schema.parse(schema, body, { mask: true });
128
135
  }
136
+ function getDataStream(baseUrl, resource, endpoint, parameters) {
137
+ const sse = getServerSentEvents(baseUrl, resource, endpoint, parameters);
138
+ return DataStream.parse(sse);
139
+ }
129
140
  function getServerSentEvents(baseUrl, resource, endpoint, parameters) {
130
141
  const { parsedUrl, parametersRest } = buildUrl(resource, parameters, { arraySeparator: ',' });
131
142
  const url = new URL(parsedUrl, baseUrl);
@@ -18,6 +18,7 @@ import { HttpServerResponse } from '../../http/server/index.js';
18
18
  import { InjectArg, ResolveArg, Singleton, resolveArgumentType } from '../../injector/index.js';
19
19
  import { Logger } from '../../logger/index.js';
20
20
  import { Schema } from '../../schema/index.js';
21
+ import { DataStreamSource } from '../../sse/data-stream-source.js';
21
22
  import { ServerSentEventsSource } from '../../sse/server-sent-events-source.js';
22
23
  import { toArray } from '../../utils/array/array.js';
23
24
  import { composeAsyncMiddleware } from '../../utils/middleware.js';
@@ -192,8 +193,9 @@ let ApiGateway = class ApiGateway {
192
193
  : isBlob(result) ? { stream: result.stream() }
193
194
  : isReadableStream(result) ? { stream: result }
194
195
  : (result instanceof ServerSentEventsSource) ? { events: result }
195
- : (context.endpoint.definition.result == String) ? { text: result }
196
- : { json: result };
196
+ : (result instanceof DataStreamSource) ? { events: result.eventSource }
197
+ : (context.endpoint.definition.result == String) ? { text: result }
198
+ : { json: result };
197
199
  }
198
200
  await next();
199
201
  }
package/api/types.d.ts CHANGED
@@ -1,6 +1,8 @@
1
+ import type { Observable } from 'rxjs';
1
2
  import type { HttpServerRequest, HttpServerResponse } from '../http/server/index.js';
2
3
  import type { HttpMethod } from '../http/types.js';
3
4
  import type { SchemaOutput, SchemaTestable } from '../schema/index.js';
5
+ import type { DataStream } from '../sse/index.js';
4
6
  import type { ServerSentEventsSource } from '../sse/server-sent-events-source.js';
5
7
  import type { ServerSentEvents } from '../sse/server-sent-events.js';
6
8
  import type { NonUndefinable, OneOrMany, Record, ReturnTypeOrT } from '../types/index.js';
@@ -91,8 +93,8 @@ export type ApiEndpointParametersSchema<T extends ApiDefinition, K extends ApiEn
91
93
  export type ApiEndpointBodySchema<T extends ApiDefinition, K extends ApiEndpointKeys<T>> = NonUndefinable<ApiEndpoint<T, K>['body']>;
92
94
  export type ApiEndpointResultSchema<T extends ApiDefinition, K extends ApiEndpointKeys<T>> = NonUndefinable<ApiEndpoint<T, K>['result']>;
93
95
  export type ApiBinaryType = typeof Uint8Array | typeof Blob | typeof ReadableStream<any>;
94
- export type ApiInputType<T extends SchemaTestable> = T extends ApiBinaryType ? InstanceType<ApiBinaryType> : T extends typeof ServerSentEvents ? ServerSentEventsSource : T extends SchemaTestable ? SchemaOutput<T> : never;
95
- export type ApiOutputType<T extends SchemaTestable> = T extends typeof ReadableStream ? ReadableStream<Uint8Array> : T extends SchemaTestable ? SchemaOutput<T> : never;
96
+ export type ApiInputType<T extends SchemaTestable> = T extends ApiBinaryType ? InstanceType<ApiBinaryType> : T extends typeof ServerSentEvents ? ServerSentEventsSource : T extends typeof DataStream<infer U> ? AsyncIterable<U> : T extends SchemaTestable ? SchemaOutput<T> : never;
97
+ export type ApiOutputType<T extends SchemaTestable> = T extends typeof ReadableStream ? ReadableStream<Uint8Array> : T extends typeof DataStream<infer U> ? Observable<U> : T extends SchemaTestable ? SchemaOutput<T> : never;
96
98
  export type ApiParameters<T extends ApiDefinition, K extends ApiEndpointKeys<T>> = ApiInputType<ApiEndpointParametersSchema<T, K>>;
97
99
  export type ApiClientBody<T extends ApiDefinition, K extends ApiEndpointKeys<T>> = ApiInputType<ApiEndpointBodySchema<T, K>>;
98
100
  export type ApiServerBody<T extends ApiDefinition, K extends ApiEndpointKeys<T>> = ApiOutputType<ApiEndpointBodySchema<T, K>>;
@@ -16,5 +16,6 @@ export declare class ArrayDictionary<K, V> extends Dictionary<K, V, ArrayDiction
16
16
  keys(): MapIterator<K>;
17
17
  values(): MapIterator<V>;
18
18
  protected _clear(): void;
19
+ private _setWithoutUpdate;
19
20
  private updateSize;
20
21
  }
@@ -10,7 +10,6 @@ export class ArrayDictionary extends Dictionary {
10
10
  this.valueArray = [];
11
11
  if (isDefined(items)) {
12
12
  this.addMany(items);
13
- this.updateSize();
14
13
  }
15
14
  }
16
15
  has(key) {
@@ -24,14 +23,7 @@ export class ArrayDictionary extends Dictionary {
24
23
  return this.valueArray[index];
25
24
  }
26
25
  set(key, value) {
27
- const index = this.keyArray.indexOf(key);
28
- if (index == -1) {
29
- this.keyArray.push(key);
30
- this.valueArray.push(value);
31
- }
32
- else {
33
- this.valueArray[index] = value;
34
- }
26
+ this._setWithoutUpdate(key, value);
35
27
  this.updateSize();
36
28
  }
37
29
  delete(key) {
@@ -58,14 +50,7 @@ export class ArrayDictionary extends Dictionary {
58
50
  }
59
51
  addMany(items) {
60
52
  for (const [key, value] of items) {
61
- const index = this.keyArray.indexOf(key);
62
- if (index == -1) {
63
- this.keyArray.push(key);
64
- this.valueArray.push(value);
65
- }
66
- else {
67
- this.valueArray[index] = value;
68
- }
53
+ this._setWithoutUpdate(key, value);
69
54
  }
70
55
  this.updateSize();
71
56
  }
@@ -91,7 +76,17 @@ export class ArrayDictionary extends Dictionary {
91
76
  this.keyArray = [];
92
77
  this.valueArray = [];
93
78
  }
79
+ _setWithoutUpdate(key, value) {
80
+ const index = this.keyArray.indexOf(key);
81
+ if (index == -1) {
82
+ this.keyArray.push(key);
83
+ this.valueArray.push(value);
84
+ }
85
+ else {
86
+ this.valueArray[index] = value;
87
+ }
88
+ }
94
89
  updateSize() {
95
- this.setSize(this.keyArray.length / 2);
90
+ this.setSize(this.keyArray.length);
96
91
  }
97
92
  }
@@ -100,7 +100,7 @@ export class ArrayList extends List {
100
100
  }
101
101
  }
102
102
  _clear() {
103
- this.backingArray.splice(0, this.backingArray.length);
103
+ this.backingArray.length = 0;
104
104
  }
105
105
  updateSize() {
106
106
  this.setSize(this.backingArray.length);
@@ -5,12 +5,16 @@ export class Cache {
5
5
  return this._capacity;
6
6
  }
7
7
  set capacity(capacity) {
8
- this.removeEntries(this._capacity - capacity);
8
+ if (capacity < 0) {
9
+ throw new Error('Capacity must be positive.');
10
+ }
11
+ const itemsToRemove = Math.max(0, this.cache.size - capacity);
12
+ this.removeEntries(itemsToRemove);
9
13
  this._capacity = capacity;
10
14
  }
11
15
  constructor(capacity) {
12
- this._capacity = capacity;
13
16
  this.cache = new Map();
17
+ this.capacity = capacity;
14
18
  }
15
19
  get(key) {
16
20
  if (!this.cache.has(key)) {
@@ -29,7 +33,7 @@ export class Cache {
29
33
  this.cache.set(key, value);
30
34
  }
31
35
  delete(key) {
32
- this.delete(key);
36
+ this.cache.delete(key);
33
37
  }
34
38
  removeEntries(count) {
35
39
  if (count <= 0) {
@@ -6,7 +6,7 @@ export class Dictionary extends Collection {
6
6
  }
7
7
  /** Returns an adapter that has the same interface as {@link Map}. No copying of data involved. */
8
8
  asMap() {
9
- return new DictionaryAdapter(this); // eslint-disable-line @typescript-eslint/no-use-before-define
9
+ return new DictionaryAdapter(this);
10
10
  }
11
11
  }
12
12
  export class DictionaryAdapter {
@@ -6,6 +6,10 @@ export declare abstract class DistinctCollection<T, TThis extends DistinctCollec
6
6
  asSet(): Set<T>;
7
7
  abstract has(value: T): boolean;
8
8
  abstract delete(value: T): boolean;
9
+ /**
10
+ * @internal
11
+ * Do not use directly. For internal adapter optimization.
12
+ */
9
13
  protected abstract _getBackingSet(): ReadonlySet<T> | undefined;
10
14
  }
11
15
  export declare class SetAdapter<T> implements Set<T> {
@@ -14,7 +14,7 @@ export class SetAdapter {
14
14
  collection;
15
15
  [Symbol.toStringTag] = 'SetAdapter';
16
16
  get fastestBackingSet() {
17
- return this.collection._backingSet ?? this.collection.toSet();
17
+ return this.collection._getBackingSet() ?? this.collection.toSet();
18
18
  }
19
19
  get size() {
20
20
  return this.collection.size;
@@ -1,5 +1,5 @@
1
- import { Collection } from './collection.js';
2
- export declare class IterableWeakMap<K extends object, V> extends Collection<[K, V], MapIterator<[K, V]>, IterableWeakMap<K, V>> implements Map<K, V> {
1
+ import { Dictionary } from './dictionary.js';
2
+ export declare class IterableWeakMap<K extends object, V> extends Dictionary<K, V, IterableWeakMap<K, V>> implements Map<K, V> {
3
3
  private weakMap;
4
4
  private refMap;
5
5
  private finalizationRegistry;
@@ -1,9 +1,9 @@
1
+ import { takeUntil } from 'rxjs';
1
2
  import { ObservableFinalizationRegistry } from '../memory/observable-finalization-registry.js';
2
3
  import { drain } from '../utils/iterable-helpers/drain.js';
3
4
  import { isDefined, isUndefined } from '../utils/type-guards.js';
4
- import { takeUntil } from 'rxjs';
5
- import { Collection } from './collection.js';
6
- export class IterableWeakMap extends Collection {
5
+ import { Dictionary } from './dictionary.js';
6
+ export class IterableWeakMap extends Dictionary {
7
7
  weakMap;
8
8
  refMap;
9
9
  finalizationRegistry;
@@ -10,6 +10,7 @@ export class SetCollection extends DistinctCollection {
10
10
  static withBackingSet(set) {
11
11
  const collection = new SetCollection();
12
12
  collection.backingSet = set;
13
+ collection.updateSize();
13
14
  return collection;
14
15
  }
15
16
  includes(item) {
@@ -133,7 +133,7 @@ let SortedArrayList = SortedArrayList_1 = class SortedArrayList extends List {
133
133
  }
134
134
  }
135
135
  _clear() {
136
- this.backingArray.splice(0, this.backingArray.length);
136
+ this.backingArray.length = 0;
137
137
  }
138
138
  updateSize() {
139
139
  this.setSize(this.backingArray.length);
@@ -1,5 +1,5 @@
1
- import { Collection } from './collection.js';
2
- export declare class WeakRefMap<K, V extends object> extends Collection<[K, V], MapIterator<[K, V]>, WeakRefMap<K, V>> implements Map<K, V> {
1
+ import { Dictionary } from './dictionary.js';
2
+ export declare class WeakRefMap<K, V extends object> extends Dictionary<K, V, WeakRefMap<K, V>> implements Map<K, V> {
3
3
  private readonly backingMapProvider;
4
4
  private backingMap;
5
5
  private finalizationRegistry;
@@ -1,8 +1,8 @@
1
+ import { takeUntil } from 'rxjs';
1
2
  import { ObservableFinalizationRegistry } from '../memory/observable-finalization-registry.js';
2
3
  import { isDefined, isUndefined } from '../utils/type-guards.js';
3
- import { takeUntil } from 'rxjs';
4
- import { Collection } from './collection.js';
5
- export class WeakRefMap extends Collection {
4
+ import { Dictionary } from './dictionary.js';
5
+ export class WeakRefMap extends Dictionary {
6
6
  backingMapProvider;
7
7
  backingMap;
8
8
  finalizationRegistry;
@@ -1,5 +1,5 @@
1
1
  import { bustCacheToken } from '../../http/tokens.js';
2
- import { ServerSentEvents } from '../../sse/server-sent-events.js';
2
+ import { DataStream } from '../../sse/index.js';
3
3
  import { Document, DocumentCategory, DocumentRequest, DocumentRequestsTemplate, DocumentRequestTemplate, DocumentType } from '../models/index.js';
4
4
  import { DocumentCategoryView, DocumentManagementData, DocumentRequestsTemplateData } from '../service-models/index.js';
5
5
  export type DocumentManagementApiDefinition = typeof documentManagementApiDefinition;
@@ -21,7 +21,10 @@ export declare const documentManagementApiDefinition: {
21
21
  parameters: import("../../schema/index.js").ObjectSchema<{
22
22
  collectionIds: string | string[];
23
23
  }>;
24
- result: typeof ServerSentEvents;
24
+ result: {
25
+ new (): DataStream<DocumentManagementData>;
26
+ parse<T>(eventSource: import("../../sse/index.js").ServerSentEvents): import("rxjs").Observable<T>;
27
+ };
25
28
  credentials: true;
26
29
  data: {
27
30
  [bustCacheToken]: boolean;
@@ -86,8 +89,8 @@ export declare const documentManagementApiDefinition: {
86
89
  resource: string;
87
90
  method: "POST";
88
91
  parameters: import("../../schema/index.js").ObjectSchema<{
89
- label: string;
90
92
  parentId: import("../../orm/schemas/uuid.js").Uuid | null;
93
+ label: string;
91
94
  metadata?: Partial<{
92
95
  attributes: import("../../orm/types.js").HasDefault<import("../../orm/schemas/json.js").Json<import("../../orm/entity.js").EntityMetadataAttributes>>;
93
96
  }> | undefined;
@@ -125,10 +128,10 @@ export declare const documentManagementApiDefinition: {
125
128
  method: "POST";
126
129
  parameters: import("../../schema/index.js").ObjectSchema<{
127
130
  date?: import("../../orm/types.js").NumericDate | null | undefined;
128
- summary?: string | null | undefined;
129
- title?: string | null | undefined;
130
131
  typeId?: import("../../orm/types.js").Uuid | null | undefined;
132
+ title?: string | null | undefined;
131
133
  subtitle?: string | null | undefined;
134
+ summary?: string | null | undefined;
132
135
  comment?: string | null | undefined;
133
136
  approval?: import("../models/document.model.js").DocumentApproval | undefined;
134
137
  originalFileName?: string | null | undefined;
@@ -177,8 +180,8 @@ export declare const documentManagementApiDefinition: {
177
180
  parameters: import("../../schema/index.js").ObjectSchema<{
178
181
  id: import("../../orm/types.js").IsPrimaryKey<import("../../orm/types.js").HasDefault<import("../../orm/schemas/uuid.js").Uuid>>;
179
182
  description?: string | null | undefined;
180
- label?: string | undefined;
181
183
  tenantId?: string | null | undefined;
184
+ label?: string | undefined;
182
185
  metadata?: Partial<{
183
186
  attributes: import("../../orm/types.js").HasDefault<import("../../orm/schemas/json.js").Json<import("../../orm/entity.js").EntityMetadataAttributes>>;
184
187
  }> | undefined;
@@ -324,8 +327,8 @@ export declare const documentManagementApiDefinition: {
324
327
  parameters: import("../../schema/index.js").ObjectSchema<{
325
328
  id: import("../../orm/types.js").IsPrimaryKey<import("../../orm/types.js").HasDefault<import("../../orm/schemas/uuid.js").Uuid>>;
326
329
  date?: import("../../orm/types.js").NumericDate | null | undefined;
327
- title?: string | null | undefined;
328
330
  typeId?: import("../../orm/types.js").Uuid | null | undefined;
331
+ title?: string | null | undefined;
329
332
  subtitle?: string | null | undefined;
330
333
  comment?: string | null | undefined;
331
334
  properties?: {
@@ -418,7 +421,10 @@ declare const _DocumentManagementApi: import("../../api/client/index.js").ApiCli
418
421
  parameters: import("../../schema/index.js").ObjectSchema<{
419
422
  collectionIds: string | string[];
420
423
  }>;
421
- result: typeof ServerSentEvents;
424
+ result: {
425
+ new (): DataStream<DocumentManagementData>;
426
+ parse<T>(eventSource: import("../../sse/index.js").ServerSentEvents): import("rxjs").Observable<T>;
427
+ };
422
428
  credentials: true;
423
429
  data: {
424
430
  [bustCacheToken]: boolean;
@@ -483,8 +489,8 @@ declare const _DocumentManagementApi: import("../../api/client/index.js").ApiCli
483
489
  resource: string;
484
490
  method: "POST";
485
491
  parameters: import("../../schema/index.js").ObjectSchema<{
486
- label: string;
487
492
  parentId: import("../../orm/schemas/uuid.js").Uuid | null;
493
+ label: string;
488
494
  metadata?: Partial<{
489
495
  attributes: import("../../orm/types.js").HasDefault<import("../../orm/schemas/json.js").Json<import("../../orm/entity.js").EntityMetadataAttributes>>;
490
496
  }> | undefined;
@@ -522,10 +528,10 @@ declare const _DocumentManagementApi: import("../../api/client/index.js").ApiCli
522
528
  method: "POST";
523
529
  parameters: import("../../schema/index.js").ObjectSchema<{
524
530
  date?: import("../../orm/types.js").NumericDate | null | undefined;
525
- summary?: string | null | undefined;
526
- title?: string | null | undefined;
527
531
  typeId?: import("../../orm/types.js").Uuid | null | undefined;
532
+ title?: string | null | undefined;
528
533
  subtitle?: string | null | undefined;
534
+ summary?: string | null | undefined;
529
535
  comment?: string | null | undefined;
530
536
  approval?: import("../models/document.model.js").DocumentApproval | undefined;
531
537
  originalFileName?: string | null | undefined;
@@ -574,8 +580,8 @@ declare const _DocumentManagementApi: import("../../api/client/index.js").ApiCli
574
580
  parameters: import("../../schema/index.js").ObjectSchema<{
575
581
  id: import("../../orm/types.js").IsPrimaryKey<import("../../orm/types.js").HasDefault<import("../../orm/schemas/uuid.js").Uuid>>;
576
582
  description?: string | null | undefined;
577
- label?: string | undefined;
578
583
  tenantId?: string | null | undefined;
584
+ label?: string | undefined;
579
585
  metadata?: Partial<{
580
586
  attributes: import("../../orm/types.js").HasDefault<import("../../orm/schemas/json.js").Json<import("../../orm/entity.js").EntityMetadataAttributes>>;
581
587
  }> | undefined;
@@ -721,8 +727,8 @@ declare const _DocumentManagementApi: import("../../api/client/index.js").ApiCli
721
727
  parameters: import("../../schema/index.js").ObjectSchema<{
722
728
  id: import("../../orm/types.js").IsPrimaryKey<import("../../orm/types.js").HasDefault<import("../../orm/schemas/uuid.js").Uuid>>;
723
729
  date?: import("../../orm/types.js").NumericDate | null | undefined;
724
- title?: string | null | undefined;
725
730
  typeId?: import("../../orm/types.js").Uuid | null | undefined;
731
+ title?: string | null | undefined;
726
732
  subtitle?: string | null | undefined;
727
733
  comment?: string | null | undefined;
728
734
  properties?: {
@@ -8,9 +8,9 @@ import { compileClient } from '../../api/client/index.js';
8
8
  import { defineApi } from '../../api/index.js';
9
9
  import { defaultAccessControlAllowHeaders } from '../../api/utils.js';
10
10
  import { bustCacheToken } from '../../http/tokens.js';
11
- import { ReplaceClass } from '../../injector/decorators.js';
11
+ import { ReplaceClass } from '../../injector/index.js';
12
12
  import { array, boolean, literal, number, object, optional, string } from '../../schema/index.js';
13
- import { ServerSentEvents } from '../../sse/server-sent-events.js';
13
+ import { DataStream } from '../../sse/index.js';
14
14
  import { policy } from '../authorization/index.js';
15
15
  import { Document, DocumentCategory, DocumentRequest, DocumentRequestsTemplate, DocumentRequestTemplate, DocumentType } from '../models/index.js';
16
16
  import { addOrArchiveDocumentToOrFromCollectionParametersSchema, applyDocumentRequestsTemplateParametersSchema, createDocumentCategoryParametersSchema, createDocumentParametersSchema, createDocumentRequestParametersSchema, createDocumentRequestsTemplateParametersSchema, createDocumentRequestTemplateParametersSchema, createDocumentTypeParametersSchema, deleteDocumentRequestParametersSchema, deleteDocumentRequestsTemplateParametersSchema, deleteDocumentRequestTemplateParametersSchema, DocumentCategoryView, DocumentManagementData, DocumentRequestsTemplateData, loadDataParametersSchema, updateDocumentParametersSchema, updateDocumentRequestParametersSchema, updateDocumentRequestsTemplateParametersSchema, updateDocumentRequestTemplateParametersSchema } from '../service-models/index.js';
@@ -28,7 +28,7 @@ export const documentManagementApiDefinition = defineApi({
28
28
  resource: 'data/stream',
29
29
  method: 'GET',
30
30
  parameters: loadDataParametersSchema,
31
- result: ServerSentEvents,
31
+ result: (DataStream),
32
32
  credentials: true,
33
33
  data: {
34
34
  [bustCacheToken]: true,
@@ -1,9 +1,9 @@
1
- import { type ApiController, type ApiRequestContext, type ApiServerResult } from '../../../api/index.js';
1
+ import type { ApiController, ApiRequestContext, ApiServerResult } from '../../../api/index.js';
2
2
  import { type DocumentManagementApiDefinition } from '../../api/index.js';
3
3
  export declare class DocumentManagementApiController implements ApiController<DocumentManagementApiDefinition> {
4
4
  #private;
5
5
  loadData(context: ApiRequestContext<DocumentManagementApiDefinition, 'loadData'>): Promise<ApiServerResult<DocumentManagementApiDefinition, 'loadData'>>;
6
- loadDataStream(context: ApiRequestContext<DocumentManagementApiDefinition, 'loadDataStream'>): Promise<ApiServerResult<DocumentManagementApiDefinition, 'loadDataStream'>>;
6
+ loadDataStream(context: ApiRequestContext<DocumentManagementApiDefinition, 'loadDataStream'>): ApiServerResult<DocumentManagementApiDefinition, 'loadDataStream'>;
7
7
  loadDocumentRequestsTemplateData(context: ApiRequestContext<DocumentManagementApiDefinition, 'loadDocumentRequestsTemplateData'>): Promise<ApiServerResult<DocumentManagementApiDefinition, 'loadDocumentRequestsTemplateData'>>;
8
8
  loadAvailableCategories(context: ApiRequestContext<DocumentManagementApiDefinition, 'loadAvailableCategories'>): Promise<ApiServerResult<DocumentManagementApiDefinition, 'loadAvailableCategories'>>;
9
9
  loadContent(context: ApiRequestContext<DocumentManagementApiDefinition, 'loadContent'>): Promise<ApiServerResult<DocumentManagementApiDefinition, 'loadContent'>>;
@@ -6,9 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  var _a;
8
8
  var DocumentManagementApiController_1;
9
- import { create as createDiffPatch } from 'jsondiffpatch';
10
9
  import { match, P } from 'ts-pattern';
11
- import { createErrorResponse } from '../../../api/index.js';
12
10
  import { apiController } from '../../../api/server/index.js';
13
11
  import { CancellationSignal } from '../../../cancellation/token.js';
14
12
  import { ForbiddenError, NotImplementedError } from '../../../errors/index.js';
@@ -16,24 +14,11 @@ import { HttpServerResponse } from '../../../http/index.js';
16
14
  import { inject } from '../../../injector/index.js';
17
15
  import { Logger } from '../../../logger/logger.js';
18
16
  import { injectRepository } from '../../../orm/server/repository.js';
19
- import { ServerSentEventsSource } from '../../../sse/server-sent-events-source.js';
20
17
  import { toArray } from '../../../utils/array/index.js';
21
- import { tryIgnoreAsync } from '../../../utils/try-ignore.js';
22
- import { isDefined, isUndefined } from '../../../utils/type-guards.js';
23
18
  import { documentManagementApiDefinition } from '../../api/index.js';
24
19
  import { DocumentManagementAuthorizationService } from '../../authorization/index.js';
25
20
  import { DocumentRequestCollectionAssignment } from '../../models/document-request-collection-assignment.model.js';
26
21
  import { DocumentCategoryTypeService, DocumentFileService, DocumentManagementService, DocumentRequestService, DocumentService, DocumentWorkflowService } from '../services/index.js';
27
- const jsonDiffPatch = createDiffPatch({
28
- omitRemovedValues: true,
29
- arrays: {
30
- detectMove: true,
31
- includeValueOnMove: false,
32
- },
33
- objectHash(item, index) {
34
- return item['id'] ?? String(index);
35
- },
36
- });
37
22
  let DocumentManagementApiController = DocumentManagementApiController_1 = class DocumentManagementApiController {
38
23
  #documentManagementService = inject(DocumentManagementService);
39
24
  #authorizationService = inject(DocumentManagementAuthorizationService);
@@ -56,7 +41,7 @@ let DocumentManagementApiController = DocumentManagementApiController_1 = class
56
41
  }
57
42
  return await this.#documentManagementService.loadData(tenantId, toArray(context.parameters.collectionIds));
58
43
  }
59
- async loadDataStream(context) {
44
+ async *loadDataStream(context) {
60
45
  const token = await context.getToken();
61
46
  const tenantId = await this.#authorizationService.getTenantId(token);
62
47
  for (const collectionId of context.parameters.collectionIds) {
@@ -65,37 +50,7 @@ let DocumentManagementApiController = DocumentManagementApiController_1 = class
65
50
  throw new ForbiddenError(`You are not allowed to read collection ${collectionId}`);
66
51
  }
67
52
  }
68
- const stream = this.#documentManagementService.loadDataStream(tenantId, toArray(context.parameters.collectionIds), this.#cancellationSignal);
69
- const eventSource = new ServerSentEventsSource();
70
- void (async () => {
71
- let lastData;
72
- try {
73
- for await (const data of stream) {
74
- if (eventSource.closed()) {
75
- break;
76
- }
77
- if (isUndefined(lastData)) {
78
- await eventSource.sendJson({ name: 'data', data });
79
- }
80
- else {
81
- const delta = jsonDiffPatch.diff(lastData, data);
82
- if (isDefined(delta)) {
83
- await eventSource.sendJson({ name: 'delta', data: delta });
84
- }
85
- }
86
- lastData = data;
87
- }
88
- }
89
- catch (error) {
90
- this.#logger.error(error);
91
- await tryIgnoreAsync(async () => await eventSource.sendJson({ name: 'error', data: createErrorResponse(error).error }));
92
- await tryIgnoreAsync(async () => await eventSource.close());
93
- }
94
- finally {
95
- await tryIgnoreAsync(async () => await eventSource.close());
96
- }
97
- })();
98
- return eventSource;
53
+ yield* this.#documentManagementService.loadDataStream(tenantId, toArray(context.parameters.collectionIds), this.#cancellationSignal);
99
54
  }
100
55
  async loadDocumentRequestsTemplateData(context) {
101
56
  const token = await context.getToken();
@@ -94,7 +94,7 @@ export declare class DocumentManagementService extends Transactional {
94
94
  * @param documentId The ID of the document to retrieve collection IDs for.
95
95
  */
96
96
  getRelevantDocumentCollectionIds(tenantId: string, documentId: string): Promise<string[]>;
97
- loadDataStream(tenantId: string, collectionIds: string[], cancellationSignal: CancellationSignal): AsyncIterableIterator<DocumentManagementData>;
97
+ loadDataStream(tenantId: string, collectionIds: string[], cancellationSignal: CancellationSignal): AsyncGenerator<DocumentManagementData>;
98
98
  loadData(tenantId: string, collectionIds: string[]): Promise<DocumentManagementData>;
99
99
  loadDocumentRequestsTemplateData(tenantId: string | null): Promise<DocumentRequestsTemplateData>;
100
100
  initializeCategoriesAndTypes<CategoryKey extends string, TypeKey extends string, DocumentPropertyKey extends string>(tenantId: string | null, data: CategoriesAndTypesInitializationData<CategoryKey, TypeKey, DocumentPropertyKey>): Promise<{
@@ -20,10 +20,10 @@ export declare const updateDocumentCollectionsParametersSchema: import("../../sc
20
20
  }>;
21
21
  export declare const createDocumentParametersSchema: import("../../schema/index.js").ObjectSchema<{
22
22
  date?: import("../../orm/types.js").NumericDate | null | undefined;
23
- summary?: string | null | undefined;
24
- title?: string | null | undefined;
25
23
  typeId?: import("../../orm/types.js").Uuid | null | undefined;
24
+ title?: string | null | undefined;
26
25
  subtitle?: string | null | undefined;
26
+ summary?: string | null | undefined;
27
27
  comment?: string | null | undefined;
28
28
  approval?: import("../models/document.model.js").DocumentApproval | undefined;
29
29
  originalFileName?: string | null | undefined;
@@ -53,8 +53,8 @@ export declare const createDocumentParametersSchema: import("../../schema/index.
53
53
  export declare const updateDocumentParametersSchema: import("../../schema/index.js").ObjectSchema<{
54
54
  id: import("../../orm/types.js").IsPrimaryKey<import("../../orm/types.js").HasDefault<import("../../orm/schemas/uuid.js").Uuid>>;
55
55
  date?: import("../../orm/types.js").NumericDate | null | undefined;
56
- title?: string | null | undefined;
57
56
  typeId?: import("../../orm/types.js").Uuid | null | undefined;
57
+ title?: string | null | undefined;
58
58
  subtitle?: string | null | undefined;
59
59
  comment?: string | null | undefined;
60
60
  properties?: {
@@ -97,8 +97,8 @@ export declare const createDocumentRequestsTemplateParametersSchema: import("../
97
97
  export declare const updateDocumentRequestsTemplateParametersSchema: import("../../schema/index.js").ObjectSchema<{
98
98
  id: import("../../orm/types.js").IsPrimaryKey<import("../../orm/types.js").HasDefault<import("../../orm/schemas/uuid.js").Uuid>>;
99
99
  description?: string | null | undefined;
100
- label?: string | undefined;
101
100
  tenantId?: string | null | undefined;
101
+ label?: string | undefined;
102
102
  metadata?: Partial<{
103
103
  attributes: import("../../orm/types.js").HasDefault<import("../../orm/schemas/json.js").Json<import("../../orm/entity.js").EntityMetadataAttributes>>;
104
104
  }> | undefined;
@@ -181,8 +181,8 @@ export declare const setDocumentPropertiesParametersSchema: import("../../schema
181
181
  documentId: string;
182
182
  }>;
183
183
  export declare const createDocumentCategoryParametersSchema: import("../../schema/index.js").ObjectSchema<{
184
- label: string;
185
184
  parentId: import("../../orm/schemas/uuid.js").Uuid | null;
185
+ label: string;
186
186
  metadata?: Partial<{
187
187
  attributes: import("../../orm/types.js").HasDefault<import("../../orm/schemas/json.js").Json<import("../../orm/entity.js").EntityMetadataAttributes>>;
188
188
  }> | undefined;
@@ -212,8 +212,8 @@ export declare const rejectDocumentRequestParametersSchema: import("../../schema
212
212
  }> | undefined;
213
213
  }>;
214
214
  export declare const createDocumentPropertyParametersSchema: import("../../schema/index.js").ObjectSchema<{
215
- label: string;
216
215
  dataType: import("../../orm/types.js").Enum<import("../models/document-property.model.js").DocumentPropertyDataType>;
216
+ label: string;
217
217
  metadata?: Partial<{
218
218
  attributes: import("../../orm/types.js").HasDefault<import("../../orm/schemas/json.js").Json<import("../../orm/entity.js").EntityMetadataAttributes>>;
219
219
  }> | undefined;
@@ -1,4 +1,4 @@
1
- import { type Signal } from '../../signals/api.js';
2
1
  import { type Observable } from 'rxjs';
2
+ import { type Signal } from '../../signals/api.js';
3
3
  export declare function observeResize$(element: Element, options?: ResizeObserverOptions): Observable<ResizeObserverEntry>;
4
4
  export declare function observeResize(elements: Element, options?: ResizeObserverOptions): Signal<ResizeObserverEntry | undefined>;
@@ -1,8 +1,8 @@
1
+ import { Subject, filter, fromEventPattern, map, shareReplay } from 'rxjs';
1
2
  import { IterableWeakMap } from '../../data-structures/iterable-weak-map.js';
2
3
  import { toSignal } from '../../signals/api.js';
3
4
  import { FactoryMap } from '../../utils/factory-map.js';
4
5
  import { isDefined } from '../../utils/type-guards.js';
5
- import { Subject, filter, fromEventPattern, map, shareReplay } from 'rxjs';
6
6
  let observer;
7
7
  let subject;
8
8
  const elementObservablesMap = new FactoryMap(() => ({}), new IterableWeakMap());
@@ -1,7 +1,6 @@
1
1
  import { resolveArgumentType } from '../../injector/index.js';
2
2
  import type { Resolvable } from '../../injector/interfaces.js';
3
- import type { ImageOptions } from '../image-service.js';
4
- import { ImageService } from '../image-service.js';
3
+ import { ImageService, type ImageOptions } from '../image-service.js';
5
4
  export type ImgproxyImageServiceConfig = {
6
5
  endpoint: string;
7
6
  key: string;
@@ -17,7 +17,7 @@ import { concatArrayBufferViews } from '../../utils/binary.js';
17
17
  import { importHmacKey, sign } from '../../utils/cryptography.js';
18
18
  import { decodeHex, encodeUtf8 } from '../../utils/encoding.js';
19
19
  import { isDefined } from '../../utils/type-guards.js';
20
- import { ImageService } from '../image-service.js';
20
+ import { ImageOrigin, ImageService } from '../image-service.js';
21
21
  export const IMGPROXY_IMAGE_SERVICE_CONFIG = injectionToken('ImgproxyImageServiceConfig');
22
22
  let ImgproxyImageService = class ImgproxyImageService extends ImageService {
23
23
  #keyBytes;
@@ -75,16 +75,16 @@ async function signString(keyBytes, saltBytes, target, size = 32) {
75
75
  }
76
76
  function convertOrigin(origin) {
77
77
  switch (origin) {
78
- case 'center': return 'ce';
79
- case 'smart': return 'sm';
80
- case 'top': return 'no';
81
- case 'left': return 'we';
82
- case 'right': return 'ea';
83
- case 'bottom': return 'so';
84
- case 'topleft': return 'nowe';
85
- case 'topright': return 'noea';
86
- case 'bottomleft': return 'sowe';
87
- case 'bottomright': return 'soea';
78
+ case ImageOrigin.Center: return 'ce';
79
+ case ImageOrigin.Smart: return 'sm';
80
+ case ImageOrigin.Top: return 'no';
81
+ case ImageOrigin.Left: return 'we';
82
+ case ImageOrigin.Right: return 'ea';
83
+ case ImageOrigin.Bottom: return 'so';
84
+ case ImageOrigin.TopLeft: return 'nowe';
85
+ case ImageOrigin.TopRight: return 'noea';
86
+ case ImageOrigin.BottomLeft: return 'sowe';
87
+ case ImageOrigin.BottomRight: return 'soea';
88
88
  default: throw new Error();
89
89
  }
90
90
  }
@@ -121,7 +121,7 @@ export declare function createColumnDecorator(data?: OrmColumnReflectionData): P
121
121
  * @param data - The ORM reflection data to add.
122
122
  * @returns A class or property decorator.
123
123
  */
124
- export declare function createTableAndColumnDecorator(data?: OrmColumnReflectionData): PropertyDecorator & ClassDecorator;
124
+ export declare function createTableAndColumnDecorator(data?: OrmColumnReflectionData): ClassDecorator & PropertyDecorator;
125
125
  /**
126
126
  * Decorator to specify ORM column options.
127
127
  * @param options - Column configuration options.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.92.150",
3
+ "version": "0.92.152",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -11,6 +11,7 @@
11
11
  "build:watch": "concurrently --raw --kill-others npm:tsc:watch npm:tsc-alias:watch",
12
12
  "build:production": "rm -rf dist && npm run build && npm run build:production:copy-files",
13
13
  "build:production:copy-files": "cp package.json eslint.config.js tsconfig.server.json dist/ && cp tsconfig.base.json dist/tsconfig.json && npm run copy:orm",
14
+ "build:dts": "tsc -p tsconfig.dts.json",
14
15
  "build:docs": "typedoc",
15
16
  "build:docs:watch": "typedoc --watch",
16
17
  "lint": "eslint --cache source/",
@@ -167,7 +168,7 @@
167
168
  "preact": "^10.27",
168
169
  "preact-render-to-string": "^6.5",
169
170
  "sharp": "^0.34",
170
- "undici": "^7.13",
171
+ "undici": "^7.14",
171
172
  "urlpattern-polyfill": "^10.1"
172
173
  },
173
174
  "peerDependenciesMeta": {
@@ -183,7 +184,7 @@
183
184
  "@types/minio": "7.1",
184
185
  "@types/mjml": "4.7",
185
186
  "@types/node": "24",
186
- "@types/nodemailer": "6.4",
187
+ "@types/nodemailer": "7.0",
187
188
  "@types/pg": "8.15",
188
189
  "concurrently": "9.2",
189
190
  "drizzle-kit": "0.31",
@@ -0,0 +1,18 @@
1
+ import type { AnyIterable } from '../utils/any-iterable-iterator.js';
2
+ import { ServerSentEventsSource } from './server-sent-events-source.js';
3
+ export type DataStreamSourceOptions = {
4
+ /**
5
+ * Whether to send deltas (the changes) between the last and current data or always the full data.
6
+ */
7
+ delta?: boolean;
8
+ };
9
+ export declare class DataStreamSource<T> {
10
+ #private;
11
+ readonly eventSource: ServerSentEventsSource;
12
+ readonly closed: import("../signals/api.js").Signal<boolean>;
13
+ constructor(options?: DataStreamSourceOptions);
14
+ static fromIterable<T>(iterable: AnyIterable<T>, options?: DataStreamSourceOptions): DataStreamSource<T>;
15
+ send(data: T): Promise<void>;
16
+ close(): Promise<void>;
17
+ error(error: unknown): Promise<void>;
18
+ }
@@ -0,0 +1,66 @@
1
+ import { create as createDiffPatch } from 'jsondiffpatch';
2
+ import { createErrorResponse } from '../api/index.js';
3
+ import { tryIgnoreAsync } from '../utils/try-ignore.js';
4
+ import { isDefined } from '../utils/type-guards.js';
5
+ import { ServerSentEventsSource } from './server-sent-events-source.js';
6
+ const jsonDiffPatch = createDiffPatch({
7
+ omitRemovedValues: true,
8
+ arrays: {
9
+ detectMove: true,
10
+ includeValueOnMove: false,
11
+ },
12
+ objectHash(item, index) {
13
+ return item['id'] ?? String(index);
14
+ },
15
+ });
16
+ export class DataStreamSource {
17
+ #options;
18
+ eventSource = new ServerSentEventsSource();
19
+ closed = this.eventSource.closed;
20
+ #lastData;
21
+ constructor(options = { delta: true }) {
22
+ this.#options = options;
23
+ }
24
+ static fromIterable(iterable, options) {
25
+ const source = new DataStreamSource(options);
26
+ void (async () => {
27
+ try {
28
+ for await (const data of iterable) {
29
+ if (source.closed()) {
30
+ break;
31
+ }
32
+ await source.send(data);
33
+ }
34
+ }
35
+ catch (error) {
36
+ await tryIgnoreAsync(async () => await source.error(error));
37
+ }
38
+ finally {
39
+ await tryIgnoreAsync(async () => await source.close());
40
+ }
41
+ })();
42
+ return source;
43
+ }
44
+ async send(data) {
45
+ if (this.eventSource.closed()) {
46
+ throw new Error('Cannot send data to a closed DataStreamSource connection.');
47
+ }
48
+ if (this.#options.delta && isDefined(this.#lastData)) {
49
+ const delta = jsonDiffPatch.diff(this.#lastData, data);
50
+ await this.eventSource.sendJson({ name: 'delta', data: delta });
51
+ }
52
+ else {
53
+ await this.eventSource.sendJson({ name: 'data', data });
54
+ }
55
+ if (this.#options.delta) {
56
+ this.#lastData = data;
57
+ }
58
+ }
59
+ async close() {
60
+ await this.eventSource.close();
61
+ }
62
+ async error(error) {
63
+ await tryIgnoreAsync(async () => await this.eventSource.sendJson({ name: 'error', data: createErrorResponse(error).error }));
64
+ await tryIgnoreAsync(async () => await this.eventSource.close());
65
+ }
66
+ }
@@ -0,0 +1,8 @@
1
+ import { type Observable } from 'rxjs';
2
+ import type { ServerSentEvents } from './server-sent-events.js';
3
+ declare const dataStreamType: unique symbol;
4
+ export declare class DataStream<T> {
5
+ readonly [dataStreamType]?: T;
6
+ static parse<T>(eventSource: ServerSentEvents): Observable<T>;
7
+ }
8
+ export {};
@@ -0,0 +1,15 @@
1
+ import { patch } from 'jsondiffpatch';
2
+ import { hasOwnProperty } from '../utils/object/object.js';
3
+ import { finalize, map, merge, scan } from 'rxjs';
4
+ export class DataStream {
5
+ static parse(eventSource) {
6
+ const data$ = eventSource.message$('data').pipe(map((message) => ({ data: JSON.parse(message.data) })));
7
+ const delta$ = eventSource.message$('delta').pipe(map((message) => ({ delta: JSON.parse(message.data) })));
8
+ return merge(data$, delta$).pipe(scan((data, message) => {
9
+ if (hasOwnProperty(message, 'data')) {
10
+ return message.data;
11
+ }
12
+ return patch(structuredClone(data), message.delta);
13
+ }, undefined), finalize(() => eventSource.close()));
14
+ }
15
+ }
package/sse/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export * from './data-stream-source.js';
2
+ export * from './data-stream.js';
1
3
  export * from './model.js';
2
4
  export * from './server-sent-events-source.js';
3
5
  export * from './server-sent-events.js';
package/sse/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ export * from './data-stream-source.js';
2
+ export * from './data-stream.js';
1
3
  export * from './model.js';
2
4
  export * from './server-sent-events-source.js';
3
5
  export * from './server-sent-events.js';
package/utils/binary.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { BinaryData, Type } from '../types/index.js';
1
+ import type { BinaryData } from '../types/index.js';
2
2
  /**
3
3
  * Get ArrayBuffer from binary data
4
4
  * @param data data to get ArrayBuffer from
@@ -11,6 +11,5 @@ export declare function toArrayBuffer(data: BinaryData, clone?: boolean): ArrayB
11
11
  * @param clone whether to clone buffer or not
12
12
  */
13
13
  export declare function toUint8Array(data: BinaryData, clone?: boolean): Uint8Array;
14
- export declare function concatArrayBuffers(buffers: ArrayBufferLike[]): ArrayBufferLike;
15
- export declare function concatArrayBufferViews<T extends ArrayBufferView>(arrays: T[], totalLength?: number): T;
16
- export declare function concatArrayBufferViews<T extends ArrayBufferView>(arrays: ArrayBufferView[], targetType: Type<T, [ArrayBufferLike, number, number]>, totalLength?: number): T;
14
+ export declare function concatArrayBuffers(buffers: readonly ArrayBufferLike[]): ArrayBuffer;
15
+ export declare function concatArrayBufferViews(arrays: readonly ArrayBufferView[], totalLength?: number): Uint8Array<ArrayBuffer>;
package/utils/binary.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { supportsBuffer } from '../supports.js';
2
- import { typeExtends } from './index.js';
3
- import { assert, isArrayBuffer, isFunction, isNumber } from './type-guards.js';
2
+ import { assert, isArrayBuffer, isUint8Array } from './type-guards.js';
4
3
  /**
5
4
  * Get ArrayBuffer from binary data
6
5
  * @param data data to get ArrayBuffer from
@@ -36,13 +35,10 @@ export function concatArrayBuffers(buffers) {
36
35
  const bytes = concatArrayBufferViews(arrays);
37
36
  return bytes.buffer;
38
37
  }
39
- export function concatArrayBufferViews(arrays, totalLengthOrTargetType, totalLengthOrNothing) {
38
+ export function concatArrayBufferViews(arrays, totalLength) {
40
39
  assert(arrays.length > 0, 'No array provided.');
41
- const totalLength = isNumber(totalLengthOrTargetType) ? totalLengthOrTargetType : totalLengthOrNothing;
42
- const type = isFunction(totalLengthOrTargetType) ? totalLengthOrTargetType : arrays[0].constructor;
43
- if (supportsBuffer && typeExtends(type, Uint8Array)) {
44
- const merged = Buffer.concat(arrays, totalLength);
45
- return new type(merged.buffer, merged.byteOffset, merged.byteLength);
40
+ if (supportsBuffer && arrays.every((array) => isUint8Array(array))) {
41
+ return Buffer.concat(arrays, totalLength);
46
42
  }
47
43
  const totalBytes = totalLength ?? arrays.reduce((sum, array) => sum + array.byteLength, 0);
48
44
  const merged = new Uint8Array(totalBytes);
@@ -52,5 +48,5 @@ export function concatArrayBufferViews(arrays, totalLengthOrTargetType, totalLen
52
48
  merged.set(uint8Array, currentIndex);
53
49
  currentIndex += uint8Array.byteLength;
54
50
  }
55
- return new type(merged.buffer, merged.byteOffset, merged.byteLength);
51
+ return merged;
56
52
  }
package/utils/math.js CHANGED
@@ -1,4 +1,3 @@
1
- import { NotSupportedError } from '../errors/not-supported.error.js';
2
1
  import { defaultRandomNumberGeneratorFn } from '../random/number-generator/random-number-generator-function.js';
3
2
  import { isNull } from './type-guards.js';
4
3
  /**
@@ -44,7 +43,7 @@ export function average(values) {
44
43
  */
45
44
  export function minimum(values) {
46
45
  if (values.length == 0) {
47
- throw new NotSupportedError('No values provided.');
46
+ throw new Error('No values provided.');
48
47
  }
49
48
  return values.reduce((previous, current) => Math.min(previous, current), Number.POSITIVE_INFINITY);
50
49
  }
@@ -55,7 +54,7 @@ export function minimum(values) {
55
54
  */
56
55
  export function maximum(values) {
57
56
  if (values.length == 0) {
58
- throw new NotSupportedError('No values provided.');
57
+ throw new Error('No values provided.');
59
58
  }
60
59
  return values.reduce((previous, current) => Math.max(previous, current), Number.NEGATIVE_INFINITY);
61
60
  }
@@ -6,5 +6,5 @@ export type ReadBinaryStreamOptions = {
6
6
  /** Action if source stream has less bytes than provided length */
7
7
  onLengthSubceed?: 'error' | 'close' | 'leave-open';
8
8
  };
9
- export declare function readBinaryStream(iterableOrStream: AnyIterable<ArrayBufferView> | ReadableStream<ArrayBufferView>, { length, onLengthExceed, onLengthSubceed }?: ReadBinaryStreamOptions): Promise<Uint8Array>;
9
+ export declare function readBinaryStream(iterableOrStream: AnyIterable<ArrayBufferView> | ReadableStream<ArrayBufferView>, { length, onLengthExceed, onLengthSubceed }?: ReadBinaryStreamOptions): Promise<Uint8Array<ArrayBuffer>>;
10
10
  export declare function readTextStream(iterableOrStream: AsyncIterable<string> | ReadableStream<string>): Promise<string>;
@@ -114,7 +114,7 @@ export async function readBinaryStream(iterableOrStream, { length, onLengthExcee
114
114
  if (views.length == 0) {
115
115
  return new Uint8Array(0);
116
116
  }
117
- return concatArrayBufferViews(views, Uint8Array, totalLength);
117
+ return concatArrayBufferViews(views, totalLength);
118
118
  }
119
119
  export async function readTextStream(iterableOrStream) {
120
120
  const iterable = isAsyncIterable(iterableOrStream) ? iterableOrStream : getReadableStreamIterable(iterableOrStream);